I am moving all the UUID handling functions to phyp_uuid.[ch] files in order not to bloat the main files phyp_driver.[ch] too much. Doing this for two reasons:
1) Network management in pHyp does not have a UUID. 2) Need to create another set of functions to manage it. I also modified some functions to support two types of execution: DOMAIN and NET, so I can re-use the base common functions. --- po/POTFILES.in | 1 + src/Makefile.am | 3 +- src/phyp/phyp_driver.c | 464 +--------------------------------- src/phyp/phyp_driver.h | 41 +++ src/phyp/phyp_uuid.c | 657 ++++++++++++++++++++++++++++++++++++++++++++++++ src/phyp/phyp_uuid.h | 36 +++ 6 files changed, 742 insertions(+), 460 deletions(-) create mode 100644 src/phyp/phyp_uuid.c create mode 100644 src/phyp/phyp_uuid.h diff --git a/po/POTFILES.in b/po/POTFILES.in index 2820ac1..e892d0b 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -50,6 +50,7 @@ src/opennebula/one_driver.c src/openvz/openvz_conf.c src/openvz/openvz_driver.c src/phyp/phyp_driver.c +src/phyp/phyp_uuid.c src/qemu/qemu_bridge_filter.c src/qemu/qemu_conf.c src/qemu/qemu_driver.c diff --git a/src/Makefile.am b/src/Makefile.am index a9a1986..608b913 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -248,7 +248,8 @@ SECURITY_DRIVER_APPARMOR_HELPER_SOURCES = \ security/virt-aa-helper.c PHYP_DRIVER_SOURCES = \ - phyp/phyp_driver.c phyp/phyp_driver.h + phyp/phyp_driver.c phyp/phyp_driver.h \ + phyp/phyp_uuid.c phyp/phyp_uuid.h OPENVZ_DRIVER_SOURCES = \ openvz/openvz_conf.c openvz/openvz_conf.h \ diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 4c723a2..6f3f49d 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -59,8 +59,10 @@ #include "storage_conf.h" #include "nodeinfo.h" #include "files.h" +#include "network_conf.h" #include "phyp_driver.h" +#include "phyp_uuid.h" #define VIR_FROM_THIS VIR_FROM_PHYP @@ -75,7 +77,7 @@ static unsigned const int HMC = 0; static unsigned const int IVM = 127; -static int +int waitsocket(int socket_fd, LIBSSH2_SESSION * session) { struct timeval timeout; @@ -307,7 +309,7 @@ phypCapsInit(void) * 1 - Not Activated * * - All * */ -static int +int phypNumDomainsGeneric(virConnectPtr conn, unsigned int type) { ConnectionData *connection_data = conn->networkPrivateData; @@ -371,7 +373,7 @@ phypNumDomainsGeneric(virConnectPtr conn, unsigned int type) * type: 0 - Running * 1 - all * */ -static int +int phypListDomainsGeneric(virConnectPtr conn, int *ids, int nids, unsigned int type) { @@ -432,462 +434,6 @@ phypListDomainsGeneric(virConnectPtr conn, int *ids, int nids, } static int -phypUUIDTable_WriteFile(virConnectPtr conn) -{ - phyp_driverPtr phyp_driver = conn->privateData; - uuid_tablePtr uuid_table = phyp_driver->uuid_table; - unsigned int i = 0; - int fd = -1; - char local_file[] = "./uuid_table"; - - if ((fd = creat(local_file, 0755)) == -1) - goto err; - - for (i = 0; i < uuid_table->nlpars; i++) { - if (safewrite(fd, &uuid_table->lpars[i]->id, - sizeof(uuid_table->lpars[i]->id)) != - sizeof(uuid_table->lpars[i]->id)) { - VIR_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; - } - } - - if (VIR_CLOSE(fd) < 0) { - virReportSystemError(errno, _("Could not close %s"), - local_file); - goto err; - } - return 0; - - err: - VIR_FORCE_CLOSE(fd); - return -1; -} - -static int -phypUUIDTable_Push(virConnectPtr conn) -{ - ConnectionData *connection_data = conn->networkPrivateData; - 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; - - 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; - } - - if (stat(local_file, &local_fileinfo) == -1) { - VIR_WARN0("Unable to stat local file."); - goto err; - } - - if (!(fd = fopen(local_file, "rb"))) { - VIR_WARN0("Unable to open local file."); - 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; - - do { - /* write the same data over and over, until error or completion */ - rc = libssh2_channel_write(channel, ptr, nread); - if (LIBSSH2_ERROR_EAGAIN == rc) { /* must loop around */ - continue; - } else if (rc > 0) { - /* rc indicates how many bytes were written this time */ - sent += rc; - } - ptr += sent; - nread -= sent; - } while (rc > 0 && sent < nread); - } while (1); - - if (channel) { - 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: - 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 -phypUUIDTable_RemLpar(virConnectPtr conn, int id) -{ - phyp_driverPtr phyp_driver = conn->privateData; - uuid_tablePtr uuid_table = phyp_driver->uuid_table; - unsigned int i = 0; - - for (i = 0; i <= uuid_table->nlpars; i++) { - if (uuid_table->lpars[i]->id == id) { - uuid_table->lpars[i]->id = -1; - memset(uuid_table->lpars[i]->uuid, 0, VIR_UUID_BUFLEN); - } - } - - if (phypUUIDTable_WriteFile(conn) == -1) - goto err; - - if (phypUUIDTable_Push(conn) == -1) - goto err; - - return 0; - - err: - return -1; -} - -static int -phypUUIDTable_AddLpar(virConnectPtr conn, unsigned char *uuid, int id) -{ - phyp_driverPtr phyp_driver = conn->privateData; - uuid_tablePtr uuid_table = phyp_driver->uuid_table; - - uuid_table->nlpars++; - unsigned int i = uuid_table->nlpars; - i--; - - if (VIR_REALLOC_N(uuid_table->lpars, uuid_table->nlpars) < 0) { - virReportOOMError(); - goto err; - } - - if (VIR_ALLOC(uuid_table->lpars[i]) < 0) { - virReportOOMError(); - goto err; - } - - uuid_table->lpars[i]->id = id; - memmove(uuid_table->lpars[i]->uuid, uuid, VIR_UUID_BUFLEN); - - if (phypUUIDTable_WriteFile(conn) == -1) - goto err; - - if (phypUUIDTable_Push(conn) == -1) - goto err; - - return 0; - - err: - return -1; -} - -static int -phypUUIDTable_ReadFile(virConnectPtr conn) -{ - phyp_driverPtr phyp_driver = conn->privateData; - uuid_tablePtr uuid_table = phyp_driver->uuid_table; - unsigned int i = 0; - int fd = -1; - char local_file[] = "./uuid_table"; - int rc = 0; - 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; - } - - 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 - virReportOOMError(); - - VIR_FORCE_CLOSE(fd); - return 0; - - err: - VIR_FORCE_CLOSE(fd); - return -1; -} - -static int -phypUUIDTable_Pull(virConnectPtr conn) -{ - ConnectionData *connection_data = conn->networkPrivateData; - 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; - - 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; - } - - /* Trying to stat the remote file. */ - do { - channel = libssh2_scp_recv(session, remote_file, &fileinfo); - - if (!channel) { - if (libssh2_session_last_errno(session) != - LIBSSH2_ERROR_EAGAIN) { - goto err;; - } else { - waitsocket(sock, session); - } - } - } while (!channel); - - /* Creating a new data base based on remote file */ - if ((fd = creat(local_file, 0755)) == -1) - goto err; - - /* Request a file via SCP */ - while (got < fileinfo.st_size) { - do { - amount = sizeof(buffer); - - if ((fileinfo.st_size - got) < amount) { - amount = fileinfo.st_size - got; - } - - rc = libssh2_channel_read(channel, buffer, amount); - if (rc > 0) { - if (safewrite(fd, buffer, rc) != rc) - VIR_WARN0 - ("Unable to write information to local file."); - - got += rc; - total += rc; - } - } while (rc > 0); - - if ((rc == LIBSSH2_ERROR_EAGAIN) - && (got < fileinfo.st_size)) { - /* this is due to blocking that would occur otherwise - * so we loop on this condition */ - - waitsocket(sock, session); /* now we wait */ - continue; - } - break; - } - if (VIR_CLOSE(fd) < 0) { - virReportSystemError(errno, _("Could not close %s"), - local_file); - goto err; - } - goto exit; - - exit: - if (channel) { - libssh2_channel_send_eof(channel); - libssh2_channel_wait_eof(channel); - libssh2_channel_wait_closed(channel); - libssh2_channel_free(channel); - channel = NULL; - } - virBufferFreeAndReset(&username); - return 0; - - err: - if (channel) { - libssh2_channel_send_eof(channel); - libssh2_channel_wait_eof(channel); - libssh2_channel_wait_closed(channel); - libssh2_channel_free(channel); - channel = NULL; - } - return -1; -} - -static int -phypUUIDTable_Init(virConnectPtr conn) -{ - uuid_tablePtr uuid_table; - phyp_driverPtr phyp_driver; - int nids_numdomains = 0; - int nids_listdomains = 0; - int *ids = NULL; - unsigned int i = 0; - - if ((nids_numdomains = phypNumDomainsGeneric(conn, 2)) < 0) - goto err; - - if (VIR_ALLOC_N(ids, nids_numdomains) < 0) { - virReportOOMError(); - goto err; - } - - if ((nids_listdomains = - phypListDomainsGeneric(conn, ids, nids_numdomains, 1)) < 0) - goto err; - - /* 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; - } - - phyp_driver = conn->privateData; - uuid_table = phyp_driver->uuid_table; - uuid_table->nlpars = nids_listdomains; - - /* try to get the table from server */ - if (phypUUIDTable_Pull(conn) == -1) { - /* file not found in the server, creating a new one */ - if (VIR_ALLOC_N(uuid_table->lpars, uuid_table->nlpars) >= 0) { - for (i = 0; i < uuid_table->nlpars; i++) { - if (VIR_ALLOC(uuid_table->lpars[i]) < 0) { - virReportOOMError(); - goto err; - } - 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; - } - - 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; - - err: - VIR_FREE(ids); - return -1; -} - -static void -phypUUIDTable_Free(uuid_tablePtr uuid_table) -{ - int i; - - if (uuid_table == NULL) - return; - - for (i = 0; i < uuid_table->nlpars; i++) - VIR_FREE(uuid_table->lpars[i]); - - VIR_FREE(uuid_table->lpars); - VIR_FREE(uuid_table); -} - -static int escape_specialcharacters(char *src, char *dst, size_t dstlen) { size_t len = strlen(src); diff --git a/src/phyp/phyp_driver.h b/src/phyp/phyp_driver.h index bc8e003..603d048 100644 --- a/src/phyp/phyp_driver.h +++ b/src/phyp/phyp_driver.h @@ -34,6 +34,7 @@ # 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 NETNAME_SIZE 24 typedef struct _ConnectionData ConnectionData; typedef ConnectionData *ConnectionDataPtr; @@ -42,6 +43,28 @@ struct _ConnectionData { int sock; }; + +/* This is the network struct that relates + * the MAC with UUID generated by the API + * */ +typedef struct _net net_t; +typedef net_t *netPtr; +struct _net { + unsigned char uuid[VIR_UUID_BUFLEN]; + long long mac; + char name[NETNAME_SIZE]; +}; + +/* Struct that holds how many networks we're + * handling and a pointer to an array of net structs + * */ +typedef struct _uuid_nettable uuid_nettable_t; +typedef uuid_nettable_t *uuid_nettablePtr; +struct _uuid_nettable { + int nnets; + netPtr *nets; +}; + /* This is the lpar (domain) struct that relates * the ID with UUID generated by the API * */ @@ -68,6 +91,7 @@ typedef struct _phyp_driver phyp_driver_t; typedef phyp_driver_t *phyp_driverPtr; struct _phyp_driver { uuid_tablePtr uuid_table; + uuid_nettablePtr uuid_nettable; virCapsPtr caps; int vios_id; @@ -81,4 +105,21 @@ struct _phyp_driver { int phypRegister(void); + +/* + * Functions used in the phyp_uuid.c and must be visible outside phyp_driver.c + * */ +int phypNumDomainsGeneric(virConnectPtr conn, unsigned int type); + +int phypListDomainsGeneric(virConnectPtr conn, int *ids, int nids, + unsigned int type); + +int waitsocket(int socket_fd, LIBSSH2_SESSION * session); + +int phypNumOfNetworks(virConnectPtr conn); + +int phypListNetworks(virConnectPtr conn, char **const names, int nnames); + +int phypListNetworkMAC(virConnectPtr conn, long long *macs, int nnets); + #endif /* PHYP_DRIVER_H */ diff --git a/src/phyp/phyp_uuid.c b/src/phyp/phyp_uuid.c new file mode 100644 index 0000000..a97dd44 --- /dev/null +++ b/src/phyp/phyp_uuid.c @@ -0,0 +1,657 @@ + +/* + * Copyright (C) 2010 Red Hat, Inc. + * Copyright IBM Corp. 2010 + * + * phyp_uuid.c: set of functions to handle lpar uuid and network uuid + * which does not have uuid itself, it must be artificially + * created. + * + * Authors: + * Eduardo Otubo <otubo at linux.vnet.ibm.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <config.h> + +#include <stdlib.h> +#include <stdio.h> +#include <libssh2.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <sys/socket.h> +#include <netdb.h> +#include <fcntl.h> +#include <sys/utsname.h> +#include <domain_event.h> + +#include "internal.h" +#include "authhelper.h" +#include "util.h" +#include "datatypes.h" +#include "buf.h" +#include "memory.h" +#include "logging.h" +#include "driver.h" +#include "libvirt/libvirt.h" +#include "virterror_internal.h" +#include "uuid.h" +#include "domain_conf.h" +#include "storage_conf.h" +#include "nodeinfo.h" +#include "files.h" + +#include "phyp_driver.h" +#include "phyp_uuid.h" + +#define VIR_FROM_THIS VIR_FROM_PHYP + +static unsigned const int NET = 0; +static unsigned const int DOMAIN = 1; + +static int +phypUUIDTable_WriteFile(virConnectPtr conn, int type) +{ + phyp_driverPtr phyp_driver = conn->privateData; + unsigned int i = 0; + int fd = -1; + + if (type == DOMAIN) { + char local_file[] = "./uuid_table"; + uuid_tablePtr uuid_table = phyp_driver->uuid_table; + + if ((fd = creat(local_file, 0755)) == -1) + goto err; + + for (i = 0; i < uuid_table->nlpars; i++) { + if (safewrite(fd, &uuid_table->lpars[i]->id, + sizeof(uuid_table->lpars[i]->id)) != + sizeof(uuid_table->lpars[i]->id)) { + VIR_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; + } + } + if (VIR_CLOSE(fd) < 0) { + virReportSystemError(errno, _("Could not close %s"), + local_file); + goto err; + } + } else if (type == NET) { + char local_file[] = "./uuid_nettable"; + uuid_nettablePtr uuid_nettable = phyp_driver->uuid_nettable; + + if ((fd = creat(local_file, 0755)) == -1) + goto err; + + for (i = 0; i < uuid_nettable->nnets; i++) { + if (safewrite(fd, &uuid_nettable->nets[i]->mac, + sizeof(uuid_nettable->nets[i]->mac)) != + sizeof(uuid_nettable->nets[i]->mac)) { + VIR_ERROR0(_ + ("Unable to write information to local file.")); + goto err; + } + + if (safewrite + (fd, uuid_nettable->nets[i]->uuid, + VIR_UUID_BUFLEN) != VIR_UUID_BUFLEN) { + VIR_ERROR0(_ + ("Unable to write information to local file.")); + goto err; + } + + if (safewrite(fd, uuid_nettable->nets[i]->name, NETNAME_SIZE) + != NETNAME_SIZE) { + VIR_ERROR0(_ + ("Unable to write information to local file.")); + goto err; + } + } + if (VIR_CLOSE(fd) < 0) { + virReportSystemError(errno, _("Could not close %s"), + local_file); + goto err; + } + } else { + VIR_ERROR0(_("Unknown file requested.")); + goto err; + } + + return 0; + + err: + VIR_FORCE_CLOSE(fd); + return -1; +} + +static int +phypUUIDTable_ReadFile(virConnectPtr conn, int type) +{ + phyp_driverPtr phyp_driver = conn->privateData; + unsigned int i = 0; + int fd = -1; + int rc = 0; + + if (type == DOMAIN) { + char local_file[] = "./uuid_table"; + int id; + uuid_tablePtr uuid_table = phyp_driver->uuid_table; + + 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; + } + + 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 + virReportOOMError(); + } else if (type == NET) { + char local_file[] = "./uuid_nettable"; + long long mac; + uuid_nettablePtr uuid_nettable = phyp_driver->uuid_nettable; + + if ((fd = open(local_file, O_RDONLY)) == -1) { + VIR_WARN0("Unable to write information to local file."); + goto err; + } + + if (VIR_ALLOC_N(uuid_nettable->nets, uuid_nettable->nnets) >= 0) { + for (i = 0; i < uuid_nettable->nnets; i++) { + + rc = read(fd, &mac, sizeof(long long)); + if (rc == sizeof(long long)) { + if (VIR_ALLOC(uuid_nettable->nets[i]) < 0) { + virReportOOMError(); + goto err; + } + uuid_nettable->nets[i]->mac = mac; + } else { + VIR_WARN0 + ("Unable to read from information to local file."); + goto err; + } + + rc = read(fd, uuid_nettable->nets[i]->uuid, + VIR_UUID_BUFLEN); + if (rc != VIR_UUID_BUFLEN) { + VIR_WARN0("Unable to read information to local file."); + goto err; + } + + rc = read(fd, uuid_nettable->nets[i]->name, NETNAME_SIZE); + if (rc != NETNAME_SIZE) { + VIR_WARN0("Unable to read information to local file."); + goto err; + } + } + } else + virReportOOMError(); + + } else { + VIR_ERROR0(_("Unknown file requested.")); + goto err; + } + + VIR_FORCE_CLOSE(fd); + return 0; + + err: + VIR_FORCE_CLOSE(fd); + return -1; +} + +static int +phypUUIDTable_Push(virConnectPtr conn, int type) +{ + ConnectionData *connection_data = conn->networkPrivateData; + 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 *remote_file = NULL; + char *local_file = NULL; + + if (conn->uri->user != NULL) { + virBufferVSprintf(&username, "%s", conn->uri->user); + + if (virBufferError(&username)) { + virBufferFreeAndReset(&username); + virReportOOMError(); + goto err; + } + } + + if (type == DOMAIN) { + if (virAsprintf(&local_file, "./uuid_table") < 0) { + virReportOOMError(); + goto err; + } + + if (virAsprintf + (&remote_file, "/home/%s/libvirt_uuid_table", + virBufferContentAndReset(&username)) + < 0) { + virReportOOMError(); + goto err; + } + } else if (type == NET) { + if (virAsprintf(&local_file, "./uuid_nettable") < 0) { + virReportOOMError(); + goto err; + } + + if (virAsprintf + (&remote_file, "/home/%s/libvirt_netuuid_table", + virBufferContentAndReset(&username)) + < 0) { + virReportOOMError(); + goto err; + } + } else { + VIR_ERROR0(_("Unknown file requested.")); + goto err; + } + + if (stat(local_file, &local_fileinfo) == -1) { + VIR_WARN0("Unable to stat local file."); + goto err; + } + + if (!(fd = fopen(local_file, "rb"))) { + VIR_WARN0("Unable to open local file."); + 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; + + do { + /* write the same data over and over, until error or completion */ + rc = libssh2_channel_write(channel, ptr, nread); + if (LIBSSH2_ERROR_EAGAIN == rc) { /* must loop around */ + continue; + } else if (rc > 0) { + /* rc indicates how many bytes were written this time */ + sent += rc; + } + ptr += sent; + nread -= sent; + } while (rc > 0 && sent < nread); + } while (1); + + if (channel) { + 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: + 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 +phypUUIDTable_Pull(virConnectPtr conn, int type) +{ + ConnectionData *connection_data = conn->networkPrivateData; + 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 *remote_file = NULL; + char *local_file = NULL; + + if (conn->uri->user != NULL) { + virBufferVSprintf(&username, "%s", conn->uri->user); + + if (virBufferError(&username)) { + virBufferFreeAndReset(&username); + virReportOOMError(); + goto err; + } + } + + if (type == DOMAIN) { + if (virAsprintf(&local_file, "./uuid_table") < 0) { + virReportOOMError(); + goto err; + } + + if (virAsprintf + (&remote_file, "/home/%s/libvirt_uuid_table", + virBufferContentAndReset(&username)) + < 0) { + virReportOOMError(); + goto err; + } + } else if (type == NET) { + if (virAsprintf(&local_file, "./uuid_nettable") + < 0) { + virReportOOMError(); + goto err; + } + + if (virAsprintf + (&remote_file, "/home/%s/libvirt_netuuid_table", + virBufferContentAndReset(&username)) + < 0) { + virReportOOMError(); + goto err; + } + } else { + VIR_ERROR0(_("Unknown file requested.")); + goto err; + } + + /* Trying to stat the remote file. */ + do { + channel = libssh2_scp_recv(session, remote_file, &fileinfo); + + if (!channel) { + if (libssh2_session_last_errno(session) != + LIBSSH2_ERROR_EAGAIN) { + goto err;; + } else { + waitsocket(sock, session); + } + } + } while (!channel); + + /* Creating a new data base based on remote file */ + if ((fd = creat(local_file, 0755)) == -1) + goto err; + + /* Request a file via SCP */ + while (got < fileinfo.st_size) { + do { + amount = sizeof(buffer); + + if ((fileinfo.st_size - got) < amount) { + amount = fileinfo.st_size - got; + } + + rc = libssh2_channel_read(channel, buffer, amount); + if (rc > 0) { + if (safewrite(fd, buffer, rc) != rc) + VIR_WARN0 + ("Unable to write information to local file."); + + got += rc; + total += rc; + } + } while (rc > 0); + + if ((rc == LIBSSH2_ERROR_EAGAIN) + && (got < fileinfo.st_size)) { + /* this is due to blocking that would occur otherwise + * so we loop on this condition */ + + waitsocket(sock, session); /* now we wait */ + continue; + } + break; + } + if (VIR_CLOSE(fd) < 0) { + virReportSystemError(errno, _("Could not close %s"), local_file); + goto err; + } + goto exit; + + exit: + if (channel) { + libssh2_channel_send_eof(channel); + libssh2_channel_wait_eof(channel); + libssh2_channel_wait_closed(channel); + libssh2_channel_free(channel); + channel = NULL; + } + virBufferFreeAndReset(&username); + return 0; + + err: + if (channel) { + libssh2_channel_send_eof(channel); + libssh2_channel_wait_eof(channel); + libssh2_channel_wait_closed(channel); + libssh2_channel_free(channel); + channel = NULL; + } + return -1; +} + +int +phypUUIDTable_RemLpar(virConnectPtr conn, int id) +{ + phyp_driverPtr phyp_driver = conn->privateData; + uuid_tablePtr uuid_table = phyp_driver->uuid_table; + unsigned int i = 0; + + for (i = 0; i < uuid_table->nlpars; i++) { + if (uuid_table->lpars[i]->id == id) { + uuid_table->lpars[i]->id = -1; + memset(uuid_table->lpars[i]->uuid, 0, VIR_UUID_BUFLEN); + } + } + + if (phypUUIDTable_WriteFile(conn, DOMAIN) == -1) + goto err; + + if (phypUUIDTable_Push(conn, DOMAIN) == -1) + goto err; + + return 0; + + err: + return -1; +} + +int +phypUUIDTable_AddLpar(virConnectPtr conn, unsigned char *uuid, int id) +{ + phyp_driverPtr phyp_driver = conn->privateData; + uuid_tablePtr uuid_table = phyp_driver->uuid_table; + + uuid_table->nlpars++; + unsigned int i = uuid_table->nlpars; + i--; + + if (VIR_REALLOC_N(uuid_table->lpars, uuid_table->nlpars) < 0) { + virReportOOMError(); + goto err; + } + + if (VIR_ALLOC(uuid_table->lpars[i]) < 0) { + virReportOOMError(); + goto err; + } + + uuid_table->lpars[i]->id = id; + memmove(uuid_table->lpars[i]->uuid, uuid, VIR_UUID_BUFLEN); + + if (phypUUIDTable_WriteFile(conn, DOMAIN) == -1) + goto err; + + if (phypUUIDTable_Push(conn, DOMAIN) == -1) + goto err; + + return 0; + + err: + return -1; +} + +int +phypUUIDTable_Init(virConnectPtr conn) +{ + uuid_tablePtr uuid_table; + phyp_driverPtr phyp_driver; + int nids_numdomains = 0; + int nids_listdomains = 0; + int *ids = NULL; + unsigned int i = 0; + + if ((nids_numdomains = phypNumDomainsGeneric(conn, 2)) < 0) + goto err; + + if (VIR_ALLOC_N(ids, nids_numdomains) < 0) { + virReportOOMError(); + goto err; + } + + if ((nids_listdomains = + phypListDomainsGeneric(conn, ids, nids_numdomains, 1)) < 0) + goto err; + + /* 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; + } + + phyp_driver = conn->privateData; + uuid_table = phyp_driver->uuid_table; + uuid_table->nlpars = nids_listdomains; + + /* try to get the table from server */ + if (phypUUIDTable_Pull(conn, DOMAIN) == -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 (virUUIDGenerate(uuid_table->lpars[i]->uuid) < 0) + VIR_WARN("Unable to generate UUID for domain %d", + ids[i]); + } + } else { + virReportOOMError(); + goto err; + } + + if (phypUUIDTable_WriteFile(conn, DOMAIN) == -1) + goto err; + + if (phypUUIDTable_Push(conn, DOMAIN) == -1) + goto err; + } else { + if (phypUUIDTable_ReadFile(conn, DOMAIN) == -1) + goto err; + goto exit; + } + + exit: + VIR_FREE(ids); + return 0; + + err: + VIR_FREE(ids); + return -1; +} + +void +phypUUIDTable_Free(uuid_tablePtr uuid_table) +{ + int i; + + if (uuid_table == NULL) + return; + + for (i = 0; i < uuid_table->nlpars; i++) + VIR_FREE(uuid_table->lpars[i]); + + VIR_FREE(uuid_table->lpars); + VIR_FREE(uuid_table); +} diff --git a/src/phyp/phyp_uuid.h b/src/phyp/phyp_uuid.h new file mode 100644 index 0000000..ddf28f4 --- /dev/null +++ b/src/phyp/phyp_uuid.h @@ -0,0 +1,36 @@ + +/* + * Copyright (C) 2010 Red Hat, Inc. + * Copyright IBM Corp. 2010 + * + * phyp_uuid.c: set of functions to handle lpar uuid and network uuid + * which does not have uuid itself, it must be artificially + * created. + * + * Authors: + * Eduardo Otubo <otubo at linux.vnet.ibm.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <config.h> + +int phypUUIDTable_Init(virConnectPtr conn); + +void phypUUIDTable_Free(uuid_tablePtr uuid_table); + +int phypUUIDTable_RemLpar(virConnectPtr conn, int id); + +int phypUUIDTable_AddLpar(virConnectPtr conn, unsigned char *uuid, int id); -- 1.7.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list