[libvirt] [PATCH 3/3] PHYP: create, destroy and other network functions

Eduardo Otubo otubo at linux.vnet.ibm.com
Fri Nov 19 14:55:06 UTC 2010


Adding networkCreateXML, networkDestroy, networkIsActive and networkLookupByName.

In the function phypCreateNetwork I just use the def->domain information to create
the new network interface because of the behaviour of the HMC and the hypervisor:

    * HMC can't simply create a network interface without assigning it to a specific 
      LPAR.
    * I also can't assign an IP addr or any other information from the HMC or VIOS
      side, but I can control in which vlan or vswitch it will be attached - but
      thought just in the simplest case scenarion now, I'll make some improvements
      in the future.

That's why I used a very simple XML for testing:

    <network>
        <uuid>3e3fce45-4f53-4fa7-bb32-11f34168b82b</uuid>
        <domain name="LPAR01" />
        <name>whatever</name>
        <bridge name="whatever" />
    </network>

The only information I really need is the domain name which I'll assign the created 
network interface. Name, MAC Addr MUST be created automatically by the hypervisor, 
they're all unique. I had to put those two other tags "name" and "bridge" so the 
function virNetworkDefParseString can return successfully, otherwise it would say 
that the XML is malformed.

---
 src/phyp/phyp_driver.c |  400 +++++++++++++++++++++++++++++++++++++++++++++++-
 src/phyp/phyp_driver.h |    2 +-
 2 files changed, 396 insertions(+), 6 deletions(-)

diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c
index c44fc69..244561e 100644
--- a/src/phyp/phyp_driver.c
+++ b/src/phyp/phyp_driver.c
@@ -1,7 +1,7 @@
 
 /*
  * Copyright (C) 2010 Red Hat, Inc.
- * Copyright IBM Corp. 2009
+ * Copyright IBM Corp. 2010
  *
  * phyp_driver.c: ssh layer to access Power Hypervisors
  *
@@ -2829,6 +2829,396 @@ phypGetStoragePoolXMLDesc(virStoragePoolPtr pool, unsigned int flags)
     return NULL;
 }
 
+static int
+networkDestroy(virNetworkPtr net)
+{
+    ConnectionData *connection_data = net->conn->networkPrivateData;
+    phyp_driverPtr phyp_driver = net->conn->privateData;
+    LIBSSH2_SESSION *session = connection_data->session;
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    uuid_nettablePtr uuid_nettable = phyp_driver->uuid_nettable;
+    char *managed_system = phyp_driver->managed_system;
+    int system_type = phyp_driver->system_type;
+    int exit_status = 0;
+    int slot_num = 0;
+    char *char_ptr;
+    char *cmd = NULL;
+    char *ret = NULL;
+    unsigned int i = 0;
+    int lpar_id = 0;
+    long long mac = 0;
+
+    for (i = 0; i < uuid_nettable->nnets; i++) {
+        if (STREQ(uuid_nettable->nets[i]->name, net->name)) {
+            mac = uuid_nettable->nets[i]->mac;
+            break;
+        }
+    }
+
+    /* Getting the LPAR ID */
+
+    virBufferAddLit(&buf, "lshwres ");
+    if (system_type == HMC)
+        virBufferVSprintf(&buf, "-m %s ", managed_system);
+
+    virBufferVSprintf(&buf,
+                      " -r virtualio --rsubtype slot --level slot "
+                      " -F drc_name,lpar_id|grep %s|"
+                      " sed -e 's/^.*,//g'", net->name);
+
+    if (virBufferError(&buf)) {
+        virBufferFreeAndReset(&buf);
+        virReportOOMError();
+        return -1;
+    }
+    cmd = virBufferContentAndReset(&buf);
+
+    ret = phypExec(session, cmd, &exit_status, net->conn);
+
+    if (exit_status < 0 || ret == NULL)
+        goto err;
+
+    if (virStrToLong_i(ret, &char_ptr, 10, &lpar_id) == -1)
+        goto err;
+
+    /* Getting the remote slot number */
+
+    virBufferAddLit(&buf, "lshwres ");
+    if (system_type == HMC)
+        virBufferVSprintf(&buf, "-m %s ", managed_system);
+
+    virBufferVSprintf(&buf,
+                      " -r virtualio --rsubtype eth --level lpar "
+                      " -F mac_addr,slot_num|grep %lld|"
+                      " sed -e 's/^.*,//g'", mac);
+
+    if (virBufferError(&buf)) {
+        virBufferFreeAndReset(&buf);
+        virReportOOMError();
+        return -1;
+    }
+    cmd = virBufferContentAndReset(&buf);
+
+    ret = phypExec(session, cmd, &exit_status, net->conn);
+
+    if (exit_status < 0 || ret == NULL)
+        goto err;
+
+    if (virStrToLong_i(ret, &char_ptr, 10, &slot_num) == -1)
+        goto err;
+
+    /* excluding interface */
+
+    virBufferAddLit(&buf, "chhwres ");
+    if (system_type == HMC)
+        virBufferVSprintf(&buf, "-m %s ", managed_system);
+
+    virBufferVSprintf(&buf,
+                      " -r virtualio --rsubtype eth"
+                      " --id %d -o r -s %d", lpar_id, slot_num);
+
+    if (virBufferError(&buf)) {
+        virBufferFreeAndReset(&buf);
+        virReportOOMError();
+        return -1;
+    }
+    cmd = virBufferContentAndReset(&buf);
+
+    ret = phypExec(session, cmd, &exit_status, net->conn);
+
+    if (exit_status < 0 || ret != NULL)
+        goto err;
+
+    if (phypUUIDTable_RemNetwork(net->conn, mac) < 0)
+        goto err;
+
+    VIR_FREE(cmd);
+    VIR_FREE(ret);
+    return 0;
+
+  err:
+    VIR_FREE(cmd);
+    VIR_FREE(ret);
+    return -1;
+}
+
+static virNetworkPtr
+phypCreateNetwork(virConnectPtr conn, const char *xml)
+{
+    ConnectionData *connection_data = conn->networkPrivateData;
+    phyp_driverPtr phyp_driver = conn->privateData;
+    LIBSSH2_SESSION *session = connection_data->session;
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    uuid_nettablePtr uuid_nettable = phyp_driver->uuid_nettable;
+    char *managed_system = phyp_driver->managed_system;
+    int system_type = phyp_driver->system_type;
+    int exit_status = 0;
+    char *char_ptr;
+    char *cmd = NULL;
+    int lpar_id = 0;
+    int slot = 0;
+    char *ret = NULL;
+    unsigned int i = 0;
+    long long mac = 0;
+    unsigned char *uuid = NULL;
+    char *name = NULL;
+    virNetworkDefPtr def;
+
+    if (VIR_ALLOC_N(name, NETNAME_SIZE) < 0) {
+        virReportOOMError();
+        goto err;
+    }
+
+    if (VIR_ALLOC_N(uuid, VIR_UUID_BUFLEN) < 0) {
+        virReportOOMError();
+        goto err;
+    }
+
+    if (!(def = virNetworkDefParseString(xml)))
+        goto err;
+
+    /* Checking for duplicate uuid */
+    if (def->uuid && virUUIDIsValid(def->uuid)) {
+        for (i = 0; i < uuid_nettable->nnets; i++) {
+            if (uuid_nettable->nets[i]->uuid == def->uuid) {
+                VIR_ERROR(_("UUID %s already exists"), name);
+                goto duplicate_uuid;
+            }
+        }
+        if (!memcpy(uuid, def->uuid, VIR_UUID_BUFLEN))
+            goto err;
+
+        goto good_uuid;
+    }
+
+  duplicate_uuid:
+
+    /*generate a new uuid */
+    if (virUUIDGenerate(uuid) < 0)
+        goto err;
+
+  good_uuid:
+
+    if (def->name)
+        VIR_WARN0
+            ("Name will be ignored, hypervisor must create one automatically.");
+
+    if (!def->domain) {
+        VIR_ERROR0(_("Domain can't be NULL, you must especify in which"
+                     "domain you want to add the new network interface."));
+        goto err;
+    }
+
+    if ((lpar_id =
+         phypGetLparID(session, managed_system, def->domain, conn)) < 0)
+        goto err;
+
+    /* Now need to get the next free slot number */
+    virBufferAddLit(&buf, "lshwres ");
+    if (system_type == HMC)
+        virBufferVSprintf(&buf, "-m %s ", managed_system);
+
+    virBufferVSprintf(&buf,
+                      " -r virtualio --rsubtype slot --level slot"
+                      " -Fslot_num --filter lpar_ids=%d"
+                      " |sort|tail -n 1", lpar_id);
+
+    if (virBufferError(&buf)) {
+        virBufferFreeAndReset(&buf);
+        virReportOOMError();
+        goto err;
+    }
+    cmd = virBufferContentAndReset(&buf);
+
+    ret = phypExec(session, cmd, &exit_status, conn);
+
+    if (exit_status < 0 || ret == NULL)
+        goto err;
+
+    if (virStrToLong_i(ret, &char_ptr, 10, &slot) == -1)
+        goto err;
+
+    /* The next free slot itself: */
+    slot++;
+
+    /* Now addig the new network interface */
+    virBufferAddLit(&buf, "chhwres ");
+    if (system_type == HMC)
+        virBufferVSprintf(&buf, "-m %s ", managed_system);
+
+    virBufferVSprintf(&buf,
+                      " -r virtualio --rsubtype eth"
+                      " --id %d -o a -s %d -a port_vlan_id=1,"
+                      "ieee_virtual_eth=0", lpar_id, slot);
+
+    if (virBufferError(&buf)) {
+        virBufferFreeAndReset(&buf);
+        virReportOOMError();
+        goto err;
+    }
+    cmd = virBufferContentAndReset(&buf);
+
+    ret = phypExec(session, cmd, &exit_status, conn);
+
+    if (exit_status < 0 || ret != NULL)
+        goto err;
+
+    /* Need to sleep a little while to wait for the HMC to
+     * complete the execution of the command.
+     * */
+    sleep(1);
+
+    /* Getting the new interface name */
+    virBufferAddLit(&buf, "lshwres ");
+    if (system_type == HMC)
+        virBufferVSprintf(&buf, "-m %s ", managed_system);
+
+    virBufferVSprintf(&buf,
+                      " -r virtualio --rsubtype slot --level slot"
+                      " |grep lpar_id=%d|grep slot_num=%d|"
+                      " sed -e 's/^.*drc_name=//g'", lpar_id, slot);
+
+    if (virBufferError(&buf)) {
+        virBufferFreeAndReset(&buf);
+        virReportOOMError();
+        goto err;
+    }
+    cmd = virBufferContentAndReset(&buf);
+
+    ret = phypExec(session, cmd, &exit_status, conn);
+
+    if (exit_status < 0 || ret == NULL)
+        goto err;
+
+    char_ptr = NULL;
+    char_ptr = strchr(ret, '\n');
+
+    if (char_ptr)
+        *char_ptr = '\0';
+
+    if (memcpy(name, ret, NETNAME_SIZE) == NULL)
+        goto err;
+
+    /* Getting the new interface mac addr */
+    virBufferAddLit(&buf, "lshwres ");
+    if (system_type == HMC)
+        virBufferVSprintf(&buf, "-m %s ", managed_system);
+
+    virBufferVSprintf(&buf,
+                      "-r virtualio --rsubtype eth --level lpar "
+                      "|grep lpar_id=%d|grep slot_num=%d|"
+                      " sed -e 's/^.*mac_addr=//g'", lpar_id, slot);
+
+    if (virBufferError(&buf)) {
+        virBufferFreeAndReset(&buf);
+        virReportOOMError();
+        goto err;
+    }
+    cmd = virBufferContentAndReset(&buf);
+
+    ret = phypExec(session, cmd, &exit_status, conn);
+
+    if (exit_status < 0 || ret == NULL)
+        goto err;
+
+    if (virStrToLong_ll(ret, &char_ptr, 10, &mac) == -1)
+        goto err;
+
+    /* Adding the new interface to the uuid database: */
+    if (phypUUIDTable_AddNetwork(conn, uuid, mac, name) < 0)
+        goto err;
+
+    VIR_FREE(cmd);
+    VIR_FREE(ret);
+    return virGetNetwork(conn, name, uuid);
+
+  err:
+    VIR_FREE(name);
+    VIR_FREE(cmd);
+    VIR_FREE(ret);
+    VIR_FREE(uuid);
+    return NULL;
+}
+
+static int
+networkIsActive(virNetworkPtr net)
+{
+    ConnectionData *connection_data = net->conn->networkPrivateData;
+    phyp_driverPtr phyp_driver = net->conn->privateData;
+    LIBSSH2_SESSION *session = connection_data->session;
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    uuid_nettablePtr uuid_nettable = phyp_driver->uuid_nettable;
+    char *managed_system = phyp_driver->managed_system;
+    int system_type = phyp_driver->system_type;
+    int exit_status = 0;
+    int state = 0;
+    char *char_ptr;
+    char *cmd = NULL;
+    char *ret = NULL;
+    unsigned int i = 0;
+    long long mac = 0;
+
+    for (i = 0; i < uuid_nettable->nnets; i++) {
+        if (uuid_nettable->nets[i]->uuid == net->uuid) {
+            mac = uuid_nettable->nets[i]->mac;
+            break;
+        }
+    }
+
+    virBufferAddLit(&buf, "lshwres ");
+    if (system_type == HMC)
+        virBufferVSprintf(&buf, "-m %s ", managed_system);
+
+    virBufferVSprintf(&buf,
+                      "-r virtualio --rsubtype eth --level lpar "
+                      "-F mac_addr,state |grep %lld|"
+                      "sed -e 's/^.*,//g'", mac);
+
+    if (virBufferError(&buf)) {
+        virBufferFreeAndReset(&buf);
+        virReportOOMError();
+        return -1;
+    }
+    cmd = virBufferContentAndReset(&buf);
+
+    ret = phypExec(session, cmd, &exit_status, net->conn);
+
+    if (exit_status < 0 || ret == NULL)
+        goto err;
+
+    if (virStrToLong_i(ret, &char_ptr, 10, &state) == -1)
+        goto err;
+
+    if (char_ptr)
+        *char_ptr = '\0';
+
+    VIR_FREE(cmd);
+    return state;
+
+  err:
+    VIR_FREE(cmd);
+    VIR_FREE(ret);
+    return -1;
+
+}
+
+static virNetworkPtr
+phypNetworkLookupByName(virConnectPtr conn, const char *name)
+{
+
+    phyp_driverPtr phyp_driver = conn->privateData;
+    uuid_nettablePtr uuid_nettable = phyp_driver->uuid_nettable;
+    unsigned int i = 0;
+
+    for (i = 0; i < uuid_nettable->nnets; i++) {
+        if (STREQ(uuid_nettable->nets[i]->name, name))
+            return virGetNetwork(conn, name, uuid_nettable->nets[i]->uuid);
+    }
+
+    VIR_ERROR(_("No network found matching %s "), name);
+    return NULL;
+}
+
 int
 phypListNetworkMAC(virConnectPtr conn, long long *macs, int nnets)
 {
@@ -3834,17 +4224,17 @@ static virNetworkDriver phypNetworkDriver = {
     .numOfDefinedNetworks = NULL,
     .listDefinedNetworks = NULL,
     .networkLookupByUUID = NULL,
-    .networkLookupByName = NULL,
-    .networkCreateXML = NULL,
+    .networkLookupByName = phypNetworkLookupByName,
+    .networkCreateXML = phypCreateNetwork,
     .networkDefineXML = NULL,
     .networkUndefine = NULL,
     .networkCreate = NULL,
-    .networkDestroy = NULL,
+    .networkDestroy = networkDestroy,
     .networkDumpXML = NULL,
     .networkGetBridgeName = NULL,
     .networkGetAutostart = NULL,
     .networkSetAutostart = NULL,
-    .networkIsActive = NULL,
+    .networkIsActive = networkIsActive,
     .networkIsPersistent = NULL
 };
 
diff --git a/src/phyp/phyp_driver.h b/src/phyp/phyp_driver.h
index 603d048..34ad84b 100644
--- a/src/phyp/phyp_driver.h
+++ b/src/phyp/phyp_driver.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2010 Red Hat, Inc.
- * Copyright IBM Corp. 2009
+ * Copyright IBM Corp. 2010
  *
  * phyp_driver.c: ssh layer to access Power Hypervisors
  *
-- 
1.7.1




More information about the libvir-list mailing list