From 89144534ebea806704e05769942bd3bebf23d8e4 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Thu, 24 Jun 2010 15:05:16 -0600 Subject: [PATCH] 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. --- src/phyp/phyp_driver.c | 3498 ++++++++++++++++++++-------------------- src/phyp/phyp_driver.h | 75 +- 2 files changed, 1763 insertions(+), 1810 deletions(-) diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index dfa31c76ef..0912f905c6 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -66,477 +66,340 @@ virReportErrorHelper(NULL, VIR_FROM_PHYP, code, __FILE__, __FUNCTION__, \ __LINE__, __VA_ARGS__) -static unsigned const int HMC = 0; -static unsigned const int IVM = 127; - /* * URI: phyp://user@[hmc|ivm]/managed_system * */ -static virDrvOpenStatus -phypOpen(virConnectPtr conn, - virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) -{ - LIBSSH2_SESSION *session = NULL; - ConnectionData *connection_data = NULL; - char *string = NULL; - size_t len = 0; - int internal_socket; - uuid_tablePtr uuid_table = NULL; - phyp_driverPtr phyp_driver = NULL; - char *char_ptr; - char *managed_system = NULL; - - if (!conn || !conn->uri) - return VIR_DRV_OPEN_DECLINED; - - if (conn->uri->scheme == NULL || STRNEQ(conn->uri->scheme, "phyp")) - return VIR_DRV_OPEN_DECLINED; +static unsigned const int HMC = 0; +static unsigned const int IVM = 127; - if (conn->uri->server == NULL) { - PHYP_ERROR(VIR_ERR_INTERNAL_ERROR, - "%s", _("Missing server name in phyp:// URI")); - return VIR_DRV_OPEN_ERROR; - } +static int +waitsocket(int socket_fd, LIBSSH2_SESSION * session) +{ + struct timeval timeout; + int rc; + fd_set fd; + fd_set *writefd = NULL; + fd_set *readfd = NULL; + int dir; - if (VIR_ALLOC(phyp_driver) < 0) { - virReportOOMError(); - goto failure; - } + timeout.tv_sec = 0; + timeout.tv_usec = 1000; - if (VIR_ALLOC(uuid_table) < 0) { - virReportOOMError(); - goto failure; - } + FD_ZERO(&fd); - if (VIR_ALLOC(connection_data) < 0) { - virReportOOMError(); - goto failure; - } + FD_SET(socket_fd, &fd); - if (conn->uri->path) { - len = strlen(conn->uri->path) + 1; + /* now make sure we wait in the correct direction */ + dir = libssh2_session_block_directions(session); - if (VIR_ALLOC_N(string, len) < 0) { - virReportOOMError(); - goto failure; - } + if (dir & LIBSSH2_SESSION_BLOCK_INBOUND) + readfd = &fd; - /* need to shift one byte in order to remove the first "/" of URI component */ - if (conn->uri->path[0] == '/') - managed_system = strdup(conn->uri->path + 1); - else - managed_system = strdup(conn->uri->path); + if (dir & LIBSSH2_SESSION_BLOCK_OUTBOUND) + writefd = &fd; - if (!managed_system) { - virReportOOMError(); - goto failure; - } + rc = select(socket_fd + 1, readfd, writefd, NULL, &timeout); - /* here we are handling only the first component of the path, - * so skipping the second: - * */ - char_ptr = strchr(managed_system, '/'); + return rc; +} - if (char_ptr) - *char_ptr = '\0'; +/* this function is the layer that manipulates the ssh channel itself + * and executes the commands on the remote machine */ +static char * +phypExec(LIBSSH2_SESSION * session, char *cmd, int *exit_status, + 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 (escape_specialcharacters(conn->uri->path, string, len) == -1) { - PHYP_ERROR(VIR_ERR_INTERNAL_ERROR, - "%s", - _("Error parsing 'path'. Invalid characters.")); - goto failure; - } + /* 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 ((session = openSSHSession(conn, auth, &internal_socket)) == NULL) { - PHYP_ERROR(VIR_ERR_INTERNAL_ERROR, - "%s", _("Error while opening SSH session.")); - goto failure; + if (channel == NULL) { + goto err; } - 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; + while ((rc = libssh2_channel_exec(channel, cmd)) == + LIBSSH2_ERROR_EAGAIN) { + waitsocket(sock, session); } - conn->privateData = phyp_driver; - conn->networkPrivateData = connection_data; - - if ((phyp_driver->system_type = phypGetSystemType(conn)) == -1) - goto failure; + if (rc != 0) { + goto err; + } - if (phypUUIDTable_Init(conn) == -1) - goto failure; + 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); - if (phyp_driver->system_type == HMC) { - if ((phyp_driver->vios_id = phypGetVIOSPartitionID(conn)) == -1) - goto failure; + /* 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; + } } - return VIR_DRV_OPEN_SUCCESS; + exitcode = 127; - failure: - if (phyp_driver != NULL) { - virCapabilitiesFree(phyp_driver->caps); - VIR_FREE(phyp_driver->managed_system); - VIR_FREE(phyp_driver); + while ((rc = libssh2_channel_close(channel)) == LIBSSH2_ERROR_EAGAIN) { + waitsocket(sock, session); } - phypUUIDTable_Free(uuid_table); - - if (session != NULL) { - libssh2_session_disconnect(session, "Disconnecting..."); - libssh2_session_free(session); + if (rc == 0) { + exitcode = libssh2_channel_get_exit_status(channel); } - VIR_FREE(connection_data); - VIR_FREE(string); + (*exit_status) = exitcode; + 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 -phypClose(virConnectPtr conn) +phypGetSystemType(virConnectPtr conn) { ConnectionData *connection_data = conn->networkPrivateData; - phyp_driverPtr phyp_driver = conn->privateData; LIBSSH2_SESSION *session = connection_data->session; + char *cmd = NULL; + char *ret = NULL; + int exit_status = 0; - libssh2_session_disconnect(session, "Disconnecting..."); - libssh2_session_free(session); + if (virAsprintf(&cmd, "lshmc -V") < 0) { + virReportOOMError(); + exit_status = -1; + } + ret = phypExec(session, cmd, &exit_status, conn); - 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; + VIR_FREE(cmd); + VIR_FREE(ret); + return exit_status; } - static int -phypIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED) +phypGetVIOSPartitionID(virConnectPtr conn) { - /* Phyp uses an SSH tunnel, so is always encrypted */ - return 1; -} + 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 *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 -phypIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED) -{ - /* Phyp uses an SSH tunnel, so is always secure */ - return 1; -} + ret = phypExec(session, cmd, &exit_status, conn); + if (exit_status < 0 || ret == NULL) + goto err; -LIBSSH2_SESSION * -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(); + if (virStrToLong_i(ret, &char_ptr, 10, &id) == -1) goto err; - } - - if (conn->uri->user != NULL) { - username = strdup(conn->uri->user); - 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; - } + VIR_FREE(cmd); + VIR_FREE(ret); + return id; - username = virRequestUsername(auth, NULL, conn->uri->server); + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; +} - if (username == NULL) { - PHYP_ERROR(VIR_ERR_AUTH_FAILED, "%s", - _("Username request failed")); - goto err; - } - } +static virCapsPtr +phypCapsInit(void) +{ + struct utsname utsname; + virCapsPtr caps; + virCapsGuestPtr guest; - memset(&hints, 0, sizeof(hints)); - hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; + uname(&utsname); - ret = getaddrinfo(hostname, "22", &hints, &ai); - if (ret != 0) { - PHYP_ERROR(VIR_ERR_INTERNAL_ERROR, - _("Error while getting %s address info"), hostname); - goto err; - } + if ((caps = virCapabilitiesNew(utsname.machine, 0, 0)) == NULL) + goto no_memory; - cur = ai; - while (cur != NULL) { - sock = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol); - if (sock >= 0) { - if (connect(sock, cur->ai_addr, cur->ai_addrlen) == 0) { - goto connected; - } - close(sock); - } - cur = cur->ai_next; + /* Some machines have problematic NUMA toplogy causing + * unexpected failures. We don't want to break the QEMU + * driver in this scenario, so log errors & carry on + */ + if (nodeCapsInitNUMA(caps) < 0) { + virCapabilitiesFreeNUMAInfo(caps); + VIR_WARN0 + ("Failed to query host NUMA topology, disabling NUMA capabilities"); } - PHYP_ERROR(VIR_ERR_INTERNAL_ERROR, - _("Failed to connect to %s"), hostname); - freeaddrinfo(ai); - goto err; - - connected: - - (*internal_socket) = sock; - - /* Create a session instance */ - session = libssh2_session_init(); - if (!session) - goto err; - - /* tell libssh2 we want it all done non-blocking */ - libssh2_session_set_blocking(session, 0); + /* XXX shouldn't 'borrow' KVM's prefix */ + virCapabilitiesSetMacPrefix(caps, (unsigned char[]) { + 0x52, 0x54, 0x00}); - 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 ((guest = virCapabilitiesAddGuest(caps, + "linux", + utsname.machine, + sizeof(int) == 4 ? 32 : 8, + NULL, NULL, 0, NULL)) == NULL) + goto no_memory; - /* Trying authentication by pubkey */ - if (stat(pvtkey, &pvt_stat) || stat(pubkey, &pub_stat)) { - rc = LIBSSH2_ERROR_SOCKET_NONE; - goto keyboard_interactive; - } + if (virCapabilitiesAddGuestDomain(guest, + "phyp", NULL, NULL, 0, NULL) == NULL) + goto no_memory; - while ((rc = - libssh2_userauth_publickey_fromfile(session, username, - pubkey, - pvtkey, - NULL)) == - LIBSSH2_ERROR_EAGAIN) ; + return caps; - keyboard_interactive: - if (rc == LIBSSH2_ERROR_SOCKET_NONE - || rc == LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED - || rc == LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED) { - if (auth == NULL || auth->cb == NULL) { - PHYP_ERROR(VIR_ERR_AUTH_FAILED, - "%s", _("No authentication callback provided.")); - goto disconnect; - } + no_memory: + virCapabilitiesFree(caps); + return NULL; +} - password = virRequestPassword(auth, username, conn->uri->server); +/* 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 (password == NULL) { - PHYP_ERROR(VIR_ERR_AUTH_FAILED, "%s", - _("Password request failed")); - goto disconnect; + if (type == 0) + state = "|grep Running"; + else if (type == 1) { + if (system_type == HMC) { + state = "|grep \"Not Activated\""; + } else { + state = "|grep \"Open Firmware\""; } + } else + state = " "; - while ((rc = - libssh2_userauth_password(session, username, - password)) == - LIBSSH2_ERROR_EAGAIN) ; + virBufferAddLit(&buf, "lssyscfg -r lpar"); + if (system_type == HMC) + virBufferVSprintf(&buf, " -m %s", managed_system); + virBufferVSprintf(&buf, " -F lpar_id,state %s |grep -c '^[0-9]*'", + state); + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return -1; + } + cmd = virBufferContentAndReset(&buf); - if (rc) { - PHYP_ERROR(VIR_ERR_AUTH_FAILED, - "%s", _("Authentication failed")); - goto disconnect; - } else - goto exit; + ret = phypExec(session, cmd, &exit_status, conn); - } else if (rc == LIBSSH2_ERROR_NONE) { - goto exit; + if (exit_status < 0 || ret == NULL) + goto err; - } else if (rc == LIBSSH2_ERROR_ALLOC || rc == LIBSSH2_ERROR_SOCKET_SEND - || rc == LIBSSH2_ERROR_SOCKET_TIMEOUT) { + if (virStrToLong_i(ret, &char_ptr, 10, &ndom) == -1) goto err; - } - disconnect: - libssh2_session_disconnect(session, "Disconnecting..."); - libssh2_session_free(session); - err: - VIR_FREE(userhome); - VIR_FREE(pubkey); - VIR_FREE(pvtkey); - VIR_FREE(username); - VIR_FREE(password); - return NULL; + VIR_FREE(cmd); + VIR_FREE(ret); + return ndom; - exit: - VIR_FREE(userhome); - VIR_FREE(pubkey); - VIR_FREE(pvtkey); - VIR_FREE(username); - VIR_FREE(password); - return session; + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; } -/* this functions is the layer that manipulates the ssh channel itself - * and executes the commands on the remote machine */ -static char * -phypExec(LIBSSH2_SESSION * session, char *cmd, int *exit_status, - virConnectPtr conn) +/* This is a generic function that won't be used directly by + * libvirt api. The function returns the ids of domains + * in different states: Running, and all: + * + * type: 0 - Running + * 1 - all + * */ +static int +phypListDomainsGeneric(virConnectPtr conn, int *ids, int nids, + unsigned int type) { - 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; - - /* 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; + 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 lpar_id = 0; + int got = 0; char *char_ptr; + unsigned int i = 0, j = 0; + char id_c[10]; char *cmd = NULL; char *ret = NULL; + const char *state; virBuffer buf = VIR_BUFFER_INITIALIZER; + if (type == 0) + state = "|grep Running"; + else + state = " "; + + memset(id_c, 0, 10); + virBufferAddLit(&buf, "lssyscfg -r lpar"); if (system_type == HMC) 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)) { virBufferFreeAndReset(&buf); virReportOOMError(); @@ -546,15 +409,32 @@ phypGetLparID(LIBSSH2_SESSION * session, const char *managed_system, 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) goto err; - - if (virStrToLong_i(ret, &char_ptr, 10, &lpar_id) == -1) - 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; + } + memset(id_c, 0, 10); + j = 0; + got++; + } else { + id_c[j] = ret[i]; + j++; + } + i++; + } + } VIR_FREE(cmd); VIR_FREE(ret); - return lpar_id; + return got; err: VIR_FREE(cmd); @@ -562,931 +442,863 @@ phypGetLparID(LIBSSH2_SESSION * session, const char *managed_system, return -1; } -/* return the lpar name given a lpar_id and a managed system name */ -static char * -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) +static int +phypUUIDTable_WriteFile(virConnectPtr conn) { phyp_driverPtr phyp_driver = conn->privateData; uuid_tablePtr uuid_table = phyp_driver->uuid_table; - lparPtr *lpars = uuid_table->lpars; unsigned int i = 0; + int fd = -1; + char local_file[] = "./uuid_table"; + + if ((fd = creat(local_file, 0755)) == -1) + goto err; for (i = 0; i < uuid_table->nlpars; i++) { - if (lpars[i]->id == lpar_id) { - memmove(uuid, lpars[i]->uuid, VIR_UUID_BUFLEN); - return 0; + 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; + } + + 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; } -/* - * type: - * 0 - maxmem - * 1 - memory - * */ -unsigned long -phypGetLparMem(virConnectPtr conn, const char *managed_system, int lpar_id, - int type) +static int +phypUUIDTable_Push(virConnectPtr conn) { ConnectionData *connection_data = conn->networkPrivateData; LIBSSH2_SESSION *session = connection_data->session; - phyp_driverPtr phyp_driver = conn->privateData; - int system_type = phyp_driver->system_type; - char *cmd = NULL; - char *ret = NULL; - char *char_ptr; - int memory = 0; - int exit_status = 0; - virBuffer buf = VIR_BUFFER_INITIALIZER; + LIBSSH2_CHANNEL *channel = NULL; + virBuffer username = VIR_BUFFER_INITIALIZER; + struct stat local_fileinfo; + char buffer[1024]; + int rc = 0; + FILE *fd; + size_t nread, sent; + char *ptr; + char local_file[] = "./uuid_table"; + char *remote_file = NULL; - if (type != 1 && type != 0) - return 0; + if (conn->uri->user != NULL) { + virBufferVSprintf(&username, "%s", conn->uri->user); - virBufferAddLit(&buf, "lshwres"); - if (system_type == HMC) - virBufferVSprintf(&buf, " -m %s", managed_system); - virBufferVSprintf(&buf, - " -r mem --level lpar -F %s --filter lpar_ids=%d", - type ? "curr_mem" : "curr_max_mem", lpar_id); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); + if (virBufferError(&username)) { + virBufferFreeAndReset(&username); + virReportOOMError(); + goto err; + } + } + + if (virAsprintf + (&remote_file, "/home/%s/libvirt_uuid_table", + virBufferContentAndReset(&username)) + < 0) { virReportOOMError(); - return 0; + goto err; } - cmd = virBufferContentAndReset(&buf); - ret = phypExec(session, cmd, &exit_status, conn); + if (stat(local_file, &local_fileinfo) == -1) { + VIR_WARN0("Unable to stat local file."); + goto err; + } - if (exit_status < 0 || ret == NULL) + if (!(fd = fopen(local_file, "rb"))) { + VIR_WARN0("Unable to open local file."); goto err; + } - char_ptr = strchr(ret, '\n'); + do { + channel = + libssh2_scp_send(session, remote_file, + 0x1FF & local_fileinfo.st_mode, + (unsigned long) local_fileinfo.st_size); - if (char_ptr) - *char_ptr = '\0'; + if ((!channel) && (libssh2_session_last_errno(session) != + LIBSSH2_ERROR_EAGAIN)) + goto err; + } while (!channel); - if (virStrToLong_i(ret, &char_ptr, 10, &memory) == -1) - goto err; + do { + 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; + } + } + ptr = buffer; + sent = 0; - VIR_FREE(cmd); - VIR_FREE(ret); - return memory; + 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); - err: - VIR_FREE(cmd); - VIR_FREE(ret); + 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 -phypGetLparCPU(virConnectPtr conn, const char *managed_system, int lpar_id) -{ - return phypGetLparCPUGeneric(conn, managed_system, lpar_id, 0); + err: + if (channel) { + libssh2_channel_send_eof(channel); + libssh2_channel_wait_eof(channel); + libssh2_channel_wait_closed(channel); + libssh2_channel_free(channel); + channel = NULL; + } + return -1; } static int -phypGetLparCPUMAX(virDomainPtr dom) -{ - phyp_driverPtr phyp_driver = dom->conn->privateData; - char *managed_system = phyp_driver->managed_system; - - return phypGetLparCPUGeneric(dom->conn, managed_system, dom->id, 1); -} - -unsigned long -phypGetLparCPUGeneric(virConnectPtr conn, const char *managed_system, - int lpar_id, int type) +phypUUIDTable_RemLpar(virConnectPtr conn, int id) { - ConnectionData *connection_data = conn->networkPrivateData; - LIBSSH2_SESSION *session = connection_data->session; phyp_driverPtr phyp_driver = conn->privateData; - int system_type = phyp_driver->system_type; - char *cmd = NULL; - char *ret = NULL; - char *char_ptr; - int exit_status = 0; - int vcpus = 0; - virBuffer buf = VIR_BUFFER_INITIALIZER; + uuid_tablePtr uuid_table = phyp_driver->uuid_table; + unsigned int i = 0; - virBufferAddLit(&buf, "lshwres"); - if (system_type == HMC) - virBufferVSprintf(&buf, " -m %s", managed_system); - 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; + for (i = 0; i <= uuid_table->nlpars; i++) { + if (uuid_table->lpars[i]->id == id) { + uuid_table->lpars[i]->id = -1; + memset(uuid_table->lpars[i]->uuid, 0, VIR_UUID_BUFLEN); + } } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); - if (exit_status < 0 || ret == NULL) + if (phypUUIDTable_WriteFile(conn) == -1) goto err; - char_ptr = strchr(ret, '\n'); - - if (char_ptr) - *char_ptr = '\0'; - - if (virStrToLong_i(ret, &char_ptr, 10, &vcpus) == -1) + if (phypUUIDTable_Push(conn) == -1) goto err; - VIR_FREE(cmd); - VIR_FREE(ret); - return (unsigned long) vcpus; + return 0; err: - VIR_FREE(cmd); - VIR_FREE(ret); - return 0; + return -1; } -int -phypGetRemoteSlot(virConnectPtr conn, const char *managed_system, - const char *lpar_name) +static int +phypUUIDTable_AddLpar(virConnectPtr conn, unsigned char *uuid, int id) { - ConnectionData *connection_data = conn->networkPrivateData; - LIBSSH2_SESSION *session = connection_data->session; 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; + uuid_tablePtr uuid_table = phyp_driver->uuid_table; - 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); + uuid_table->nlpars++; + unsigned int i = uuid_table->nlpars; + i--; + + if (VIR_REALLOC_N(uuid_table->lpars, uuid_table->nlpars) < 0) { 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; + } - char_ptr = strchr(ret, '\n'); + uuid_table->lpars[i]->id = id; + memmove(uuid_table->lpars[i]->uuid, uuid, VIR_UUID_BUFLEN); - if (char_ptr) - *char_ptr = '\0'; + if (phypUUIDTable_WriteFile(conn) == -1) + goto err; - if (virStrToLong_i(ret, &char_ptr, 10, &remote_slot) == -1) + if (phypUUIDTable_Push(conn) == -1) goto err; - VIR_FREE(cmd); - VIR_FREE(ret); - return remote_slot; + return 0; err: - VIR_FREE(cmd); - VIR_FREE(ret); return -1; } -char * -phypGetBackingDevice(virConnectPtr conn, const char *managed_system, - char *lpar_name) +static int +phypUUIDTable_ReadFile(virConnectPtr conn) { - ConnectionData *connection_data = conn->networkPrivateData; - LIBSSH2_SESSION *session = connection_data->session; phyp_driverPtr phyp_driver = conn->privateData; - int system_type = phyp_driver->system_type; - char *cmd = NULL; - char *ret = NULL; - int remote_slot = 0; - int exit_status = 0; - char *char_ptr; - char *backing_device = NULL; - virBuffer buf = VIR_BUFFER_INITIALIZER; - - if ((remote_slot = - phypGetRemoteSlot(conn, managed_system, lpar_name)) == -1) - return NULL; + uuid_tablePtr uuid_table = phyp_driver->uuid_table; + unsigned int i = 0; + int fd = -1; + char local_file[] = "./uuid_table"; + int rc = 0; + int id; - virBufferAddLit(&buf, "lshwres"); - if (system_type == HMC) - virBufferVSprintf(&buf, " -m %s", managed_system); - virBufferVSprintf(&buf, " -r virtualio --rsubtype scsi -F " - "backing_devices --filter slots=%d", remote_slot); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return NULL; + if ((fd = open(local_file, O_RDONLY)) == -1) { + VIR_WARN0("Unable to write information to local file."); + goto err; } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); - if (exit_status < 0 || ret == NULL) - goto err; + /* Creating a new data base and writing to local file */ + if (VIR_ALLOC_N(uuid_table->lpars, uuid_table->nlpars) >= 0) { + for (i = 0; i < uuid_table->nlpars; i++) { - /* 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); + 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; + } - if (backing_device == NULL) { - virReportOOMError(); - goto err; + rc = read(fd, uuid_table->lpars[i]->uuid, VIR_UUID_BUFLEN); + if (rc != VIR_UUID_BUFLEN) { + VIR_WARN0("Unable to read information to local file."); + goto err; + } } - } else { - backing_device = ret; - ret = NULL; - } - - char_ptr = strchr(backing_device, '\n'); - - if (char_ptr) - *char_ptr = '\0'; + } else + virReportOOMError(); - VIR_FREE(cmd); - VIR_FREE(ret); - return backing_device; + close(fd); + return 0; err: - VIR_FREE(cmd); - VIR_FREE(ret); - return NULL; - + close(fd); + return -1; } -int -phypGetLparState(virConnectPtr conn, unsigned int lpar_id) +static int +phypUUIDTable_Pull(virConnectPtr conn) { 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 *cmd = NULL; - char *ret = NULL; - 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; + LIBSSH2_CHANNEL *channel = NULL; + virBuffer username = VIR_BUFFER_INITIALIZER; + struct stat fileinfo; + char buffer[1024]; + int rc = 0; + int fd; + int got = 0; + int amount = 0; + int total = 0; + int sock = 0; + char local_file[] = "./uuid_table"; + char *remote_file = NULL; - virBufferAddLit(&buf, "lssyscfg -r lpar"); - if (system_type == HMC) - virBufferVSprintf(&buf, " -m %s", managed_system); - virBufferVSprintf(&buf, " -F state --filter lpar_ids=%d", lpar_id); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return state; - } - cmd = virBufferContentAndReset(&buf); + if (conn->uri->user != NULL) { + virBufferVSprintf(&username, "%s", conn->uri->user); - ret = phypExec(session, cmd, &exit_status, conn); + if (virBufferError(&username)) { + virBufferFreeAndReset(&username); + virReportOOMError(); + goto err; + } + } - if (exit_status < 0 || ret == NULL) - goto cleanup; + if (virAsprintf + (&remote_file, "/home/%s/libvirt_uuid_table", + virBufferContentAndReset(&username)) + < 0) { + virReportOOMError(); + goto err; + } - char_ptr = strchr(ret, '\n'); + /* Trying to stat the remote file. */ + do { + channel = libssh2_scp_recv(session, remote_file, &fileinfo); - if (char_ptr) - *char_ptr = '\0'; + if (!channel) { + if (libssh2_session_last_errno(session) != + LIBSSH2_ERROR_EAGAIN) { + goto err;; + } else { + waitsocket(sock, session); + } + } + } while (!channel); - 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; + /* Creating a new data base based on remote file */ + if ((fd = creat(local_file, 0755)) == -1) + goto err; - cleanup: - VIR_FREE(cmd); - VIR_FREE(ret); - return state; -} + /* Request a file via SCP */ + while (got < fileinfo.st_size) { + do { + amount = sizeof(buffer); -int -phypGetVIOSPartitionID(virConnectPtr conn) -{ - 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 *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; + if ((fileinfo.st_size - got) < amount) { + amount = fileinfo.st_size - got; + } - 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); + rc = libssh2_channel_read(channel, buffer, amount); + if (rc > 0) { + if (safewrite(fd, buffer, rc) != rc) + VIR_WARN0 + ("Unable to write information to local file."); - ret = phypExec(session, cmd, &exit_status, conn); + got += rc; + total += rc; + } + } while (rc > 0); - if (exit_status < 0 || ret == NULL) - goto err; + if ((rc == LIBSSH2_ERROR_EAGAIN) + && (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) - goto err; + waitsocket(sock, session); /* now we wait */ + continue; + } + break; + } + close(fd); + goto exit; - VIR_FREE(cmd); - VIR_FREE(ret); - return id; + exit: + 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; err: - VIR_FREE(cmd); - VIR_FREE(ret); + if (channel) { + libssh2_channel_send_eof(channel); + libssh2_channel_wait_eof(channel); + libssh2_channel_wait_closed(channel); + libssh2_channel_free(channel); + channel = NULL; + } return -1; } -int -phypDiskType(virConnectPtr conn, char *backing_device) +static int +phypUUIDTable_Init(virConnectPtr conn) { - phyp_driverPtr phyp_driver = conn->privateData; - ConnectionData *connection_data = conn->networkPrivateData; - 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; + uuid_tablePtr uuid_table; + phyp_driverPtr phyp_driver; + int nids_numdomains = 0; + int nids_listdomains = 0; + int *ids = NULL; + unsigned int i = 0; - virBufferAddLit(&buf, "viosvrcmd"); - if (system_type == HMC) - virBufferVSprintf(&buf, " -m %s", managed_system); - 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); + if ((nids_numdomains = phypNumDomainsGeneric(conn, 2)) < 0) + goto err; + + if (VIR_ALLOC_N(ids, nids_numdomains) < 0) { virReportOOMError(); - return disk_type; + goto err; } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); - if (exit_status < 0 || ret == NULL) - goto cleanup; + if ((nids_listdomains = + phypListDomainsGeneric(conn, ids, nids_numdomains, 1)) < 0) + goto err; - char_ptr = strchr(ret, '\n'); - - if (char_ptr) - *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; + /* 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; + } - cleanup: - VIR_FREE(cmd); - VIR_FREE(ret); - return disk_type; -} + phyp_driver = conn->privateData; + uuid_table = phyp_driver->uuid_table; + uuid_table->nlpars = nids_listdomains; -/* 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; + /* 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; + } + uuid_table->lpars[i]->id = ids[i]; - if (type == 0) - state = "|grep Running"; - else if (type == 1) { - if (system_type == HMC) { - state = "|grep \"Not Activated\""; + if (virUUIDGenerate(uuid_table->lpars[i]->uuid) < 0) + VIR_WARN("Unable to generate UUID for domain %d", + ids[i]); + } } else { - state = "|grep \"Open Firmware\""; + virReportOOMError(); + goto err; } - } else - state = " "; - - virBufferAddLit(&buf, "lssyscfg -r lpar"); - if (system_type == HMC) - virBufferVSprintf(&buf, " -m %s", managed_system); - virBufferVSprintf(&buf, " -F lpar_id,state %s |grep -c '^[0-9]*'", - state); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return -1; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); - if (exit_status < 0 || ret == NULL) - goto err; + if (phypUUIDTable_WriteFile(conn) == -1) + goto err; - if (virStrToLong_i(ret, &char_ptr, 10, &ndom) == -1) - goto err; + if (phypUUIDTable_Push(conn) == -1) + goto err; + } else { + if (phypUUIDTable_ReadFile(conn) == -1) + goto err; + goto exit; + } - VIR_FREE(cmd); - VIR_FREE(ret); - return ndom; + exit: + VIR_FREE(ids); + return 0; err: - VIR_FREE(cmd); - VIR_FREE(ret); + VIR_FREE(ids); return -1; } -static int -phypNumDefinedDomains(virConnectPtr conn) +static void +phypUUIDTable_Free(uuid_tablePtr uuid_table) { - return phypNumDomainsGeneric(conn, 1); -} + int i; -static int -phypNumDomains(virConnectPtr conn) -{ - return phypNumDomainsGeneric(conn, 0); + 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); } -/* This is a generic function that won't be used directly by - * libvirt api. The function returns the ids of domains - * in different states: Running, and all: - * - * type: 0 - Running - * 1 - all - * */ static int -phypListDomainsGeneric(virConnectPtr conn, int *ids, int nids, - unsigned int type) +escape_specialcharacters(char *src, char *dst, size_t dstlen) { - 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; - char *char_ptr; + size_t len = strlen(src); + char temp_buffer[len]; unsigned int i = 0, j = 0; - char id_c[10]; - char *cmd = NULL; - char *ret = NULL; - const char *state; - virBuffer buf = VIR_BUFFER_INITIALIZER; - - if (type == 0) - state = "|grep Running"; - else - state = " "; - - memset(id_c, 0, 10); - - virBufferAddLit(&buf, "lssyscfg -r lpar"); - 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(); + if (len == 0) return -1; - } - cmd = virBufferContentAndReset(&buf); - - 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) - 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; - } - memset(id_c, 0, 10); - j = 0; - got++; - } else { - id_c[j] = ret[i]; + 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++; - } - i++; } } + temp_buffer[j] = '\0'; - VIR_FREE(cmd); - VIR_FREE(ret); - return got; + if (virStrcpy(dst, temp_buffer, dstlen) == NULL) + return -1; - err: - VIR_FREE(cmd); - VIR_FREE(ret); - return -1; + return 0; } -static int -phypListDomains(virConnectPtr conn, int *ids, int nids) +static LIBSSH2_SESSION * +openSSHSession(virConnectPtr conn, virConnectAuthPtr auth, + int *internal_socket) { - return phypListDomainsGeneric(conn, ids, nids, 0); -} + 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; -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; + if (userhome == NULL) + goto err; - 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); + if (virAsprintf(&pubkey, "%s/.ssh/id_rsa.pub", userhome) < 0) { virReportOOMError(); - return -1; + goto err; } - 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) + if (virAsprintf(&pvtkey, "%s/.ssh/id_rsa", userhome) < 0) { + virReportOOMError(); goto err; - else { - domains = ret; - - 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: - for (i = 0; i < got; i++) - VIR_FREE(names[i]); - VIR_FREE(cmd); - VIR_FREE(ret); - return -1; -} + if (conn->uri->user != NULL) { + username = strdup(conn->uri->user); -static virDomainPtr -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]; + 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; + } - lpar_id = phypGetLparID(session, managed_system, lpar_name, conn); - if (lpar_id == -1) - return NULL; + username = virRequestUsername(auth, NULL, conn->uri->server); - if (phypGetLparUUID(lpar_uuid, lpar_id, conn) == -1) - return NULL; + if (username == NULL) { + PHYP_ERROR(VIR_ERR_AUTH_FAILED, "%s", + _("Username request failed")); + goto err; + } + } - dom = virGetDomain(conn, lpar_name, lpar_uuid); + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; - if (dom) - dom->id = lpar_id; + ret = getaddrinfo(hostname, "22", &hints, &ai); + if (ret != 0) { + PHYP_ERROR(VIR_ERR_INTERNAL_ERROR, + _("Error while getting %s address info"), hostname); + goto err; + } - return dom; -} + cur = ai; + while (cur != NULL) { + sock = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol); + if (sock >= 0) { + if (connect(sock, cur->ai_addr, cur->ai_addrlen) == 0) { + goto connected; + } + close(sock); + } + cur = cur->ai_next; + } -static virDomainPtr -phypDomainLookupByID(virConnectPtr conn, int lpar_id) -{ - ConnectionData *connection_data = conn->networkPrivateData; - phyp_driverPtr phyp_driver = conn->privateData; - LIBSSH2_SESSION *session = connection_data->session; - virDomainPtr dom = NULL; - char *managed_system = phyp_driver->managed_system; - int exit_status = 0; - unsigned char lpar_uuid[VIR_UUID_BUFLEN]; + PHYP_ERROR(VIR_ERR_INTERNAL_ERROR, + _("Failed to connect to %s"), hostname); + freeaddrinfo(ai); + goto err; - char *lpar_name = phypGetLparNAME(session, managed_system, lpar_id, - conn); + connected: - if (phypGetLparUUID(lpar_uuid, lpar_id, conn) == -1) - goto err; + (*internal_socket) = sock; - if (exit_status < 0) + /* Create a session instance */ + session = libssh2_session_init(); + if (!session) goto err; - dom = virGetDomain(conn, lpar_name, lpar_uuid); - - if (dom) - dom->id = lpar_id; - - VIR_FREE(lpar_name); - return dom; + /* tell libssh2 we want it all done non-blocking */ + libssh2_session_set_blocking(session, 0); - err: - VIR_FREE(lpar_name); - return NULL; -} + 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; + } -static char * -phypDomainDumpXML(virDomainPtr dom, int flags) -{ - ConnectionData *connection_data = dom->conn->networkPrivateData; - phyp_driverPtr phyp_driver = dom->conn->privateData; - LIBSSH2_SESSION *session = connection_data->session; - virDomainDef def; - char *managed_system = phyp_driver->managed_system; + /* Trying authentication by pubkey */ + if (stat(pvtkey, &pvt_stat) || stat(pubkey, &pub_stat)) { + rc = LIBSSH2_ERROR_SOCKET_NONE; + goto keyboard_interactive; + } - memset(&def, 0, sizeof(virDomainDef)); + while ((rc = + libssh2_userauth_publickey_fromfile(session, username, + pubkey, + pvtkey, + NULL)) == + LIBSSH2_ERROR_EAGAIN) ; - def.virtType = VIR_DOMAIN_VIRT_PHYP; - def.id = dom->id; + keyboard_interactive: + if (rc == LIBSSH2_ERROR_SOCKET_NONE + || rc == LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED + || rc == LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED) { + if (auth == NULL || auth->cb == NULL) { + PHYP_ERROR(VIR_ERR_AUTH_FAILED, + "%s", _("No authentication callback provided.")); + goto disconnect; + } - char *lpar_name = phypGetLparNAME(session, managed_system, def.id, - dom->conn); + password = virRequestPassword(auth, username, conn->uri->server); - if (lpar_name == NULL) { - VIR_ERROR0(_("Unable to determine domain's name.")); - goto err; - } + if (password == NULL) { + PHYP_ERROR(VIR_ERR_AUTH_FAILED, "%s", + _("Password request failed")); + goto disconnect; + } - if (phypGetLparUUID(def.uuid, dom->id, dom->conn) == -1) { - VIR_ERROR0(_("Unable to generate random uuid.")); - goto err; - } + while ((rc = + libssh2_userauth_password(session, username, + password)) == + LIBSSH2_ERROR_EAGAIN) ; - if ((def.maxmem = - phypGetLparMem(dom->conn, managed_system, dom->id, 0)) == 0) { - VIR_ERROR0(_("Unable to determine domain's max memory.")); - goto err; - } + if (rc) { + PHYP_ERROR(VIR_ERR_AUTH_FAILED, + "%s", _("Authentication failed")); + goto disconnect; + } else + goto exit; - if ((def.memory = - phypGetLparMem(dom->conn, managed_system, dom->id, 1)) == 0) { - VIR_ERROR0(_("Unable to determine domain's memory.")); - goto err; - } + } else if (rc == LIBSSH2_ERROR_NONE) { + goto exit; - if ((def.vcpus = - phypGetLparCPU(dom->conn, managed_system, dom->id)) == 0) { - VIR_ERROR0(_("Unable to determine domain's CPU.")); + } else if (rc == LIBSSH2_ERROR_ALLOC || rc == LIBSSH2_ERROR_SOCKET_SEND + || rc == LIBSSH2_ERROR_SOCKET_TIMEOUT) { goto err; } - return virDomainDefFormat(&def, flags); - + disconnect: + libssh2_session_disconnect(session, "Disconnecting..."); + libssh2_session_free(session); err: + VIR_FREE(userhome); + VIR_FREE(pubkey); + VIR_FREE(pvtkey); + VIR_FREE(username); + VIR_FREE(password); return NULL; + + exit: + VIR_FREE(userhome); + VIR_FREE(pubkey); + VIR_FREE(pvtkey); + VIR_FREE(username); + VIR_FREE(password); + return session; } -static int -phypDomainResume(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; +static virDrvOpenStatus +phypOpen(virConnectPtr conn, + virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) +{ + LIBSSH2_SESSION *session = NULL; + ConnectionData *connection_data = NULL; + char *string = NULL; + size_t len = 0; + int internal_socket; + uuid_tablePtr uuid_table = NULL; + phyp_driverPtr phyp_driver = NULL; + char *char_ptr; + char *managed_system = NULL; - virBufferAddLit(&buf, "chsysstate"); - 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); + if (!conn || !conn->uri) + return VIR_DRV_OPEN_DECLINED; + + if (conn->uri->scheme == NULL || STRNEQ(conn->uri->scheme, "phyp")) + return VIR_DRV_OPEN_DECLINED; + + if (conn->uri->server == NULL) { + PHYP_ERROR(VIR_ERR_INTERNAL_ERROR, + "%s", _("Missing server name in phyp:// URI")); + return VIR_DRV_OPEN_ERROR; + } + + if (VIR_ALLOC(phyp_driver) < 0) { virReportOOMError(); - return -1; + goto failure; } - cmd = virBufferContentAndReset(&buf); - ret = phypExec(session, cmd, &exit_status, dom->conn); + if (VIR_ALLOC(uuid_table) < 0) { + virReportOOMError(); + goto failure; + } - if (exit_status < 0) - goto err; + if (VIR_ALLOC(connection_data) < 0) { + virReportOOMError(); + goto failure; + } - VIR_FREE(cmd); - VIR_FREE(ret); - return 0; + if (conn->uri->path) { + len = strlen(conn->uri->path) + 1; - err: - VIR_FREE(cmd); - VIR_FREE(ret); - return -1; -} + if (VIR_ALLOC_N(string, len) < 0) { + virReportOOMError(); + goto failure; + } -static int -phypDomainShutdown(virDomainPtr dom) -{ - ConnectionData *connection_data = dom->conn->networkPrivateData; - virConnectPtr conn = dom->conn; - LIBSSH2_SESSION *session = connection_data->session; - phyp_driverPtr phyp_driver = conn->privateData; - 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; + /* need to shift one byte in order to remove the first "/" of URI component */ + if (conn->uri->path[0] == '/') + managed_system = strdup(conn->uri->path + 1); + else + managed_system = strdup(conn->uri->path); - virBufferAddLit(&buf, "chsysstate"); - 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); + 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(); - return 0; + goto failure; } - cmd = virBufferContentAndReset(&buf); - ret = phypExec(session, cmd, &exit_status, dom->conn); + conn->privateData = phyp_driver; + conn->networkPrivateData = connection_data; - if (exit_status < 0) - goto err; + if ((phyp_driver->system_type = phypGetSystemType(conn)) == -1) + goto failure; - VIR_FREE(cmd); - VIR_FREE(ret); - return 0; + if (phypUUIDTable_Init(conn) == -1) + goto failure; - err: - VIR_FREE(cmd); - VIR_FREE(ret); - return 0; + 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 -phypDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) +phypClose(virConnectPtr conn) { - phyp_driverPtr phyp_driver = dom->conn->privateData; - char *managed_system = phyp_driver->managed_system; + ConnectionData *connection_data = conn->networkPrivateData; + phyp_driverPtr phyp_driver = conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; - info->state = phypGetLparState(dom->conn, dom->id); + libssh2_session_disconnect(session, "Disconnecting..."); + libssh2_session_free(session); - if ((info->maxMem = - phypGetLparMem(dom->conn, managed_system, dom->id, 0)) == 0) - VIR_WARN0("Unable to determine domain's max memory."); + 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; +} - 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."); +static int +phypIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED) +{ + /* Phyp uses an SSH tunnel, so is always encrypted */ + return 1; +} - return 0; + +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 -phypDomainDestroy(virDomainPtr dom) +phypGetLparID(LIBSSH2_SESSION * session, const char *managed_system, + const char *name, virConnectPtr conn) { - ConnectionData *connection_data = dom->conn->networkPrivateData; - phyp_driverPtr phyp_driver = dom->conn->privateData; - LIBSSH2_SESSION *session = connection_data->session; + phyp_driverPtr phyp_driver = conn->privateData; int system_type = phyp_driver->system_type; - char *managed_system = phyp_driver->managed_system; int exit_status = 0; + int lpar_id = 0; + char *char_ptr; char *cmd = NULL; char *ret = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; - virBufferAddLit(&buf, "rmsyscfg"); + virBufferAddLit(&buf, "lssyscfg -r lpar"); if (system_type == HMC) virBufferVSprintf(&buf, " -m %s", managed_system); - virBufferVSprintf(&buf, " -r lpar --id %d", dom->id); + virBufferVSprintf(&buf, " --filter lpar_names=%s -F lpar_id", name); if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); @@ -1494,174 +1306,172 @@ phypDomainDestroy(virDomainPtr dom) } 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 (phypUUIDTable_RemLpar(dom->conn, dom->id) == -1) + if (virStrToLong_i(ret, &char_ptr, 10, &lpar_id) == -1) goto err; VIR_FREE(cmd); VIR_FREE(ret); - return 0; + return lpar_id; err: VIR_FREE(cmd); VIR_FREE(ret); return -1; - } -static virDomainPtr -phypDomainCreateAndStart(virConnectPtr conn, - const char *xml, unsigned int flags) +/* return the lpar name given a lpar_id and a managed system name */ +static char * +phypGetLparNAME(LIBSSH2_SESSION * session, const char *managed_system, + unsigned int lpar_id, virConnectPtr conn) { - - ConnectionData *connection_data = conn->networkPrivateData; - LIBSSH2_SESSION *session = connection_data->session; - virDomainDefPtr def = NULL; - virDomainPtr dom = NULL; phyp_driverPtr phyp_driver = conn->privateData; - uuid_tablePtr uuid_table = phyp_driver->uuid_table; - lparPtr *lpars = uuid_table->lpars; - unsigned int i = 0; - char *managed_system = phyp_driver->managed_system; - - virCheckFlags(0, NULL); - - if (!(def = virDomainDefParseString(phyp_driver->caps, xml, - VIR_DOMAIN_XML_SECURE))) - goto err; + int system_type = phyp_driver->system_type; + char *cmd = NULL; + char *ret = NULL; + int exit_status = 0; + virBuffer buf = VIR_BUFFER_INITIALIZER; - /* checking if this name already exists on this system */ - if (phypGetLparID(session, managed_system, def->name, conn) == -1) { - VIR_WARN0("LPAR name already exists."); - goto err; + 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); - /* checking if ID or UUID already exists on this system */ - for (i = 0; i < uuid_table->nlpars; i++) { - if (lpars[i]->id == def->id || lpars[i]->uuid == def->uuid) { - VIR_WARN0("LPAR ID or UUID already exists."); - goto err; - } - } + ret = phypExec(session, cmd, &exit_status, conn); - if ((dom = virGetDomain(conn, def->name, def->uuid)) == NULL) + if (exit_status < 0 || ret == NULL) goto err; - if (phypBuildLpar(conn, def) == -1) - goto err; + char *char_ptr = strchr(ret, '\n'); - if (phypDomainResume(dom) == -1) - goto err; + if (char_ptr) + *char_ptr = '\0'; - return dom; + VIR_FREE(cmd); + return ret; err: - virDomainDefFree(def); - if (dom) - virUnrefDomain(dom); + VIR_FREE(cmd); + VIR_FREE(ret); return NULL; } -static char * -phypConnectGetCapabilities(virConnectPtr conn) + +/* 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 +phypGetLparUUID(unsigned char *uuid, int lpar_id, virConnectPtr conn) { phyp_driverPtr phyp_driver = conn->privateData; - char *xml; + uuid_tablePtr uuid_table = phyp_driver->uuid_table; + lparPtr *lpars = uuid_table->lpars; + unsigned int i = 0; - if ((xml = virCapabilitiesFormatXML(phyp_driver->caps)) == NULL) - virReportOOMError(); + 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 xml; + return -1; } -virCapsPtr -phypCapsInit(void) +/* + * type: + * 0 - maxmem + * 1 - memory + * */ +static unsigned long +phypGetLparMem(virConnectPtr conn, const char *managed_system, int lpar_id, + int type) { - struct utsname utsname; - virCapsPtr caps; - virCapsGuestPtr guest; - - uname(&utsname); + ConnectionData *connection_data = conn->networkPrivateData; + LIBSSH2_SESSION *session = connection_data->session; + phyp_driverPtr phyp_driver = conn->privateData; + int system_type = phyp_driver->system_type; + char *cmd = NULL; + char *ret = NULL; + char *char_ptr; + int memory = 0; + int exit_status = 0; + virBuffer buf = VIR_BUFFER_INITIALIZER; - if ((caps = virCapabilitiesNew(utsname.machine, 0, 0)) == NULL) - goto no_memory; + if (type != 1 && type != 0) + return 0; - /* Some machines have problematic NUMA toplogy causing - * unexpected failures. We don't want to break the QEMU - * driver in this scenario, so log errors & carry on - */ - if (nodeCapsInitNUMA(caps) < 0) { - virCapabilitiesFreeNUMAInfo(caps); - VIR_WARN0 - ("Failed to query host NUMA topology, disabling NUMA capabilities"); + virBufferAddLit(&buf, "lshwres"); + if (system_type == HMC) + virBufferVSprintf(&buf, " -m %s", managed_system); + virBufferVSprintf(&buf, + " -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); - /* XXX shouldn't 'borrow' KVM's prefix */ - virCapabilitiesSetMacPrefix(caps, (unsigned char[]) { - 0x52, 0x54, 0x00}); + ret = phypExec(session, cmd, &exit_status, conn); - if ((guest = virCapabilitiesAddGuest(caps, - "linux", - utsname.machine, - sizeof(int) == 4 ? 32 : 8, - NULL, NULL, 0, NULL)) == NULL) - goto no_memory; + if (exit_status < 0 || ret == NULL) + goto err; - if (virCapabilitiesAddGuestDomain(guest, - "phyp", NULL, NULL, 0, NULL) == NULL) - goto no_memory; + char_ptr = strchr(ret, '\n'); - return caps; + if (char_ptr) + *char_ptr = '\0'; + + if (virStrToLong_i(ret, &char_ptr, 10, &memory) == -1) + goto err; + + VIR_FREE(cmd); + VIR_FREE(ret); + return memory; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return 0; - no_memory: - virCapabilitiesFree(caps); - return NULL; } -static int -phypDomainSetCPU(virDomainPtr dom, unsigned int nvcpus) +static unsigned long +phypGetLparCPUGeneric(virConnectPtr conn, const char *managed_system, + int lpar_id, int type) { - ConnectionData *connection_data = dom->conn->networkPrivateData; - phyp_driverPtr phyp_driver = dom->conn->privateData; + ConnectionData *connection_data = conn->networkPrivateData; LIBSSH2_SESSION *session = connection_data->session; + phyp_driverPtr phyp_driver = conn->privateData; int system_type = phyp_driver->system_type; - char *managed_system = phyp_driver->managed_system; - int exit_status = 0; char *cmd = NULL; char *ret = NULL; - char operation; - unsigned long ncpus = 0; - unsigned int amount = 0; + char *char_ptr; + int exit_status = 0; + int vcpus = 0; virBuffer buf = VIR_BUFFER_INITIALIZER; - if ((ncpus = phypGetLparCPU(dom->conn, managed_system, dom->id)) == 0) - return 0; - - 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) 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); + 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(); @@ -1669,139 +1479,64 @@ phypDomainSetCPU(virDomainPtr dom, unsigned int nvcpus) } cmd = virBufferContentAndReset(&buf); - ret = phypExec(session, cmd, &exit_status, dom->conn); + ret = phypExec(session, cmd, &exit_status, conn); - if (exit_status < 0) { - VIR_ERROR0(_ - ("Possibly you don't have IBM Tools installed in your LPAR." - " Contact your support to enable this feature.")); - } + if (exit_status < 0 || ret == NULL) + goto err; + + char_ptr = strchr(ret, '\n'); + + if (char_ptr) + *char_ptr = '\0'; + + if (virStrToLong_i(ret, &char_ptr, 10, &vcpus) == -1) + goto err; + + VIR_FREE(cmd); + VIR_FREE(ret); + return (unsigned long) vcpus; + err: VIR_FREE(cmd); VIR_FREE(ret); return 0; +} +static unsigned long +phypGetLparCPU(virConnectPtr conn, const char *managed_system, int lpar_id) +{ + return phypGetLparCPUGeneric(conn, managed_system, lpar_id, 0); } -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 */ -}; +static int +phypGetLparCPUMAX(virDomainPtr dom) +{ + phyp_driverPtr phyp_driver = dom->conn->privateData; + char *managed_system = phyp_driver->managed_system; -int -phypBuildLpar(virConnectPtr conn, virDomainDefPtr def) + return phypGetLparCPUGeneric(dom->conn, managed_system, dom->id, 1); +} + +static int +phypGetRemoteSlot(virConnectPtr conn, const char *managed_system, + const char *lpar_name) { ConnectionData *connection_data = conn->networkPrivateData; - phyp_driverPtr phyp_driver = conn->privateData; LIBSSH2_SESSION *session = connection_data->session; + phyp_driverPtr phyp_driver = conn->privateData; int system_type = phyp_driver->system_type; - char *managed_system = phyp_driver->managed_system; char *cmd = NULL; char *ret = NULL; + char *char_ptr; + int remote_slot = 0; int exit_status = 0; virBuffer buf = VIR_BUFFER_INITIALIZER; - virBufferAddLit(&buf, "mksyscfg"); + virBufferAddLit(&buf, "lshwres"); 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); + virBufferVSprintf(&buf, " -r virtualio --rsubtype scsi -F " + "remote_slot_num --filter lpar_names=%s", lpar_name); if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); @@ -1811,19 +1546,20 @@ phypBuildLpar(virConnectPtr conn, virDomainDefPtr def) ret = phypExec(session, cmd, &exit_status, conn); - if (exit_status < 0) { - VIR_ERROR(_("Unable to create LPAR. Reason: '%s'"), ret); + if (exit_status < 0 || ret == NULL) goto err; - } - if (phypUUIDTable_AddLpar(conn, def->uuid, def->id) == -1) { - VIR_ERROR0(_("Unable to add LPAR to the table")); + char_ptr = strchr(ret, '\n'); + + if (char_ptr) + *char_ptr = '\0'; + + if (virStrToLong_i(ret, &char_ptr, 10, &remote_slot) == -1) goto err; - } VIR_FREE(cmd); VIR_FREE(ret); - return 0; + return remote_slot; err: VIR_FREE(cmd); @@ -1831,535 +1567,803 @@ phypBuildLpar(virConnectPtr conn, virDomainDefPtr def) return -1; } -int -phypUUIDTable_RemLpar(virConnectPtr conn, int id) +/* XXX - is this needed? */ +static char *phypGetBackingDevice(virConnectPtr, const char *, char *) + ATTRIBUTE_UNUSED; +static char * +phypGetBackingDevice(virConnectPtr conn, const char *managed_system, + char *lpar_name) { + ConnectionData *connection_data = conn->networkPrivateData; + LIBSSH2_SESSION *session = connection_data->session; phyp_driverPtr phyp_driver = conn->privateData; - uuid_tablePtr uuid_table = phyp_driver->uuid_table; - unsigned int i = 0; + int system_type = phyp_driver->system_type; + char *cmd = NULL; + char *ret = NULL; + int remote_slot = 0; + int exit_status = 0; + char *char_ptr; + char *backing_device = NULL; + virBuffer buf = VIR_BUFFER_INITIALIZER; - for (i = 0; i <= uuid_table->nlpars; i++) { - if (uuid_table->lpars[i]->id == id) { - uuid_table->lpars[i]->id = -1; - memset(uuid_table->lpars[i]->uuid, 0, VIR_UUID_BUFLEN); - } + if ((remote_slot = + phypGetRemoteSlot(conn, managed_system, lpar_name)) == -1) + return NULL; + + virBufferAddLit(&buf, "lshwres"); + if (system_type == HMC) + virBufferVSprintf(&buf, " -m %s", managed_system); + 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); - if (phypUUIDTable_WriteFile(conn) == -1) - goto err; + ret = phypExec(session, cmd, &exit_status, conn); - if (phypUUIDTable_Push(conn) == -1) + if (exit_status < 0 || ret == NULL) goto err; - return 0; + /* 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(ret); + return backing_device; err: - return -1; + VIR_FREE(cmd); + VIR_FREE(ret); + return NULL; + } -int -phypUUIDTable_AddLpar(virConnectPtr conn, unsigned char *uuid, int id) +static int +phypGetLparState(virConnectPtr conn, unsigned int lpar_id) { + ConnectionData *connection_data = conn->networkPrivateData; phyp_driverPtr phyp_driver = conn->privateData; - uuid_tablePtr uuid_table = phyp_driver->uuid_table; - - uuid_table->nlpars++; - unsigned int i = uuid_table->nlpars; - i--; + 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 = NULL; + char *managed_system = phyp_driver->managed_system; + int state = VIR_DOMAIN_NOSTATE; + virBuffer buf = VIR_BUFFER_INITIALIZER; - if (VIR_REALLOC_N(uuid_table->lpars, uuid_table->nlpars) < 0) { + virBufferAddLit(&buf, "lssyscfg -r lpar"); + if (system_type == HMC) + virBufferVSprintf(&buf, " -m %s", managed_system); + virBufferVSprintf(&buf, " -F state --filter lpar_ids=%d", lpar_id); + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); virReportOOMError(); - goto err; + return state; } + cmd = virBufferContentAndReset(&buf); - if (VIR_ALLOC(uuid_table->lpars[i]) < 0) { - virReportOOMError(); - goto err; - } + ret = phypExec(session, cmd, &exit_status, conn); - uuid_table->lpars[i]->id = id; - memmove(uuid_table->lpars[i]->uuid, uuid, VIR_UUID_BUFLEN); + if (exit_status < 0 || ret == NULL) + goto cleanup; - if (phypUUIDTable_WriteFile(conn) == -1) - goto err; + char_ptr = strchr(ret, '\n'); - if (phypUUIDTable_Push(conn) == -1) - goto err; + if (char_ptr) + *char_ptr = '\0'; - return 0; + 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; - err: - return -1; + cleanup: + VIR_FREE(cmd); + VIR_FREE(ret); + return state; } -int -phypUUIDTable_ReadFile(virConnectPtr conn) +/* XXX - is this needed? */ +static int phypDiskType(virConnectPtr, char *) ATTRIBUTE_UNUSED; +static int +phypDiskType(virConnectPtr conn, char *backing_device) { phyp_driverPtr phyp_driver = conn->privateData; - uuid_tablePtr uuid_table = phyp_driver->uuid_table; - unsigned int i = 0; - int fd = -1; - char local_file[] = "./uuid_table"; - int rc = 0; - 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 */ - if (VIR_ALLOC_N(uuid_table->lpars, uuid_table->nlpars) >= 0) { - for (i = 0; i < uuid_table->nlpars; i++) { - - 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; - } + ConnectionData *connection_data = conn->networkPrivateData; + 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; - rc = read(fd, uuid_table->lpars[i]->uuid, VIR_UUID_BUFLEN); - if (rc != VIR_UUID_BUFLEN) { - VIR_WARN0("Unable to read information to local file."); - goto err; - } - } - } else + virBufferAddLit(&buf, "viosvrcmd"); + if (system_type == HMC) + virBufferVSprintf(&buf, " -m %s", managed_system); + 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); - close(fd); - return 0; + ret = phypExec(session, cmd, &exit_status, conn); - err: - close(fd); - return -1; -} + if (exit_status < 0 || ret == NULL) + goto cleanup; -int -phypUUIDTable_WriteFile(virConnectPtr conn) -{ - phyp_driverPtr phyp_driver = conn->privateData; - uuid_tablePtr uuid_table = phyp_driver->uuid_table; - unsigned int i = 0; - int fd = -1; - char local_file[] = "./uuid_table"; + char_ptr = strchr(ret, '\n'); - if ((fd = creat(local_file, 0755)) == -1) - goto err; + if (char_ptr) + *char_ptr = '\0'; - for (i = 0; i < uuid_table->nlpars; i++) { - if (safewrite(fd, &uuid_table->lpars[i]->id, - sizeof(uuid_table->lpars[i]->id)) != - sizeof(uuid_table->lpars[i]->id)) { - VIR_ERROR0(_("Unable to write information to local file.")); - goto err; - } + if (STREQ(ret, "LVPOOL")) + disk_type = VIR_DOMAIN_DISK_TYPE_BLOCK; + else if (STREQ(ret, "FBPOOL")) + disk_type = VIR_DOMAIN_DISK_TYPE_FILE; - 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; - } - } + cleanup: + VIR_FREE(cmd); + VIR_FREE(ret); + return disk_type; +} - close(fd); - return 0; +static int +phypNumDefinedDomains(virConnectPtr conn) +{ + return phypNumDomainsGeneric(conn, 1); +} - err: - close(fd); - return -1; +static int +phypNumDomains(virConnectPtr conn) +{ + return phypNumDomainsGeneric(conn, 0); } -int -phypUUIDTable_Init(virConnectPtr conn) +static int +phypListDomains(virConnectPtr conn, int *ids, int nids) { - uuid_tablePtr uuid_table; - phyp_driverPtr phyp_driver; - int nids_numdomains = 0; - int nids_listdomains = 0; - int *ids = NULL; - unsigned int i = 0; + return phypListDomainsGeneric(conn, ids, nids, 0); +} - if ((nids_numdomains = phypNumDomainsGeneric(conn, 2)) < 0) - goto err; +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; - if (VIR_ALLOC_N(ids, nids_numdomains) < 0) { + 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(); - goto err; + return -1; } + cmd = virBufferContentAndReset(&buf); - if ((nids_listdomains = - phypListDomainsGeneric(conn, ids, nids_numdomains, 1)) < 0) - goto err; + ret = phypExec(session, cmd, &exit_status, conn); - /* 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.")); + /* I need to parse the textual return in order to get the domains */ + if (exit_status < 0 || ret == NULL) goto err; - } + else { + domains = ret; - phyp_driver = conn->privateData; - uuid_table = phyp_driver->uuid_table; - uuid_table->nlpars = nids_listdomains; + while (got < nnames) { + char_ptr2 = strchr(domains, '\n'); - /* 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) { + if (char_ptr2) { + *char_ptr2 = '\0'; + if ((names[got++] = strdup(domains)) == NULL) { virReportOOMError(); goto err; } - uuid_table->lpars[i]->id = ids[i]; - - if (virUUIDGenerate(uuid_table->lpars[i]->uuid) < 0) - VIR_WARN("Unable to generate UUID for domain %d", - ids[i]); - } - } else { - virReportOOMError(); - goto err; + char_ptr2++; + domains = char_ptr2; + } else + break; } - - if (phypUUIDTable_WriteFile(conn) == -1) - goto err; - - if (phypUUIDTable_Push(conn) == -1) - goto err; - } else { - if (phypUUIDTable_ReadFile(conn) == -1) - goto err; - goto exit; } - exit: - VIR_FREE(ids); - return 0; + VIR_FREE(cmd); + VIR_FREE(ret); + return got; err: - VIR_FREE(ids); + for (i = 0; i < got; i++) + VIR_FREE(names[i]); + VIR_FREE(cmd); + VIR_FREE(ret); return -1; } -void -phypUUIDTable_Free(uuid_tablePtr uuid_table) +static virDomainPtr +phypDomainLookupByName(virConnectPtr conn, const char *lpar_name) { - int i; + 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]; - if (uuid_table == NULL) - return; + lpar_id = phypGetLparID(session, managed_system, lpar_name, conn); + if (lpar_id == -1) + return NULL; - for (i = 0; i < uuid_table->nlpars; i++) - VIR_FREE(uuid_table->lpars[i]); + if (phypGetLparUUID(lpar_uuid, lpar_id, conn) == -1) + return NULL; - VIR_FREE(uuid_table->lpars); - VIR_FREE(uuid_table); + dom = virGetDomain(conn, lpar_name, lpar_uuid); + + if (dom) + dom->id = lpar_id; + + return dom; } -int -phypUUIDTable_Push(virConnectPtr conn) +static virDomainPtr +phypDomainLookupByID(virConnectPtr conn, int lpar_id) { ConnectionData *connection_data = conn->networkPrivateData; + phyp_driverPtr phyp_driver = conn->privateData; LIBSSH2_SESSION *session = connection_data->session; - LIBSSH2_CHANNEL *channel = NULL; - virBuffer username = VIR_BUFFER_INITIALIZER; - struct stat local_fileinfo; - char buffer[1024]; - int rc = 0; - FILE *fd; - size_t nread, sent; - char *ptr; - char local_file[] = "./uuid_table"; - char *remote_file = NULL; + virDomainPtr dom = NULL; + char *managed_system = phyp_driver->managed_system; + int exit_status = 0; + unsigned char lpar_uuid[VIR_UUID_BUFLEN]; - if (conn->uri->user != NULL) { - virBufferVSprintf(&username, "%s", conn->uri->user); - - if (virBufferError(&username)) { - virBufferFreeAndReset(&username); - virReportOOMError(); - goto err; - } - } - - if (virAsprintf - (&remote_file, "/home/%s/libvirt_uuid_table", - virBufferContentAndReset(&username)) - < 0) { - virReportOOMError(); - goto err; - } + char *lpar_name = phypGetLparNAME(session, managed_system, lpar_id, + conn); - if (stat(local_file, &local_fileinfo) == -1) { - VIR_WARN0("Unable to stat local file."); + if (phypGetLparUUID(lpar_uuid, lpar_id, conn) == -1) goto err; - } - if (!(fd = fopen(local_file, "rb"))) { - VIR_WARN0("Unable to open local file."); + if (exit_status < 0) goto err; - } - - do { - 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) != - LIBSSH2_ERROR_EAGAIN)) - goto err; - } while (!channel); - do { - 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; - } - } - ptr = buffer; - sent = 0; + dom = virGetDomain(conn, lpar_name, lpar_uuid); - 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 (dom) + dom->id = lpar_id; - 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; + VIR_FREE(lpar_name); + return dom; err: - if (channel) { - libssh2_channel_send_eof(channel); - libssh2_channel_wait_eof(channel); - libssh2_channel_wait_closed(channel); - libssh2_channel_free(channel); - channel = NULL; - } - return -1; + VIR_FREE(lpar_name); + return NULL; } -int -phypUUIDTable_Pull(virConnectPtr conn) +static char * +phypDomainDumpXML(virDomainPtr dom, int flags) { - ConnectionData *connection_data = conn->networkPrivateData; + ConnectionData *connection_data = dom->conn->networkPrivateData; + phyp_driverPtr phyp_driver = dom->conn->privateData; LIBSSH2_SESSION *session = connection_data->session; - LIBSSH2_CHANNEL *channel = NULL; - virBuffer username = VIR_BUFFER_INITIALIZER; - struct stat fileinfo; - char buffer[1024]; - int rc = 0; - int fd; - int got = 0; - int amount = 0; - int total = 0; - int sock = 0; - char local_file[] = "./uuid_table"; - char *remote_file = NULL; + virDomainDef def; + char *managed_system = phyp_driver->managed_system; - if (conn->uri->user != NULL) { - virBufferVSprintf(&username, "%s", conn->uri->user); + memset(&def, 0, sizeof(virDomainDef)); - if (virBufferError(&username)) { - virBufferFreeAndReset(&username); - virReportOOMError(); - goto err; - } + def.virtType = VIR_DOMAIN_VIRT_PHYP; + def.id = dom->id; + + char *lpar_name = phypGetLparNAME(session, managed_system, def.id, + dom->conn); + + if (lpar_name == NULL) { + VIR_ERROR0(_("Unable to determine domain's name.")); + goto err; } - if (virAsprintf - (&remote_file, "/home/%s/libvirt_uuid_table", - virBufferContentAndReset(&username)) - < 0) { - virReportOOMError(); + if (phypGetLparUUID(def.uuid, dom->id, dom->conn) == -1) { + VIR_ERROR0(_("Unable to generate random uuid.")); goto err; } - /* Trying to stat the remote file. */ - do { - channel = libssh2_scp_recv(session, remote_file, &fileinfo); + if ((def.maxmem = + phypGetLparMem(dom->conn, managed_system, dom->id, 0)) == 0) { + VIR_ERROR0(_("Unable to determine domain's max memory.")); + goto err; + } - if (!channel) { - if (libssh2_session_last_errno(session) != - LIBSSH2_ERROR_EAGAIN) { - goto err;; - } else { - waitsocket(sock, session); - } - } - } while (!channel); + if ((def.memory = + phypGetLparMem(dom->conn, managed_system, dom->id, 1)) == 0) { + VIR_ERROR0(_("Unable to determine domain's memory.")); + goto err; + } - /* Creating a new data base based on remote file */ - if ((fd = creat(local_file, 0755)) == -1) + if ((def.vcpus = + phypGetLparCPU(dom->conn, managed_system, dom->id)) == 0) { + VIR_ERROR0(_("Unable to determine domain's CPU.")); goto err; + } - /* Request a file via SCP */ - while (got < fileinfo.st_size) { - do { - amount = sizeof(buffer); + return virDomainDefFormat(&def, flags); - if ((fileinfo.st_size - got) < amount) { - amount = fileinfo.st_size - got; - } + err: + return NULL; +} - rc = libssh2_channel_read(channel, buffer, amount); - if (rc > 0) { - if (safewrite(fd, buffer, rc) != rc) - VIR_WARN0 - ("Unable to write information to local file."); +static int +phypDomainResume(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; - got += rc; - total += rc; - } - } while (rc > 0); + virBufferAddLit(&buf, "chsysstate"); + 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); - if ((rc == LIBSSH2_ERROR_EAGAIN) - && (got < fileinfo.st_size)) { - /* this is due to blocking that would occur otherwise - * so we loop on this condition */ + ret = phypExec(session, cmd, &exit_status, dom->conn); - waitsocket(sock, session); /* now we wait */ - continue; - } - break; - } - close(fd); - goto exit; + if (exit_status < 0) + goto err; - exit: - 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); + VIR_FREE(cmd); + VIR_FREE(ret); return 0; err: - if (channel) { - libssh2_channel_send_eof(channel); - libssh2_channel_wait_eof(channel); - libssh2_channel_wait_closed(channel); - libssh2_channel_free(channel); - channel = NULL; - } + VIR_FREE(cmd); + VIR_FREE(ret); return -1; } -int -escape_specialcharacters(char *src, char *dst, size_t dstlen) +static int +phypDomainShutdown(virDomainPtr dom) { - 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++; - } + ConnectionData *connection_data = dom->conn->networkPrivateData; + virConnectPtr conn = dom->conn; + LIBSSH2_SESSION *session = connection_data->session; + phyp_driverPtr phyp_driver = conn->privateData; + 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, "chsysstate"); + 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(); + return 0; } - temp_buffer[j] = '\0'; + cmd = virBufferContentAndReset(&buf); - if (virStrcpy(dst, temp_buffer, dstlen) == NULL) + ret = phypExec(session, cmd, &exit_status, dom->conn); + + if (exit_status < 0) + goto err; + + VIR_FREE(cmd); + VIR_FREE(ret); + 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); + + ret = phypExec(session, cmd, &exit_status, dom->conn); + + if (exit_status < 0) + goto err; + + if (phypUUIDTable_RemLpar(dom->conn, dom->id) == -1) + goto err; + VIR_FREE(cmd); + VIR_FREE(ret); return 0; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; + } -int -waitsocket(int socket_fd, LIBSSH2_SESSION * session) +static int +phypBuildLpar(virConnectPtr conn, virDomainDefPtr def) { - struct timeval timeout; - int rc; - fd_set fd; - fd_set *writefd = NULL; - fd_set *readfd = NULL; - int dir; + 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; + char *cmd = NULL; + char *ret = NULL; + int exit_status = 0; + virBuffer buf = VIR_BUFFER_INITIALIZER; - timeout.tv_sec = 0; - timeout.tv_usec = 1000; + virBufferAddLit(&buf, "mksyscfg"); + 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(); + return -1; + } + cmd = virBufferContentAndReset(&buf); - FD_ZERO(&fd); + ret = phypExec(session, cmd, &exit_status, conn); - FD_SET(socket_fd, &fd); + if (exit_status < 0) { + VIR_ERROR(_("Unable to create LPAR. Reason: '%s'"), ret); + goto err; + } - /* now make sure we wait in the correct direction */ - dir = libssh2_session_block_directions(session); + if (phypUUIDTable_AddLpar(conn, def->uuid, def->id) == -1) { + VIR_ERROR0(_("Unable to add LPAR to the table")); + goto err; + } - if (dir & LIBSSH2_SESSION_BLOCK_INBOUND) - readfd = &fd; + VIR_FREE(cmd); + VIR_FREE(ret); + return 0; - if (dir & LIBSSH2_SESSION_BLOCK_OUTBOUND) - writefd = &fd; + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; +} - rc = select(socket_fd + 1, readfd, writefd, NULL, &timeout); +static virDomainPtr +phypDomainCreateAndStart(virConnectPtr conn, + const char *xml, unsigned int flags) +{ + + ConnectionData *connection_data = conn->networkPrivateData; + LIBSSH2_SESSION *session = connection_data->session; + virDomainDefPtr def = NULL; + virDomainPtr dom = NULL; + phyp_driverPtr phyp_driver = conn->privateData; + uuid_tablePtr uuid_table = phyp_driver->uuid_table; + lparPtr *lpars = uuid_table->lpars; + unsigned int i = 0; + char *managed_system = phyp_driver->managed_system; + + virCheckFlags(0, NULL); + + if (!(def = virDomainDefParseString(phyp_driver->caps, xml, + VIR_DOMAIN_XML_SECURE))) + goto err; + + /* checking if this name already exists on this system */ + if (phypGetLparID(session, managed_system, def->name, conn) == -1) { + VIR_WARN0("LPAR name already exists."); + goto err; + } + + /* checking if ID or UUID already exists on this system */ + for (i = 0; i < uuid_table->nlpars; i++) { + if (lpars[i]->id == def->id || lpars[i]->uuid == def->uuid) { + VIR_WARN0("LPAR ID or UUID already exists."); + goto err; + } + } + + if ((dom = virGetDomain(conn, def->name, def->uuid)) == NULL) + goto err; + + if (phypBuildLpar(conn, def) == -1) + goto err; + + if (phypDomainResume(dom) == -1) + goto err; + + return dom; + + err: + virDomainDefFree(def); + if (dom) + virUnrefDomain(dom); + return NULL; +} + +static char * +phypConnectGetCapabilities(virConnectPtr conn) +{ + phyp_driverPtr phyp_driver = conn->privateData; + char *xml; + + if ((xml = virCapabilitiesFormatXML(phyp_driver->caps)) == NULL) + virReportOOMError(); + + return xml; +} + +static int +phypDomainSetCPU(virDomainPtr dom, unsigned int nvcpus) +{ + ConnectionData *connection_data = dom->conn->networkPrivateData; + phyp_driverPtr phyp_driver = dom->conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + int system_type = phyp_driver->system_type; + char *managed_system = phyp_driver->managed_system; + 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; + + if ((ncpus = phypGetLparCPU(dom->conn, managed_system, dom->id)) == 0) + return 0; + + 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"); + 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); + + ret = phypExec(session, cmd, &exit_status, dom->conn); + + if (exit_status < 0) { + VIR_ERROR0(_ + ("Possibly you don't have IBM Tools installed in your LPAR." + " Contact your support to enable this feature.")); + } + + 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 phypRegister(void) { diff --git a/src/phyp/phyp_driver.h b/src/phyp/phyp_driver.h index 80ff0c321e..a22156c875 100644 --- a/src/phyp/phyp_driver.h +++ b/src/phyp/phyp_driver.h @@ -1,5 +1,5 @@ - /* + * Copyright (C) 2010 Red Hat, Inc. * Copyright IBM Corp. 2009 * * phyp_driver.c: ssh layer to access Power Hypervisors @@ -22,14 +22,17 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "conf/capabilities.h" -#include "conf/domain_conf.h" -#include -#include +#ifndef PHYP_DRIVER_H +# define PHYP_DRIVER_H + +# include "conf/capabilities.h" +# include "conf/domain_conf.h" +# include +# include -#define LPAR_EXEC_ERR -1 -#define SSH_CONN_ERR -2 /* error while trying to connect to remote host */ -#define SSH_CMD_ERR -3 /* error while trying to execute the remote cmd */ +# define LPAR_EXEC_ERR -1 +# define SSH_CONN_ERR -2 /* error while trying to connect to remote host */ +# define SSH_CMD_ERR -3 /* error while trying to execute the remote cmd */ typedef struct _ConnectionData ConnectionData; typedef ConnectionData *ConnectionDataPtr; @@ -75,60 +78,6 @@ struct _phyp_driver { 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 phypGetLparState(virConnectPtr conn, unsigned int lpar_id); - -unsigned long phypGetLparMem(virConnectPtr conn, - const char *managed_system, int lpar_id, - int type); - -unsigned long phypGetLparCPU(virConnectPtr conn, - const char *managed_system, int lpar_id); - -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); +#endif /* PHYP_DRIVER_H */ -- GitLab