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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list