[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