Now adding some basic operation network functions and its UUID "helpers". --- src/phyp/phyp_driver.c | 202 ++++++++++++++++++++++++++++++++++++++++++++++- src/phyp/phyp_uuid.c | 177 ++++++++++++++++++++++++++++++++++++++++++ src/phyp/phyp_uuid.h | 8 ++ 3 files changed, 382 insertions(+), 5 deletions(-) diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 6f3f49d..c44fc69 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -667,6 +667,7 @@ phypOpen(virConnectPtr conn, size_t len = 0; int internal_socket; uuid_tablePtr uuid_table = NULL; + uuid_nettablePtr uuid_nettable = NULL; phyp_driverPtr phyp_driver = NULL; char *char_ptr; char *managed_system = NULL; @@ -693,6 +694,11 @@ phypOpen(virConnectPtr conn, goto failure; } + if (VIR_ALLOC(uuid_nettable) < 0) { + virReportOOMError(); + goto failure; + } + if (VIR_ALLOC(connection_data) < 0) { virReportOOMError(); goto failure; @@ -744,10 +750,15 @@ phypOpen(virConnectPtr conn, uuid_table->nlpars = 0; uuid_table->lpars = NULL; + uuid_nettable->nnets = 0; + uuid_nettable->nets = NULL; + if (conn->uri->path) phyp_driver->managed_system = managed_system; phyp_driver->uuid_table = uuid_table; + phyp_driver->uuid_nettable = uuid_nettable; + if ((phyp_driver->caps = phypCapsInit()) == NULL) { virReportOOMError(); goto failure; @@ -759,14 +770,17 @@ phypOpen(virConnectPtr conn, if ((phyp_driver->system_type = phypGetSystemType(conn)) == -1) goto failure; - if (phypUUIDTable_Init(conn) == -1) - goto failure; - if (phyp_driver->system_type == HMC) { if ((phyp_driver->vios_id = phypGetVIOSPartitionID(conn)) == -1) goto failure; } + if (phypUUIDTable_Init(conn) == -1) + goto failure; + + if (phypUUIDNetworkTable_Init(conn) == -1) + goto failure; + return VIR_DRV_OPEN_SUCCESS; failure: @@ -777,6 +791,7 @@ phypOpen(virConnectPtr conn, } phypUUIDTable_Free(uuid_table); + phypUUIDNetworkTable_Free(uuid_nettable); if (session != NULL) { libssh2_session_disconnect(session, "Disconnecting..."); @@ -801,6 +816,7 @@ phypClose(virConnectPtr conn) virCapabilitiesFree(phyp_driver->caps); phypUUIDTable_Free(phyp_driver->uuid_table); + phypUUIDNetworkTable_Free(phyp_driver->uuid_nettable); VIR_FREE(phyp_driver->managed_system); VIR_FREE(phyp_driver); VIR_FREE(connection_data); @@ -2813,6 +2829,182 @@ phypGetStoragePoolXMLDesc(virStoragePoolPtr pool, unsigned int flags) return NULL; } +int +phypListNetworkMAC(virConnectPtr conn, long long *macs, int nnets) +{ + ConnectionData *connection_data = conn->networkPrivateData; + phyp_driverPtr phyp_driver = conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + int system_type = phyp_driver->system_type; + char *managed_system = phyp_driver->managed_system; + int vios_id = phyp_driver->vios_id; + int exit_status = 0; + int got = -1; + char *cmd = NULL; + char *ret = NULL; + char *line, *next_line; + virBuffer buf = VIR_BUFFER_INITIALIZER; + + virBufferAddLit(&buf, "lshwres"); + if (system_type == HMC) + virBufferVSprintf(&buf, " -m %s", managed_system); + + virBufferVSprintf(&buf, " -r virtualio --rsubtype eth --level lpar" + "|grep -v lpar_id=%d| sed -e 's/^.*mac_addr=//g'", + vios_id); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return -1; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, conn); + + if (exit_status < 0 || ret == NULL) + goto err; + + /* I need to parse the textual return in order to get the macs */ + line = ret; + got = 0; + while (*line && got < nnets) { + if (virStrToLong_ll(line, &next_line, 10, &macs[got]) == -1) { + VIR_ERROR(_("Cannot parse number from '%s'"), line); + got = -1; + goto err; + } + got++; + line = next_line; + while (*line == '\n') + line++; /* skip \n */ + } + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return got; +} + +int +phypListNetworks(virConnectPtr conn, char **const names, int nnames) +{ + ConnectionData *connection_data = conn->networkPrivateData; + phyp_driverPtr phyp_driver = conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + int system_type = phyp_driver->system_type; + char *managed_system = phyp_driver->managed_system; + int vios_id = phyp_driver->vios_id; + int exit_status = 0; + int got = 0; + int i; + char *cmd = NULL; + char *ret = NULL; + char *networks = NULL; + char *char_ptr2 = NULL; + virBuffer buf = VIR_BUFFER_INITIALIZER; + + virBufferAddLit(&buf, "lshwres"); + if (system_type == HMC) + virBufferVSprintf(&buf, " -m %s", managed_system); + virBufferVSprintf(&buf, " -r virtualio --rsubtype slot --level slot" + "|grep eth|grep -v lpar_id=%d|" + "sed -e 's/^.*drc_name=//g'", vios_id); + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return -1; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, conn); + + /* I need to parse the textual return in order to get the network interfaces */ + if (exit_status < 0 || ret == NULL) + goto err; + else { + networks = ret; + + while (got < nnames) { + char_ptr2 = strchr(networks, '\n'); + + if (char_ptr2) { + *char_ptr2 = '\0'; + if ((names[got++] = strdup(networks)) == NULL) { + virReportOOMError(); + goto err; + } + char_ptr2++; + networks = char_ptr2; + } else + break; + } + } + + VIR_FREE(cmd); + VIR_FREE(ret); + return got; + + err: + for (i = 0; i < got; i++) + VIR_FREE(names[i]); + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; +} + +int +phypNumOfNetworks(virConnectPtr conn) +{ + ConnectionData *connection_data = conn->networkPrivateData; + phyp_driverPtr phyp_driver = conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + char *managed_system = phyp_driver->managed_system; + int system_type = phyp_driver->system_type; + int vios_id = phyp_driver->vios_id; + int exit_status = 0; + int nnets = 0; + char *char_ptr; + char *cmd = NULL; + char *ret = NULL; + virBuffer buf = VIR_BUFFER_INITIALIZER; + + virBufferAddLit(&buf, "lshwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + "-r virtualio --rsubtype eth --level lpar|" + "grep -v lpar_id=%d|grep -c lpar_name", vios_id); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return -1; + } + 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, &nnets) == -1) + goto err; + + if (char_ptr) + *char_ptr = '\0'; + + VIR_FREE(cmd); + return nnets; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; + +} + static int phypGetLparState(virConnectPtr conn, unsigned int lpar_id) { @@ -3637,8 +3829,8 @@ static virNetworkDriver phypNetworkDriver = { .name = "PHYP", .open = phypVIOSDriverOpen, .close = phypVIOSDriverClose, - .numOfNetworks = NULL, - .listNetworks = NULL, + .numOfNetworks = phypNumOfNetworks, + .listNetworks = phypListNetworks, .numOfDefinedNetworks = NULL, .listDefinedNetworks = NULL, .networkLookupByUUID = NULL, diff --git a/src/phyp/phyp_uuid.c b/src/phyp/phyp_uuid.c index a97dd44..c4a0cc2 100644 --- a/src/phyp/phyp_uuid.c +++ b/src/phyp/phyp_uuid.c @@ -655,3 +655,180 @@ phypUUIDTable_Free(uuid_tablePtr uuid_table) VIR_FREE(uuid_table->lpars); VIR_FREE(uuid_table); } + +int +phypUUIDTable_RemNetwork(virConnectPtr conn, long long mac) +{ + 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 (uuid_nettable->nets[i]->mac == mac) { + uuid_nettable->nets[i]->mac = -1; + memset(uuid_nettable->nets[i]->uuid, 0, VIR_UUID_BUFLEN); + break; + } + } + + if (phypUUIDTable_WriteFile(conn, NET) == -1) + goto err; + + if (phypUUIDTable_Push(conn, NET) == -1) + goto err; + + return 0; + + err: + return -1; +} + +int +phypUUIDTable_AddNetwork(virConnectPtr conn, unsigned char *uuid, + long long mac, char *name) +{ + phyp_driverPtr phyp_driver = conn->privateData; + uuid_nettablePtr uuid_nettable = phyp_driver->uuid_nettable; + + unsigned int i = uuid_nettable->nnets; + uuid_nettable->nnets++; + + if (VIR_REALLOC_N(uuid_nettable->nets, uuid_nettable->nnets) < 0) { + virReportOOMError(); + goto err; + } + + if (VIR_ALLOC(uuid_nettable->nets[i]) < 0) { + virReportOOMError(); + goto err; + } + + uuid_nettable->nets[i]->mac = mac; + memmove(uuid_nettable->nets[i]->uuid, uuid, VIR_UUID_BUFLEN); + memmove(uuid_nettable->nets[i]->name, name, NETNAME_SIZE); + + if (phypUUIDTable_WriteFile(conn, NET) == -1) + goto err; + + if (phypUUIDTable_Push(conn, NET) == -1) + goto err; + + return 0; + + err: + return -1; +} + +int +phypUUIDNetworkTable_Init(virConnectPtr conn) +{ + uuid_nettablePtr uuid_nettable; + phyp_driverPtr phyp_driver; + int nnets_numnetworks = 0; + int nnets_listnetworks = 0; + long long *macs = NULL; + char **names = NULL; + unsigned int i = 0; + + if ((nnets_numnetworks = phypNumOfNetworks(conn)) < 0) + goto err; + + if (VIR_ALLOC_N(macs, nnets_numnetworks) < 0) { + virReportOOMError(); + goto err; + } + + if ((nnets_listnetworks = + phypListNetworkMAC(conn, macs, nnets_numnetworks)) < 0) + goto err; + + /* exit early if there are no domains */ + if (nnets_numnetworks == 0 && nnets_listnetworks == 0) + goto exit; + else if (nnets_numnetworks != nnets_listnetworks) { + VIR_ERROR0(_ + ("Unable to determine number of networks interfaces.")); + goto err; + } + + if (VIR_ALLOC_N(names, nnets_numnetworks) < 0) { + virReportOOMError(); + goto err; + } + + for (i = 0; i < nnets_numnetworks; i++) { + if (VIR_ALLOC_N(names[i], NETNAME_SIZE) < 0) { + virReportOOMError(); + goto err; + } + } + + if (phypListNetworks(conn, names, nnets_numnetworks) < 0) + goto err; + + phyp_driver = conn->privateData; + uuid_nettable = phyp_driver->uuid_nettable; + uuid_nettable->nnets = nnets_listnetworks; + + /* try to get the table from server */ + if (phypUUIDTable_Pull(conn, NET) == -1) { + /* file not found in the server, creating a new one */ + if (VIR_ALLOC_N(uuid_nettable->nets, uuid_nettable->nnets) >= 0) { + for (i = 0; i < uuid_nettable->nnets; i++) { + if (VIR_ALLOC(uuid_nettable->nets[i]) < 0) { + virReportOOMError(); + goto err; + } + uuid_nettable->nets[i]->mac = macs[i]; + + if (memcpy + (uuid_nettable->nets[i]->name, names[i], + NETNAME_SIZE) == NULL) + goto err; + + if (virUUIDGenerate(uuid_nettable->nets[i]->uuid) < 0) + VIR_WARN + ("Unable to generate UUID for Network with MAC %lld", + macs[i]); + } + } else { + virReportOOMError(); + goto err; + } + + if (phypUUIDTable_WriteFile(conn, NET) == -1) + goto err; + + if (phypUUIDTable_Push(conn, NET) == -1) + goto err; + } else { + if (phypUUIDTable_ReadFile(conn, NET) == -1) + goto err; + goto exit; + } + + exit: + VIR_FREE(macs); + VIR_FREE(names); + return 0; + + err: + VIR_FREE(macs); + VIR_FREE(names); + return -1; +} + +void +phypUUIDNetworkTable_Free(uuid_nettablePtr uuid_nettable) +{ + int i; + + if (uuid_nettable == NULL) + return; + + for (i = 0; i < uuid_nettable->nnets; i++) + VIR_FREE(uuid_nettable->nets[i]); + + VIR_FREE(uuid_nettable->nets); + VIR_FREE(uuid_nettable); +} diff --git a/src/phyp/phyp_uuid.h b/src/phyp/phyp_uuid.h index ddf28f4..90a0178 100644 --- a/src/phyp/phyp_uuid.h +++ b/src/phyp/phyp_uuid.h @@ -34,3 +34,11 @@ void phypUUIDTable_Free(uuid_tablePtr uuid_table); int phypUUIDTable_RemLpar(virConnectPtr conn, int id); int phypUUIDTable_AddLpar(virConnectPtr conn, unsigned char *uuid, int id); + +int phypUUIDNetworkTable_Init(virConnectPtr conn); + +void phypUUIDNetworkTable_Free(uuid_nettablePtr uuid_table); + +int phypUUIDTable_AddNetwork(virConnectPtr conn, unsigned char *uuid, long long mac, char *name); + +int phypUUIDTable_RemNetwork(virConnectPtr conn, long long mac); -- 1.7.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list