[libvirt] [PATCH 1/3] PHYP: Separating UUID functions in another file
Eduardo Otubo
otubo at linux.vnet.ibm.com
Fri Nov 19 14:55:04 UTC 2010
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
More information about the libvir-list
mailing list