[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH] create() and destroy() support for Power Hypervisor



Hello all,

This patch includes a lot of changes:

* I changed all references of uuid_db to uuid_table. Bigger name, but this semantic has a better understanding.

* Now we have a little control of UUID generated for each partition. It's based on a table that matches UUID with LPAR's IDs, I keep it in a file that is stored in the managed system (HMC or IVM). Even having isolated functions to manipulate this file I still need to implement a way to lock it and make the operation atomic to avoid corruptions.

* The XML file used in the create() function still must be improved. I used the <disk> tag to make a work around to handle storage pools. Now I ask for some help, how do I use the <pool> tag if there is no reference to it at the virDomainDef structure?

I've been told that libvirt possibly would make a mini-release this week to push some major fixes on Fedora 12. Is there a little possibility to push these new phyp features too? This would be very important for the phyp project, since this functions are not just to manage partitions but manipulate them.

Any comments are always welcome.
[]'s

--
Eduardo Otubo
Software Engineer
Linux Technology Center
IBM Systems & Technology Group
Mobile: +55 19 8135 0885 eotubo linux vnet ibm com

diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c
index ef465ed..b856078 100644
--- a/src/phyp/phyp_driver.c
+++ b/src/phyp/phyp_driver.c
@@ -25,6 +25,7 @@
 #include <config.h>
 
 #include <sys/types.h>
+#include <sys/stat.h>
 #include <limits.h>
 #include <string.h>
 #include <strings.h>
@@ -39,6 +40,9 @@
 #include <arpa/inet.h>
 #include <sys/socket.h>
 #include <netdb.h>
+#include <fcntl.h>
+#include <sys/utsname.h>
+#include <conf/domain_event.h>
 
 #include "internal.h"
 #include "util.h"
@@ -51,15 +55,12 @@
 #include "virterror_internal.h"
 #include "uuid.h"
 #include "domain_conf.h"
+#include "nodeinfo.h"
 
 #include "phyp_driver.h"
 
 #define VIR_FROM_THIS VIR_FROM_PHYP
 
-#define PHYP_CMD_DEBUG VIR_DEBUG("COMMAND:%s\n",cmd);
-
-static int escape_specialcharacters(char *src, char *dst, size_t dstlen);
-
 /*
  * URI: phyp://user [hmc|ivm]/managed_system
  * */
@@ -72,8 +73,9 @@ phypOpen(virConnectPtr conn,
     ConnectionData *connection_data = NULL;
     char *string;
     size_t len = 0;
-    uuid_dbPtr uuid_db = NULL;
     int internal_socket;
+    uuid_tablePtr uuid_table = NULL;
+    phyp_driverPtr phyp_driver = NULL;
 
     if (!conn || !conn->uri)
         return VIR_DRV_OPEN_DECLINED;
@@ -95,7 +97,12 @@ phypOpen(virConnectPtr conn,
         return VIR_DRV_OPEN_ERROR;
     }
 
-    if (VIR_ALLOC(uuid_db) < 0) {
+    if (VIR_ALLOC(phyp_driver) < 0) {
+        virReportOOMError(conn);
+        goto failure;
+    }
+
+    if (VIR_ALLOC(uuid_table) < 0) {
         virReportOOMError(conn);
         goto failure;
     }
@@ -129,17 +136,25 @@ phypOpen(virConnectPtr conn,
     connection_data->session = session;
     connection_data->auth = auth;
 
-    uuid_db->nlpars = 0;
-    uuid_db->lpars = NULL;
+    uuid_table->nlpars = 0;
+    uuid_table->lpars = NULL;
+
+    phyp_driver->uuid_table = uuid_table;
+    if ((phyp_driver->caps = phypCapsInit()) == NULL)
+        goto failure;
 
-    conn->privateData = uuid_db;
+    conn->privateData = phyp_driver;
     conn->networkPrivateData = connection_data;
-    init_uuid_db(conn);
+    if (phypUUIDTable_Init(conn) == -1)
+        goto failure;
+
+    if ((phyp_driver->vios_id = phypGetVIOSPartitionID(conn)) == -1)
+        goto failure;
 
     return VIR_DRV_OPEN_SUCCESS;
 
   failure:
-    VIR_FREE(uuid_db);
+    VIR_FREE(uuid_table);
     VIR_FREE(connection_data);
     VIR_FREE(string);
 
@@ -174,17 +189,16 @@ openSSHSession(virConnectPtr conn, virConnectAuthPtr auth,
     struct addrinfo hints;
     int ret;
 
-    memset (&hints, '\0', sizeof (hints));
+    memset(&hints, '\0', sizeof(hints));
     hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
     hints.ai_socktype = SOCK_STREAM;
     hints.ai_protocol = 0;
 
-    ret = getaddrinfo (hostname, "22", &hints, &ai);
+    ret = getaddrinfo(hostname, "22", &hints, &ai);
     if (ret != 0) {
         virRaiseError(conn, NULL, NULL, 0, VIR_FROM_PHYP,
                       VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
-                      _("Error while getting %s address info"),
-                      hostname);
+                      _("Error while getting %s address info"), hostname);
         goto err;
     }
 
@@ -192,10 +206,10 @@ openSSHSession(virConnectPtr conn, virConnectAuthPtr auth,
     while (cur != NULL) {
         sock = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol);
         if (sock >= 0) {
-            if (connect (sock, cur->ai_addr, cur->ai_addrlen) == 0) {
+            if (connect(sock, cur->ai_addr, cur->ai_addrlen) == 0) {
                 goto connected;
             }
-            close (sock);
+            close(sock);
         }
         cur = cur->ai_next;
     }
@@ -203,10 +217,10 @@ openSSHSession(virConnectPtr conn, virConnectAuthPtr auth,
     virRaiseError(conn, NULL, NULL, 0, VIR_FROM_PHYP,
                   VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
                   _("Failed to connect to %s"), hostname);
-    freeaddrinfo (ai);
+    freeaddrinfo(ai);
     goto err;
 
-connected:
+  connected:
 
     (*internal_socket) = sock;
 
@@ -407,7 +421,6 @@ phypGetLparID(LIBSSH2_SESSION * session, const char *managed_system,
         virReportOOMError(conn);
         goto err;
     }
-    PHYP_CMD_DEBUG;
 
     const char *ret = phypExec(session, cmd, &exit_status, conn);
 
@@ -439,7 +452,6 @@ phypGetLparNAME(LIBSSH2_SESSION * session, const char *managed_system,
         virReportOOMError(conn);
         goto err;
     }
-    PHYP_CMD_DEBUG;
 
     char *ret = phypExec(session, cmd, &exit_status, conn);
 
@@ -463,7 +475,7 @@ phypGetLparNAME(LIBSSH2_SESSION * session, const char *managed_system,
 }
 
 
-/* Search into the uuid_db for a lpar_uuid given a lpar_id
+/* Search into the uuid_table for a lpar_uuid given a lpar_id
  * and a managed system name
  *
  * return:  0 - record found
@@ -472,11 +484,12 @@ phypGetLparNAME(LIBSSH2_SESSION * session, const char *managed_system,
 int
 phypGetLparUUID(unsigned char *uuid, int lpar_id, virConnectPtr conn)
 {
-    uuid_dbPtr uuid_db = conn->privateData;
-    lparPtr *lpars = uuid_db->lpars;
+    phyp_driverPtr phyp_driver = conn->privateData;
+    uuid_tablePtr uuid_table = phyp_driver->uuid_table;
+    lparPtr *lpars = uuid_table->lpars;
     unsigned int i = 0;
 
-    for (i = 0; i < uuid_db->nlpars; i++) {
+    for (i = 0; i < uuid_table->nlpars; i++) {
         if (lpars[i]->id == lpar_id) {
             memmove(uuid, lpars[i]->uuid, VIR_UUID_BUFLEN);
             return 0;
@@ -520,7 +533,6 @@ phypGetLparMem(virConnectPtr conn, const char *managed_system, int lpar_id,
             goto err;
         }
     }
-    PHYP_CMD_DEBUG;
 
     char *ret = phypExec(session, cmd, &exit_status, conn);
 
@@ -562,7 +574,6 @@ phypGetLparCPU(virConnectPtr conn, const char *managed_system, int lpar_id)
         virReportOOMError(conn);
         goto err;
     }
-    PHYP_CMD_DEBUG;
     char *ret = phypExec(session, cmd, &exit_status, conn);
 
     if (ret == NULL)
@@ -604,7 +615,6 @@ phypGetRemoteSlot(virConnectPtr conn, const char *managed_system,
         virReportOOMError(conn);
         goto err;
     }
-    PHYP_CMD_DEBUG;
     char *ret = phypExec(session, cmd, &exit_status, conn);
 
     if (ret == NULL)
@@ -626,7 +636,7 @@ phypGetRemoteSlot(virConnectPtr conn, const char *managed_system,
 
   err:
     VIR_FREE(cmd);
-    return 0;
+    return -1;
 }
 
 char *
@@ -640,7 +650,7 @@ phypGetBackingDevice(virConnectPtr conn, const char *managed_system,
     int exit_status = 0;
 
     if ((remote_slot =
-         phypGetRemoteSlot(conn, managed_system, lpar_name)) == 0)
+         phypGetRemoteSlot(conn, managed_system, lpar_name)) == -1)
         goto err;
 
     if (virAsprintf(&cmd,
@@ -649,7 +659,6 @@ phypGetBackingDevice(virConnectPtr conn, const char *managed_system,
         virReportOOMError(conn);
         goto err;
     }
-    PHYP_CMD_DEBUG;
 
     char *ret = phypExec(session, cmd, &exit_status, conn);
 
@@ -721,7 +730,6 @@ phypGetLparState(virConnectPtr conn, unsigned int lpar_id)
         virReportOOMError(conn);
         goto err;
     }
-    PHYP_CMD_DEBUG;
 
     char *ret = phypExec(session, cmd, &exit_status, conn);
 
@@ -752,27 +760,87 @@ phypGetLparState(virConnectPtr conn, unsigned int lpar_id)
 }
 
 int
+phypGetVIOSPartitionID(virConnectPtr conn)
+{
+    ConnectionData *connection_data = conn->networkPrivateData;
+    LIBSSH2_SESSION *session = connection_data->session;
+    char *cmd;
+    int exit_status = 0;
+    int id = -1;
+    char *char_ptr;
+    char *managed_system = conn->uri->path;
+
+    /* need to shift one byte in order to remove the first "/" of URI component */
+    if (managed_system[0] == '/')
+        managed_system++;
+
+    /* here we are handling only the first component of the path,
+     * so skipping the second:
+     * */
+    char_ptr = strchr(managed_system, '/');
+
+    if (char_ptr)
+        *char_ptr = '\0';
+
+    if (virAsprintf(&cmd,
+                    "lssyscfg -m %s -r lpar -F lpar_id,lpar_env|grep vioserver|sed -s 's/,.*$//g'",
+                    managed_system) < 0) {
+        virReportOOMError(conn);
+        goto err;
+    }
+
+    char *ret = phypExec(session, cmd, &exit_status, conn);
+
+    if (exit_status < 0 || ret == NULL)
+        goto err;
+
+    if (virStrToLong_i(ret, &char_ptr, 10, &id) == -1)
+        goto err;
+
+    return id;
+
+  err:
+    VIR_FREE(cmd);
+    return -1;
+}
+
+int
 phypDiskType(virConnectPtr conn, char *backing_device)
 {
+    phyp_driverPtr phyp_driver = conn->privateData;
     ConnectionData *connection_data = conn->networkPrivateData;
     LIBSSH2_SESSION *session = connection_data->session;
     char *cmd;
     int exit_status = 0;
+    char *char_ptr;
+    char *managed_system = conn->uri->path;
+    int vios_id = phyp_driver->vios_id;
+
+    /* need to shift one byte in order to remove the first "/" of URI component */
+    if (managed_system[0] == '/')
+        managed_system++;
+
+    /* here we are handling only the first component of the path,
+     * so skipping the second:
+     * */
+    char_ptr = strchr(managed_system, '/');
+
+    if (char_ptr)
+        *char_ptr = '\0';
 
     if (virAsprintf(&cmd,
-                    "ioscli lssp -field name type -fmt , -all|grep %s|sed -e 's/^.*,//g'",
-                    backing_device) < 0) {
+                    "viosvrcmd -m %s -p %d -c \"lssp -field name type -fmt , -all|grep %s|sed -e 's/^.*,//g'\"",
+                    managed_system, vios_id, backing_device) < 0) {
         virReportOOMError(conn);
         goto err;
     }
-    PHYP_CMD_DEBUG;
 
     char *ret = phypExec(session, cmd, &exit_status, conn);
 
     if (ret == NULL)
         goto err;
 
-    char *char_ptr = strchr(ret, '\n');
+    char_ptr = strchr(ret, '\n');
 
     if (char_ptr)
         *char_ptr = '\0';
@@ -839,7 +907,6 @@ phypNumDomainsGeneric(virConnectPtr conn, unsigned int type)
         virReportOOMError(conn);
         goto err;
     }
-    PHYP_CMD_DEBUG;
 
     char *ret = phypExec(session, cmd, &exit_status, conn);
 
@@ -874,7 +941,7 @@ phypNumDomains(virConnectPtr conn)
  * in different states: Running, and all:
  *
  * type: 0 - Running
- *       * - all
+ *       1 - all
  * */
 static int
 phypListDomainsGeneric(virConnectPtr conn, int *ids, int nids,
@@ -917,7 +984,6 @@ phypListDomainsGeneric(virConnectPtr conn, int *ids, int nids,
         virReportOOMError(conn);
         goto err;
     }
-    PHYP_CMD_DEBUG;
     char *ret = phypExec(session, cmd, &exit_status, conn);
 
     /* I need to parse the textual return in order to get the ret */
@@ -984,7 +1050,6 @@ phypListDefinedDomains(virConnectPtr conn, char **const names, int nnames)
         virReportOOMError(conn);
         goto err;
     }
-    PHYP_CMD_DEBUG;
 
     char *ret = phypExec(session, cmd, &exit_status, conn);
 
@@ -1052,7 +1117,7 @@ phypDomainLookupByName(virConnectPtr conn, const char *lpar_name)
         *char_ptr = '\0';
 
     lpar_id = phypGetLparID(session, managed_system, lpar_name, conn);
-    if (lpar_id < 0)
+    if (lpar_id == -1)
         goto err;
 
     if (phypGetLparUUID(lpar_uuid, lpar_id, conn) == -1)
@@ -1189,9 +1254,12 @@ phypDomainDumpXML(virDomainPtr dom, int flags)
 
     ret = virDomainDefFormat(dom->conn, def, flags);
 
-  err:
     VIR_FREE(def);
     return ret;
+
+  err:
+    VIR_FREE(def);
+    return NULL;
 }
 
 static int
@@ -1223,15 +1291,20 @@ phypDomainResume(virDomainPtr dom)
         virReportOOMError(dom->conn);
         goto err;
     }
-    PHYP_CMD_DEBUG;
 
     char *ret = phypExec(session, cmd, &exit_status, dom->conn);
 
-  err:
+    if (exit_status < 0)
+        goto err;
+
     VIR_FREE(cmd);
     VIR_FREE(ret);
     return 0;
 
+  err:
+    VIR_FREE(cmd);
+    VIR_FREE(ret);
+    return -1;
 }
 
 static int
@@ -1263,15 +1336,20 @@ phypDomainShutdown(virDomainPtr dom)
         virReportOOMError(dom->conn);
         goto err;
     }
-    PHYP_CMD_DEBUG;
 
     char *ret = phypExec(session, cmd, &exit_status, dom->conn);
 
-  err:
+    if (exit_status < 0)
+        goto err;
+
     VIR_FREE(cmd);
     VIR_FREE(ret);
     return 0;
 
+  err:
+    VIR_FREE(cmd);
+    VIR_FREE(ret);
+    return 0;
 }
 
 static int
@@ -1306,9 +1384,184 @@ phypDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
         VIR_WARN("%s", "Unable to determine domain's CPU.");
 
     return 0;
+}
+
+static int phypDomainDestroy(virDomainPtr dom){
+    ConnectionData *connection_data = dom->conn->networkPrivateData;
+    LIBSSH2_SESSION *session = connection_data->session;
+    char *managed_system = dom->conn->uri->path;
+    int exit_status = 0;
+    char *char_ptr = NULL;
+    char *cmd;
+
+    /* need to shift one byte in order to remove the first "/" of URI component */
+    if (managed_system[0] == '/')
+        managed_system++;
+
+    /* here we are handling only the first component of the path,
+     * so skipping the second:
+     * */
+    char_ptr = strchr(managed_system, '/');
+
+    if (char_ptr)
+        *char_ptr = '\0';
+
+    if (virAsprintf
+        (&cmd,
+         "rmsyscfg -m %s -r lpar --id %d",
+         managed_system, dom->id) < 0) {
+        virReportOOMError(dom->conn);
+        goto err;
+    }
+
+    char *ret = phypExec(session, cmd, &exit_status, dom->conn);
+
+    if (exit_status < 0)
+        goto err;
+
+    if(phypUUIDTable_RemLpar(dom->conn, dom->id) == -1)
+        goto err;
+
+    VIR_FREE(cmd);
+    VIR_FREE(ret);
+    return 0;
+
+  err:
+    VIR_FREE(cmd);
+    VIR_FREE(ret);
+    return 0;
 
 }
 
+static virDomainPtr
+phypDomainCreateAndStart(virConnectPtr conn,
+                         const char *xml,
+                         unsigned int flags ATTRIBUTE_UNUSED)
+{
+
+    ConnectionData *connection_data = conn->networkPrivateData;
+    LIBSSH2_SESSION *session = connection_data->session;
+    virDomainDefPtr def = NULL;
+    virDomainPtr dom = NULL;
+    phyp_driverPtr phyp_driver = conn->privateData;
+    uuid_tablePtr uuid_table = phyp_driver->uuid_table;
+    lparPtr *lpars = uuid_table->lpars;
+    unsigned int i = 0;
+    char *managed_system = conn->uri->path;
+    char *char_ptr = NULL;
+
+    /* need to shift one byte in order to remove the first "/" of URI component */
+    if (managed_system[0] == '/')
+        managed_system++;
+
+    /* here we are handling only the first component of the path,
+     * so skipping the second:
+     * */
+    char_ptr = strchr(managed_system, '/');
+
+    if (char_ptr)
+        *char_ptr = '\0';
+
+
+    if (VIR_ALLOC(def) < 0)
+        virReportOOMError(conn);
+
+    if (VIR_ALLOC(dom) < 0)
+        virReportOOMError(conn);
+
+    if (!(def = virDomainDefParseString(conn, phyp_driver->caps, xml,
+                                        VIR_DOMAIN_XML_INACTIVE)))
+        goto err;
+
+    /* checking if this name already exists on this system */
+    if (phypGetLparID(session, managed_system, def->name, conn) == -1) {
+        VIR_WARN("%s", "LPAR name already exists.");
+        goto err;
+    }
+
+    /* checking if ID or UUID already exists on this system */
+    for (i = 0; i < uuid_table->nlpars; i++) {
+        if (lpars[i]->id == def->id || lpars[i]->uuid == def->uuid) {
+            VIR_WARN("%s", "LPAR ID or UUID already exists.");
+            goto err;
+        }
+    }
+
+    dom->conn = conn;
+    dom->name = def->name;
+    dom->id = def->id;
+    memmove(dom->uuid, def->uuid, VIR_UUID_BUFLEN);
+
+    if(phypBuildLpar(conn, def) == -1)
+        goto err;
+
+    if(phypDomainResume(dom) == -1)
+        goto err;
+
+    return dom;
+
+  err:
+    VIR_FREE(def);
+    VIR_FREE(dom);
+    return NULL;
+}
+
+static char *
+phypConnectGetCapabilities(virConnectPtr conn)
+{
+    phyp_driverPtr phyp_driver = conn->privateData;
+    char *xml;
+
+    if ((xml = virCapabilitiesFormatXML(phyp_driver->caps)) == NULL)
+        virReportOOMError(conn);
+
+    return xml;
+}
+
+virCapsPtr
+phypCapsInit(void)
+{
+    struct utsname utsname;
+    virCapsPtr caps;
+    virCapsGuestPtr guest;
+
+    uname(&utsname);
+
+    if ((caps = virCapabilitiesNew(utsname.machine, 0, 0)) == NULL)
+        goto no_memory;
+
+    /* Some machines have problematic NUMA toplogy causing
+     * unexpected failures. We don't want to break the QEMU
+     * driver in this scenario, so log errors & carry on
+     */
+    if (nodeCapsInitNUMA(caps) < 0) {
+        virCapabilitiesFreeNUMAInfo(caps);
+        VIR_WARN0
+            ("Failed to query host NUMA topology, disabling NUMA capabilities");
+    }
+
+    /* XXX shouldn't 'borrow' KVM's prefix */
+    virCapabilitiesSetMacPrefix(caps, (unsigned char[]) {
+                                0x52, 0x54, 0x00});
+
+    if ((guest = virCapabilitiesAddGuest(caps,
+                                         "linux",
+                                         utsname.machine,
+                                         sizeof(int) == 4 ? 32 : 8,
+                                         NULL, NULL, 0, NULL)) == NULL)
+        goto no_memory;
+
+    if (virCapabilitiesAddGuestDomain(guest,
+                                      "phyp", NULL, NULL, 0, NULL) == NULL)
+        goto no_memory;
+
+    return caps;
+
+  no_memory:
+    virCapabilitiesFree(caps);
+    return NULL;
+}
+
 virDriver phypDriver = {
     VIR_DRV_PHYP,
     "PHYP",
@@ -1320,10 +1573,10 @@ virDriver phypDriver = {
     NULL,                       /* getHostname */
     NULL,                       /* getMaxVcpus */
     NULL,                       /* nodeGetInfo */
-    NULL,                       /* getCapabilities */
+    phypConnectGetCapabilities, /* getCapabilities */
     phypListDomains,            /* listDomains */
     phypNumDomains,             /* numOfDomains */
-    NULL,                       /* domainCreateXML */
+    phypDomainCreateAndStart,   /* domainCreateXML */
     phypDomainLookupByID,       /* domainLookupByID */
     NULL,                       /* domainLookupByUUID */
     phypDomainLookupByName,     /* domainLookupByName */
@@ -1331,7 +1584,7 @@ virDriver phypDriver = {
     phypDomainResume,           /* domainResume */
     phypDomainShutdown,         /* domainShutdown */
     NULL,                       /* domainReboot */
-    NULL,                       /* domainDestroy */
+    phypDomainDestroy,          /* domainDestroy */
     NULL,                       /* domainGetOSType */
     NULL,                       /* domainGetMaxMemory */
     NULL,                       /* domainSetMaxMemory */
@@ -1381,52 +1634,473 @@ virDriver phypDriver = {
 };
 
 int
-phypRegister(void)
+phypBuildLpar(virConnectPtr conn, virDomainDefPtr def)
 {
-    virRegisterDriver(&phypDriver);
+    ConnectionData *connection_data = conn->networkPrivateData;
+    LIBSSH2_SESSION *session = connection_data->session;
+    char *managed_system = conn->uri->path;
+    char *char_ptr = NULL;
+    char *cmd;
+    int exit_status = 0;
+
+    /* need to shift one byte in order to remove the first "/" of URI component */
+    if (managed_system[0] == '/')
+        managed_system++;
+
+    /* here we are handling only the first component of the path,
+     * so skipping the second:
+     * */
+    char_ptr = strchr(managed_system, '/');
+
+    if (char_ptr)
+        *char_ptr = '\0';
+
+    if (virAsprintf
+        (&cmd,
+         "mksyscfg -m %s -r lpar --id %d -i name=%s,min_mem=%d,desired_mem=%d,\
+          max_mem=%d,desired_procs=%d,virtual_scsi_adapters=%s",
+         managed_system, def->id, def->name, (int)def->memory, (int)def->memory, (int)def->maxmem, (int) def->vcpus, def->disks[0]->src) <
+        0) {
+        virReportOOMError(conn);
+        goto err;
+    }
+
+    char *ret = phypExec(session, cmd, &exit_status, conn);
+
+    if (exit_status < 0) {
+        VIR_ERROR("%s\"%s\"", "Unable to create LPAR. Reason: ", ret);
+        goto err;
+    }
+
+    if(phypUUIDTable_AddLpar(conn, def->uuid, def->id) == -1){
+        VIR_ERROR("%s", "Unable to add LPAR to the table");
+        goto err;
+    }
+
+    VIR_FREE(cmd);
+    VIR_FREE(ret);
+    return 0;
+
+  err:
+    VIR_FREE(cmd);
+    VIR_FREE(ret);
+    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;
+            if (!memset(uuid_table->lpars[i]->uuid, '0', VIR_UUID_BUFLEN))
+                goto exit;
+        }
+    }
+
+    if(phypUUIDTable_WriteFile(conn) == -1)
+        goto err;
+
+    if(phypUUIDTable_Push(conn) == -1)
+        goto err;
+
+exit:
     return 0;
+
+err:
+    return -1;
 }
 
-void
-init_uuid_db(virConnectPtr conn)
+int
+phypUUIDTable_AddLpar(virConnectPtr conn, unsigned char *uuid, int id)
 {
-    uuid_dbPtr uuid_db;
+    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(conn);
+        goto err;
+    }
+
+    if (VIR_ALLOC(uuid_table->lpars[i]) < 0)
+        virReportOOMError(conn);
+
+    uuid_table->lpars[i]->id = id;
+    if (memmove(uuid_table->lpars[i]->uuid, uuid, VIR_UUID_BUFLEN) == NULL)
+        goto err;
+
+    if(phypUUIDTable_WriteFile(conn) == -1)
+        goto err;
+
+    if(phypUUIDTable_Push(conn) == -1)
+        goto err;
+
+    return 0;
+
+  err:
+    return -1;
+}
+
+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;
+    int rc = 0;
+    char buffer[1024];
+
+    if (virAsprintf(&local_file, "./uuid_table") < 0) {
+        virReportOOMError(conn);
+        goto err;
+    }
+    if (!(fd = open(local_file, O_RDONLY))) {
+        VIR_WARN("%s", "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, buffer, sizeof(int));
+            if (rc == sizeof(int)) {
+                if (VIR_ALLOC(uuid_table->lpars[i]) < 0)
+                    virReportOOMError(conn);
+                uuid_table->lpars[i]->id = (*buffer);
+            } else {
+                VIR_WARN("%s",
+                         "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_WARN("%s",
+                         "Unable to read information to local file.");
+                goto err;
+            }
+        }
+    }
+
+    close(fd);
+    goto exit;
+
+  exit:
+    VIR_FREE(local_file);
+    return 0;
+
+  err:
+    VIR_FREE(local_file);
+    return -1;
+}
+
+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;
+
+    if (virAsprintf(&local_file, "./uuid_table") < 0) {
+        virReportOOMError(conn);
+        goto err;
+    }
+
+    if ((fd = creat(local_file, 0755)) == -1)
+        goto err;
+
+    for (i = 0; i < uuid_table->nlpars; i++) {
+        if (write(fd, &uuid_table->lpars[i]->id, sizeof(uuid_table->lpars[i]->id)) == -1)
+            VIR_WARN("%s", "Unable to write information to local file.");
+
+        if (write(fd, uuid_table->lpars[i]->uuid, VIR_UUID_BUFLEN) == -1)
+            VIR_WARN("%s", "Unable to write information to local file.");
+    }
+    close(fd);
+    goto exit;
+
+  exit:
+    VIR_FREE(local_file);
+    return 0;
+
+  err:
+    VIR_FREE(local_file);
+    return -1;
+}
+
+int
+phypUUIDTable_Init(virConnectPtr conn)
+{
+    uuid_tablePtr uuid_table;
+    phyp_driverPtr phyp_driver;
     int nids = 0;
     int *ids = NULL;
     unsigned int i = 0;
 
     if ((nids = phypNumDomainsGeneric(conn, 2)) == 0)
-        goto exit;
+        goto err;
 
     if (VIR_ALLOC_N(ids, nids) < 0)
         virReportOOMError(conn);
 
-    if (VIR_ALLOC(uuid_db) < 0)
+    if (VIR_ALLOC(phyp_driver) < 0)
+        virReportOOMError(conn);
+
+    if (VIR_ALLOC(uuid_table) < 0)
         virReportOOMError(conn);
 
     if (phypListDomainsGeneric(conn, ids, nids, 1) == 0)
-        goto exit;
+        goto err;
+
+    phyp_driver = conn->privateData;
+    uuid_table = phyp_driver->uuid_table;
+    uuid_table->nlpars = nids;
+
+    /* 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++) {
+                char *id_c;
 
-    uuid_db = conn->privateData;
-    uuid_db->nlpars = nids;
+                if (VIR_ALLOC(uuid_table->lpars[i]) < 0)
+                    virReportOOMError(conn);
+                uuid_table->lpars[i]->id = ids[i];
 
-    if (VIR_ALLOC_N(uuid_db->lpars, uuid_db->nlpars) >= 0) {
-        for (i = 0; i < uuid_db->nlpars; i++) {
-            if (VIR_ALLOC(uuid_db->lpars[i]) < 0)
-                virReportOOMError(conn);
-            uuid_db->lpars[i]->id = ids[i];
+                if (virUUIDGenerate(uuid_table->lpars[i]->uuid) < 0)
+                    VIR_WARN("%s %d", "Unable to generate UUID for domain",
+                             ids[i]);
 
-            if (virUUIDGenerate(uuid_db->lpars[i]->uuid) < 0)
-                VIR_WARN("%s %d", "Unable to generate UUID for domain",
-                         ids[i]);
+                VIR_FREE(id_c);
+            }
         }
+        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;
+    return 0;
+
+  err:
+    VIR_FREE(ids);
+    return -1;
 }
 
-static int
+int
+phypUUIDTable_Push(virConnectPtr conn)
+{
+    ConnectionData *connection_data = conn->networkPrivateData;
+    LIBSSH2_SESSION *session = connection_data->session;
+    LIBSSH2_CHANNEL *channel = NULL;
+    struct stat local_fileinfo;
+    char buffer[1024];
+    int rc = 0;
+    FILE *fd;
+    size_t nread, sent;
+    char *ptr;
+    char *remote_file;
+    char *local_file;
+
+    if (virAsprintf(&remote_file, "/home/hscroot/uuid_table") < 0) {
+        virReportOOMError(conn);
+        goto err;
+    }
+
+    if (virAsprintf(&local_file, "./uuid_table") < 0) {
+        virReportOOMError(conn);
+        goto err;
+    }
+
+    if (stat(local_file, &local_fileinfo) == -1) {
+        VIR_WARN("%s", "Unable to stat local file.");
+        goto err;
+    }
+
+    if (!(fd = fopen(local_file, "rb"))) {
+        VIR_WARN("%s", "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) {
+            /* end of file */
+            break;
+        }
+        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 {
+                /* rc indicates how many bytes were written this time */
+                sent += rc;
+            }
+        } while (rc > 0 && sent < nread);
+        ptr += sent;
+        nread -= sent;
+    } while (1);
+
+    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;
+    }
+    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_Pull(virConnectPtr conn)
+{
+    ConnectionData *connection_data = conn->networkPrivateData;
+    LIBSSH2_SESSION *session = connection_data->session;
+    LIBSSH2_CHANNEL *channel = NULL;
+    struct stat fileinfo;
+    char buffer[1024];
+    int rc = 0;
+    int fd;
+    int got = 0;
+    int amount = 0;
+    int spin = 0;
+    int total = 0;
+    int sock = 0;
+    char *remote_file;
+    char *local_file;
+
+    if (virAsprintf(&remote_file, "/home/hscroot/uuid_table") < 0) {
+        virReportOOMError(conn);
+        goto err;
+    }
+
+    if (virAsprintf(&local_file, "./uuid_table") < 0) {
+        virReportOOMError(conn);
+        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 (write(fd, buffer, rc) == -1)
+                    VIR_WARN("%s",
+                             "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 */
+
+            spin++;
+            waitsocket(sock, session);  /* now we wait */
+            continue;
+        }
+        break;
+    }
+    close(fd);
+    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;
+    }
+    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
 escape_specialcharacters(char *src, char *dst, size_t dstlen)
 {
     size_t len = strlen(src);
@@ -1488,3 +2162,10 @@ waitsocket(int socket_fd, LIBSSH2_SESSION * session)
 
     return rc;
 }
+
+int
+phypRegister(void)
+{
+    virRegisterDriver(&phypDriver);
+    return 0;
+}
diff --git a/src/phyp/phyp_driver.h b/src/phyp/phyp_driver.h
index b793774..e396f87 100644
--- a/src/phyp/phyp_driver.h
+++ b/src/phyp/phyp_driver.h
@@ -1,3 +1,29 @@
+
+/*
+ * Copyright IBM Corp. 2009
+ *
+ * phyp_driver.c: ssh layer to access Power Hypervisors
+ *
+ * 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 "conf/capabilities.h"
+#include "conf/domain_conf.h"
 #include <config.h>
 #include <libssh2.h>
 
@@ -26,22 +52,52 @@ struct _lpar {
 /* Struct that holds how many lpars (domains) we're
  * handling and a pointer to an array of lpar structs
  * */
-typedef struct _uuid_db uuid_db_t;
-typedef uuid_db_t *uuid_dbPtr;
-struct _uuid_db {
+typedef struct _uuid_table uuid_table_t;
+typedef uuid_table_t *uuid_tablePtr;
+struct _uuid_table {
     int nlpars;
     lparPtr *lpars;
 };
 
-int phypGetLparUUID(unsigned char *uuid, int lpar_id, virConnectPtr conn);
+/* This is the main structure of the driver
+ * */
+typedef struct _phyp_driver phyp_driver_t;
+typedef phyp_driver_t *phyp_driverPtr;
+struct _phyp_driver {
+		uuid_tablePtr uuid_table;
+    virCapsPtr caps;
+		int vios_id;
+};
 
-void init_uuid_db(virConnectPtr conn);
+int phypCheckSPFreeSapce(virConnectPtr conn, int required_size, char *sp);
 
-int phypRegister(void);
+int phypGetVIOSPartitionID(virConnectPtr conn);
+
+virCapsPtr phypCapsInit(void);
+
+int phypBuildLpar(virConnectPtr conn, virDomainDefPtr def);
+
+int phypUUIDTable_WriteFile(virConnectPtr conn);
+
+int phypUUIDTable_ReadFile(virConnectPtr conn);
+
+int phypUUIDTable_AddLpar(virConnectPtr conn, unsigned char *uuid, int id);
+
+int phypUUIDTable_RemLpar(virConnectPtr conn, int id);
 
-void stripPath(char *striped_path, char *path);
+int phypUUIDTable_Pull(virConnectPtr conn);
 
-void stripNewline(char *striped_string, char *string);
+int phypUUIDTable_Push(virConnectPtr conn);
+
+int phypUUIDTable_Init(virConnectPtr conn);
+
+int escape_specialcharacters(char *src, char *dst, size_t dstlen);
+
+int waitsocket(int socket_fd, LIBSSH2_SESSION * session);
+
+int phypGetLparUUID(unsigned char *uuid, int lpar_id, virConnectPtr conn);
+
+int phypRegister(void);
 
 int phypGetLparState(virConnectPtr conn, unsigned int lpar_id);
 
@@ -61,5 +117,3 @@ char *phypGetBackingDevice(virConnectPtr conn, const char *managed_system,
 int phypDiskType(virConnectPtr conn, char *backing_device);
 
 LIBSSH2_SESSION *openSSHSession(virConnectPtr conn, virConnectAuthPtr auth, int *internal_socket);
-
-int waitsocket(int socket_fd, LIBSSH2_SESSION * session);

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]