diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index dfa31c76efb3fb3b9112034805a9683860a8ce91..0912f905c637724251df74dff3aad2eee72f5ffb 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 80ff0c321e28b2358e9f1c2e77484b732e4abc63..a22156c875318599ffd397bc8468d978cfcf76fd 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 */