[libvirt] [PATCH 0/3] PHYP: Adding network management support

This is a series of 3 patches to add network management support for pHyp driver. Eduardo Otubo (3): PHYP: Separating UUID functions in another file PHYP: Adding basic network functions PHYP: create, destroy and other network functions po/POTFILES.in | 1 + src/Makefile.am | 3 +- src/phyp/phyp_driver.c | 1066 +++++++++++++++++++++++++++--------------------- src/phyp/phyp_driver.h | 43 ++- src/phyp/phyp_uuid.c | 834 +++++++++++++++++++++++++++++++++++++ src/phyp/phyp_uuid.h | 44 ++ 6 files changed, 1520 insertions(+), 471 deletions(-) create mode 100644 src/phyp/phyp_uuid.c create mode 100644 src/phyp/phyp_uuid.h

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

On 11/19/2010 07:55 AM, Eduardo Otubo wrote:
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
[I've rearranged my review a bit; .h before .c]
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. + * ... + +#include <config.h>
While there are other counter-examples currently in libvirt.git, the general rule of thumb tends to be that .c files should include config.h first before any headers, and therefore .h files should not include it (because it will already have been included by the .c file including this .h).
+ +int phypUUIDTable_Init(virConnectPtr conn);
Where is virConnectPtr defined? This header should be self-contained, rather than relying on the .c file to include pre-requisite headers.
+ +void phypUUIDTable_Free(uuid_tablePtr uuid_table);
Where is uuid_tablePtr defined? Did you mean int? Or should phypUUIDTable_Init be returning a uuid_tablePtr instead of an int?
+ +int phypUUIDTable_RemLpar(virConnectPtr conn, int id); + +int phypUUIDTable_AddLpar(virConnectPtr conn, unsigned char *uuid, int id);
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
Is this adequate? What's your rationale for this size?
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;
Typically a mac is 6 bytes, not 8. Is sign extension going to be a problem?
+ 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
s/int/size_t/ 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);
Why is this not in the phyp namespace?
+ +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_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)
See earlier question about namespace. You should probably rename it in a separate patch prior to this one, so that the bulk of this patch will be just code motion with no renaming. In fact, when doing a refactor like this, splitting it into multiple steps makes it easier to review: + function renames and signature changes (for example, phypUUIDTable_WriteFile gaining an int type parameter), even though the new parameters have a constant value of DOMAIN + code motion into new files + add new code, by adding support for NET value alongside existing DOMAIN value of parameters added in first patch That way, the two real changes have a smaller line count, and the large line-count code motion change provably has 0 semantic change because it has no subtle differences introduced between the old and new location. That said, I'll go ahead and glance through the rest of this, but my review is very spotty because I'd like to see it broken into three commits before I do a thorough review (in fact, it looks like your static helper functions add NET support in this patch, but that you didn't ever pass NET to those functions until a later patch; my suggestion is therefore to refactor it to have the NET code in the static functions added at the same time or just before the code that uses it, but not during the code motion).
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)
Pre-existing code question: Why is the ./uuid_table file created with executable permissions? And why world-readable - is any process with a different euid ever expected to read it?
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 + * ... +#include <config.h> + +#include <stdlib.h> +#include <stdio.h> +#include <libssh2.h>
Does configure.ac guarantee that this header exists if phyp is enabled, or are you lacking include guards? [answering myself] yes, configure.ac guarantees libssh2 for phyp, so no problem here.
+#include <domain_event.h>
This is an internal file rather than a system header; it should be "domain_event.h".
+static unsigned const int NET = 0; +static unsigned const int DOMAIN = 1;
Generally, I prefer enums over static ints; also, I would have put DOMAIN as 0 and NET as 1 since NET is the new code and since NET sorts after DOMAIN.
+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";
This repetition of file names is begging for a #DEFINE.
+ +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);
Seems like a case for strdup() rather than the overhead of a virBuffer, if all the buffer will ever hold is a copy of a single other string.
+ + if (virBufferError(&username)) { + virBufferFreeAndReset(&username); + virReportOOMError(); + goto err; + } + } + + if (type == DOMAIN) { + if (virAsprintf(&local_file, "./uuid_table") < 0) {
Likewise, virAsprintf seems like overkill when strdup() would do the job.
+ + if (stat(local_file, &local_fileinfo) == -1) { + VIR_WARN0("Unable to stat local file."); + goto err; + } + + if (!(fd = fopen(local_file, "rb"))) {
No need to stat() a file if you are just going to follow it with fopen(); just open it, and fopen() will fail with the same reason as stat() would have failed if it can't be done.
+ VIR_WARN0("Unable to open local file."); + goto err; + } + + do { + channel = + libssh2_scp_send(session, remote_file, + 0x1FF & local_fileinfo.st_mode,
File modes should usually be treated as octal, not hex constants (0777 rather than 0x1ff).
+ +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--;
Why not just: unsigned int i = uuid_table->nlpars - 1;
+ + uuid_table->lpars[i]->id = id; + memmove(uuid_table->lpars[i]->uuid, uuid, VIR_UUID_BUFLEN);
These don't overlap, you can use memcpy() for speed. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On 11/19/2010 07:37 PM, Eric Blake wrote:
On 11/19/2010 07:55 AM, Eduardo Otubo wrote:
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
[I've rearranged my review a bit; .h before .c]
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. + * ... + +#include<config.h>
While there are other counter-examples currently in libvirt.git, the general rule of thumb tends to be that .c files should include config.h first before any headers, and therefore .h files should not include it (because it will already have been included by the .c file including this .h).
And regarding all your comments, I'll fix and reply in my next patch using virInterface API. Thank you very much for all the comments. :) Regards, -- Eduardo Otubo Software Engineer Linux Technology Center IBM Systems & Technology Group Mobile: +55 19 8135 0885 eotubo@linux.vnet.ibm.com

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

On 11/19/2010 07:55 AM, Eduardo Otubo wrote:
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(-)
+int +phypListNetworkMAC(virConnectPtr conn, long long *macs, int nnets)
This should probably be static.
+{ + 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'",
That two-process grep | sed is more efficient as one, and ^ can only match once, so the g is pointless: | sed '/lpar_id=%d/d; s/^.*mac_addr=//'
+int +phypListNetworks(virConnectPtr conn, char **const names, int nnames)
Likewise a candidate for static (in fact, it's sometimes a good idea to mark everything new as static, see what doesn't compile, and fix the few fallouts - it's always better to shoot for the smallest possible scope).
+ 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);
Here, you can replace grep | grep | sed with: sed -n '/lpar_id=%d/d; /eth/ s/^.*drc_name=//p' Mostly looks okay, but there's still the issue of using long long instead of a 6-byte array for MACs that might be worth changing. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

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

On 11/19/2010 07:55 AM, Eduardo Otubo wrote:
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
s/scenarion/scenario/
+++ b/src/phyp/phyp_driver.c @@ -1,7 +1,7 @@
/* * Copyright (C) 2010 Red Hat, Inc. - * Copyright IBM Corp. 2009 + * Copyright IBM Corp. 2010
You should never remove copyright years; this would be okay as 2009-2010.
+ + 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);
Another grep | sed you can simplify: sed -n '/%s/ s/^.*,//p'
+ virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth --level lpar " + " -F mac_addr,slot_num|grep %lld|" + " sed -e 's/^.*,//g'", mac);
MACs are usually represented as hex, not decimal. And if it really is decimal, wouldn't you want unsigned? Simplify: sed -n '/%lld/ /^.*,//p'
+ + if (!def->domain) { + VIR_ERROR0(_("Domain can't be NULL, you must especify in which"
s/especify/specify/
+ + 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);
This seems racy, and 1 second is a long pause. Is there something more reliable you can use to tell whether HMC is done? Can you set up a retry loop and sleep for shorter periods of time with retries until it works to avoid a long pause?
+ + /* 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);
sed '/lpar_id=%d/!d; /slot_num=%d/!d; s/^.*drc_name=//'
+ /* 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);
Similar.
+ 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);
Another instance where decimal MAC seems odd. sed -n '/%lld/ s/^.*,//p'
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
This hunk seems completely random. Should it be rebased into another patch that actually touches phyp_driver.h? And should it be 2009-2010? -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On Fri, Nov 19, 2010 at 12:55:03PM -0200, Eduardo Otubo wrote:
This is a series of 3 patches to add network management support for pHyp driver.
Can you explain what sort of network connectivity you are managing here ? The virNetwork APIs are specifically for an IP layer virtual switch, that does IP forwarding, optionally with NAT. Reading the patches, it sounds more like you're trying to represent ethernet layer virtual switches (aka bridging to physical NICs). This is what the virInterface APIs are intended to cover So if my understanding is correct you need to implement the virInterface APIs rather than virNetwork APIs Regards, Daniel

On 11/22/2010 12:52 PM, Daniel P. Berrange wrote:
On Fri, Nov 19, 2010 at 12:55:03PM -0200, Eduardo Otubo wrote:
This is a series of 3 patches to add network management support for pHyp driver.
Can you explain what sort of network connectivity you are managing here ?
The virNetwork APIs are specifically for an IP layer virtual switch, that does IP forwarding, optionally with NAT.
Reading the patches, it sounds more like you're trying to represent ethernet layer virtual switches (aka bridging to physical NICs). This is what the virInterface APIs are intended to cover
So if my understanding is correct you need to implement the virInterface APIs rather than virNetwork APIs
I guess you're right. My initial idea was to describe the management of network interfaces. I was not aware of this virInterface API. Perhaps I should re write from the beginning, which will not take long since I have all the command calls ready and logic fresh in my head. Thanks you very much for the comment, will send a patch soon. -- Eduardo Otubo Software Engineer Linux Technology Center IBM Systems & Technology Group Mobile: +55 19 8135 0885 eotubo@linux.vnet.ibm.com

This is the implementation of the previous patch now using virInterface* API. Ended up this patch got much more simpler, smaller and easier to review. Here is some details: * MAC size and interface name are fixed due to specifications on HMC, both are created automatically and CAN'T be specified from user. They have the following format: * MAC: 122980003002 * Interface name: U9124.720.067BE8B-V3-C0 * I did replaced all the |grep|sed following the comments Eric Blake did on the last patch. * According to my last email, It's not possible to create a network interface without assigning it to a specific lpar. Then, I am using this very minimalistic XML file for testing: <interface type='ethernet' name='LPAR01'> </interface> In this file I am using "name" as the lpar name which I am going to assign the new network interface. I couldn't find a better way to refer to it. Comments are welcome. * Regarding the fact I am sleeping one second waiting for the HMC to complete creation of the interface, I don't have means to check if the whole process is done. All I do is execute a command, wait until is complete (which is not enough in this case) check the return and the exit status. The process of actually creating a networking interface seems to take a little longer than just the return of the ssh control. --- src/phyp/phyp_driver.c | 572 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 553 insertions(+), 19 deletions(-) diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 4c723a2..407f644 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -59,6 +59,7 @@ #include "storage_conf.h" #include "nodeinfo.h" #include "files.h" +#include "interface_conf.h" #include "phyp_driver.h" @@ -74,6 +75,8 @@ static unsigned const int HMC = 0; static unsigned const int IVM = 127; +static unsigned const int PHYP_IFACENAME_SIZE = 24; +static unsigned const int PHYP_MAC_SIZE= 12; static int waitsocket(int socket_fd, LIBSSH2_SESSION * session) @@ -3268,6 +3271,542 @@ phypGetStoragePoolXMLDesc(virStoragePoolPtr pool, unsigned int flags) } static int +phypInterfaceDestroy(virInterfacePtr iface, + unsigned int flags ATTRIBUTE_UNUSED) +{ + ConnectionData *connection_data = iface->conn->networkPrivateData; + phyp_driverPtr phyp_driver = iface->conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *managed_system = phyp_driver->managed_system; + int system_type = phyp_driver->system_type; + int exit_status = 0; + int slot_num = 0; + int lpar_id = 0; + char *char_ptr; + char *cmd = NULL; + char *ret = NULL; + + /* Getting the remote slot number */ + + char_ptr = NULL; + char_ptr = strchr(iface->mac, '\n'); + + if (char_ptr) + *char_ptr = '\0'; + + 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|" + " sed -n '/%s/ s/^.*,//p'", iface->mac); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return -1; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, iface->conn); + + if (exit_status < 0 || ret == NULL) + goto err; + + if (virStrToLong_i(ret, &char_ptr, 10, &slot_num) == -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,lpar_id|" + " sed -n '/%s/ s/^.*,//p'", iface->mac); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return -1; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, iface->conn); + + if (exit_status < 0 || ret == NULL) + goto err; + + if (virStrToLong_i(ret, &char_ptr, 10, &lpar_id) == -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, iface->conn); + + if (exit_status < 0 || ret != NULL) + goto err; + + VIR_FREE(cmd); + VIR_FREE(ret); + return 0; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; +} + +static virInterfacePtr +phypInterfaceDefineXML(virConnectPtr conn, const char *xml, + unsigned int flags ATTRIBUTE_UNUSED) +{ + ConnectionData *connection_data = conn->networkPrivateData; + phyp_driverPtr phyp_driver = conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + 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 slot = 0; + char *ret = NULL; + char *name = NULL; + char *mac = NULL; + virInterfaceDefPtr def; + + if (VIR_ALLOC_N(name, PHYP_IFACENAME_SIZE) < 0) { + virReportOOMError(); + goto err; + } + + if (VIR_ALLOC_N(mac, PHYP_MAC_SIZE) < 0) { + virReportOOMError(); + goto err; + } + + if (!(def = virInterfaceDefParseString(xml))) + 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_names=%s" + " |sort|tail -n 1", def->name); + + 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" + " -p %s -o a -s %d -a port_vlan_id=1," + "ieee_virtual_eth=0", def->name, 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" + " |sed '/lpar_name=%s/!d; /slot_num=%d/!d; " + "s/^.*drc_name=//'", def->name, 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, PHYP_IFACENAME_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 " + " |sed '/lpar_name=%s/!d; /slot_num=%d/!d; " + "s/^.*mac_addr=//'", def->name, 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 (memcpy(mac, ret, PHYP_IFACENAME_SIZE) == NULL) + goto err; + + VIR_FREE(cmd); + VIR_FREE(ret); + return virGetInterface(conn, name, mac); + + err: + VIR_FREE(name); + VIR_FREE(cmd); + VIR_FREE(ret); + return NULL; +} + +static virInterfacePtr +phypInterfaceLookupByName(virConnectPtr conn, const char *name) +{ + ConnectionData *connection_data = conn->networkPrivateData; + phyp_driverPtr phyp_driver = conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *managed_system = phyp_driver->managed_system; + int system_type = phyp_driver->system_type; + int exit_status = 0; + char *char_ptr; + char *cmd = NULL; + char *ret = NULL; + int slot = 0; + int lpar_id = 0; + + /*Getting the slot number for the interface */ + virBufferAddLit(&buf, "lshwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype slot --level slot " + " -F drc_name,slot_num |" + " sed -n '/%s/ s/^.*,//p'", name); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL; + } + 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; + + if (char_ptr) + *char_ptr = '\0'; + + /*Getting the lpar_id for the interface */ + 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 |" + " sed -n '/%s/ s/^.*,//p'", name); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL; + } + 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, &lpar_id) == -1) + goto err; + + if (char_ptr) + *char_ptr = '\0'; + + /*Getting the interface mac */ + virBufferAddLit(&buf, "lshwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth --level lpar " + " -F lpar_id,slot_num,mac_addr|" + " sed -n '/%d,%d/ s/^.*,//p'", lpar_id, slot); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, conn); + + if (exit_status < 0 || ret == NULL) + goto err; + + VIR_FREE(cmd); + return virGetInterface(conn, name, ret); + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return NULL; + +} + +static int +phypInterfaceIsActive(virInterfacePtr iface) +{ + ConnectionData *connection_data = iface->conn->networkPrivateData; + phyp_driverPtr phyp_driver = iface->conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + 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; + + 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 |" + " sed -n '/%s/ s/^.*,//p'", iface->mac); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return -1; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, iface->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 int +phypListInterfaces(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|" + " sed '/eth/!d; /lpar_id=%d/d; 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; +} + +static int +phypNumOfInterfaces(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) { ConnectionData *connection_data = conn->networkPrivateData; @@ -4087,27 +4626,22 @@ static virStorageDriver phypStorageDriver = { .poolIsPersistent = NULL }; -static virNetworkDriver phypNetworkDriver = { +static virInterfaceDriver phypInterfaceDriver = { .name = "PHYP", .open = phypVIOSDriverOpen, .close = phypVIOSDriverClose, - .numOfNetworks = NULL, - .listNetworks = NULL, - .numOfDefinedNetworks = NULL, - .listDefinedNetworks = NULL, - .networkLookupByUUID = NULL, - .networkLookupByName = NULL, - .networkCreateXML = NULL, - .networkDefineXML = NULL, - .networkUndefine = NULL, - .networkCreate = NULL, - .networkDestroy = NULL, - .networkDumpXML = NULL, - .networkGetBridgeName = NULL, - .networkGetAutostart = NULL, - .networkSetAutostart = NULL, - .networkIsActive = NULL, - .networkIsPersistent = NULL + .numOfInterfaces = phypNumOfInterfaces, + .listInterfaces = phypListInterfaces, + .numOfDefinedInterfaces = NULL, + .listDefinedInterfaces = NULL, + .interfaceLookupByName = phypInterfaceLookupByName, + .interfaceLookupByMACString = NULL, + .interfaceGetXMLDesc = NULL, + .interfaceDefineXML = phypInterfaceDefineXML, + .interfaceUndefine = NULL, + .interfaceCreate = NULL, + .interfaceDestroy = phypInterfaceDestroy, + .interfaceIsActive = phypInterfaceIsActive }; int @@ -4117,7 +4651,7 @@ phypRegister(void) return -1; if (virRegisterStorageDriver(&phypStorageDriver) < 0) return -1; - if (virRegisterNetworkDriver(&phypNetworkDriver) < 0) + if (virRegisterInterfaceDriver(&phypInterfaceDriver) < 0) return -1; return 0; -- 1.7.1

Sorry for the tops posting, but I was wondering if someone could take a look at my patch v2, thanks. Regards, On 11/22/2010 11:03 PM, Eduardo Otubo wrote:
This is the implementation of the previous patch now using virInterface* API. Ended up this patch got much more simpler, smaller and easier to review. Here is some details:
* MAC size and interface name are fixed due to specifications on HMC, both are created automatically and CAN'T be specified from user. They have the following format:
* MAC: 122980003002 * Interface name: U9124.720.067BE8B-V3-C0
* I did replaced all the |grep|sed following the comments Eric Blake did on the last patch.
* According to my last email, It's not possible to create a network interface without assigning it to a specific lpar. Then, I am using this very minimalistic XML file for testing:
<interface type='ethernet' name='LPAR01'> </interface>
In this file I am using "name" as the lpar name which I am going to assign the new network interface. I couldn't find a better way to refer to it. Comments are welcome.
* Regarding the fact I am sleeping one second waiting for the HMC to complete creation of the interface, I don't have means to check if the whole process is done. All I do is execute a command, wait until is complete (which is not enough in this case) check the return and the exit status. The process of actually creating a networking interface seems to take a little longer than just the return of the ssh control. --- src/phyp/phyp_driver.c | 572 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 553 insertions(+), 19 deletions(-)
diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 4c723a2..407f644 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -59,6 +59,7 @@ #include "storage_conf.h" #include "nodeinfo.h" #include "files.h" +#include "interface_conf.h"
#include "phyp_driver.h"
@@ -74,6 +75,8 @@
static unsigned const int HMC = 0; static unsigned const int IVM = 127; +static unsigned const int PHYP_IFACENAME_SIZE = 24; +static unsigned const int PHYP_MAC_SIZE= 12;
static int waitsocket(int socket_fd, LIBSSH2_SESSION * session) @@ -3268,6 +3271,542 @@ phypGetStoragePoolXMLDesc(virStoragePoolPtr pool, unsigned int flags) }
static int +phypInterfaceDestroy(virInterfacePtr iface, + unsigned int flags ATTRIBUTE_UNUSED) +{ + ConnectionData *connection_data = iface->conn->networkPrivateData; + phyp_driverPtr phyp_driver = iface->conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *managed_system = phyp_driver->managed_system; + int system_type = phyp_driver->system_type; + int exit_status = 0; + int slot_num = 0; + int lpar_id = 0; + char *char_ptr; + char *cmd = NULL; + char *ret = NULL; + + /* Getting the remote slot number */ + + char_ptr = NULL; + char_ptr = strchr(iface->mac, '\n'); + + if (char_ptr) + *char_ptr = '\0'; + + 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|" + " sed -n '/%s/ s/^.*,//p'", iface->mac); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return -1; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd,&exit_status, iface->conn); + + if (exit_status< 0 || ret == NULL) + goto err; + + if (virStrToLong_i(ret,&char_ptr, 10,&slot_num) == -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,lpar_id|" + " sed -n '/%s/ s/^.*,//p'", iface->mac); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return -1; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd,&exit_status, iface->conn); + + if (exit_status< 0 || ret == NULL) + goto err; + + if (virStrToLong_i(ret,&char_ptr, 10,&lpar_id) == -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, iface->conn); + + if (exit_status< 0 || ret != NULL) + goto err; + + VIR_FREE(cmd); + VIR_FREE(ret); + return 0; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; +} + +static virInterfacePtr +phypInterfaceDefineXML(virConnectPtr conn, const char *xml, + unsigned int flags ATTRIBUTE_UNUSED) +{ + ConnectionData *connection_data = conn->networkPrivateData; + phyp_driverPtr phyp_driver = conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + 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 slot = 0; + char *ret = NULL; + char *name = NULL; + char *mac = NULL; + virInterfaceDefPtr def; + + if (VIR_ALLOC_N(name, PHYP_IFACENAME_SIZE)< 0) { + virReportOOMError(); + goto err; + } + + if (VIR_ALLOC_N(mac, PHYP_MAC_SIZE)< 0) { + virReportOOMError(); + goto err; + } + + if (!(def = virInterfaceDefParseString(xml))) + 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_names=%s" + " |sort|tail -n 1", def->name); + + 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" + " -p %s -o a -s %d -a port_vlan_id=1," + "ieee_virtual_eth=0", def->name, 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" + " |sed '/lpar_name=%s/!d; /slot_num=%d/!d; " + "s/^.*drc_name=//'", def->name, 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, PHYP_IFACENAME_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 " + " |sed '/lpar_name=%s/!d; /slot_num=%d/!d; " + "s/^.*mac_addr=//'", def->name, 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 (memcpy(mac, ret, PHYP_IFACENAME_SIZE) == NULL) + goto err; + + VIR_FREE(cmd); + VIR_FREE(ret); + return virGetInterface(conn, name, mac); + + err: + VIR_FREE(name); + VIR_FREE(cmd); + VIR_FREE(ret); + return NULL; +} + +static virInterfacePtr +phypInterfaceLookupByName(virConnectPtr conn, const char *name) +{ + ConnectionData *connection_data = conn->networkPrivateData; + phyp_driverPtr phyp_driver = conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *managed_system = phyp_driver->managed_system; + int system_type = phyp_driver->system_type; + int exit_status = 0; + char *char_ptr; + char *cmd = NULL; + char *ret = NULL; + int slot = 0; + int lpar_id = 0; + + /*Getting the slot number for the interface */ + virBufferAddLit(&buf, "lshwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype slot --level slot " + " -F drc_name,slot_num |" + " sed -n '/%s/ s/^.*,//p'", name); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL; + } + 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; + + if (char_ptr) + *char_ptr = '\0'; + + /*Getting the lpar_id for the interface */ + 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 |" + " sed -n '/%s/ s/^.*,//p'", name); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL; + } + 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,&lpar_id) == -1) + goto err; + + if (char_ptr) + *char_ptr = '\0'; + + /*Getting the interface mac */ + virBufferAddLit(&buf, "lshwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth --level lpar " + " -F lpar_id,slot_num,mac_addr|" + " sed -n '/%d,%d/ s/^.*,//p'", lpar_id, slot); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd,&exit_status, conn); + + if (exit_status< 0 || ret == NULL) + goto err; + + VIR_FREE(cmd); + return virGetInterface(conn, name, ret); + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return NULL; + +} + +static int +phypInterfaceIsActive(virInterfacePtr iface) +{ + ConnectionData *connection_data = iface->conn->networkPrivateData; + phyp_driverPtr phyp_driver = iface->conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + 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; + + 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 |" + " sed -n '/%s/ s/^.*,//p'", iface->mac); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return -1; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd,&exit_status, iface->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 int +phypListInterfaces(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|" + " sed '/eth/!d; /lpar_id=%d/d; 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; +} + +static int +phypNumOfInterfaces(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) { ConnectionData *connection_data = conn->networkPrivateData; @@ -4087,27 +4626,22 @@ static virStorageDriver phypStorageDriver = { .poolIsPersistent = NULL };
-static virNetworkDriver phypNetworkDriver = { +static virInterfaceDriver phypInterfaceDriver = { .name = "PHYP", .open = phypVIOSDriverOpen, .close = phypVIOSDriverClose, - .numOfNetworks = NULL, - .listNetworks = NULL, - .numOfDefinedNetworks = NULL, - .listDefinedNetworks = NULL, - .networkLookupByUUID = NULL, - .networkLookupByName = NULL, - .networkCreateXML = NULL, - .networkDefineXML = NULL, - .networkUndefine = NULL, - .networkCreate = NULL, - .networkDestroy = NULL, - .networkDumpXML = NULL, - .networkGetBridgeName = NULL, - .networkGetAutostart = NULL, - .networkSetAutostart = NULL, - .networkIsActive = NULL, - .networkIsPersistent = NULL + .numOfInterfaces = phypNumOfInterfaces, + .listInterfaces = phypListInterfaces, + .numOfDefinedInterfaces = NULL, + .listDefinedInterfaces = NULL, + .interfaceLookupByName = phypInterfaceLookupByName, + .interfaceLookupByMACString = NULL, + .interfaceGetXMLDesc = NULL, + .interfaceDefineXML = phypInterfaceDefineXML, + .interfaceUndefine = NULL, + .interfaceCreate = NULL, + .interfaceDestroy = phypInterfaceDestroy, + .interfaceIsActive = phypInterfaceIsActive };
int @@ -4117,7 +4651,7 @@ phypRegister(void) return -1; if (virRegisterStorageDriver(&phypStorageDriver)< 0) return -1; - if (virRegisterNetworkDriver(&phypNetworkDriver)< 0) + if (virRegisterInterfaceDriver(&phypInterfaceDriver)< 0) return -1;
return 0;
-- Eduardo Otubo Software Engineer Linux Technology Center IBM Systems & Technology Group Mobile: +55 19 8135 0885 eotubo@linux.vnet.ibm.com

On 11/22/2010 06:03 PM, Eduardo Otubo wrote: Apologies for my review backlog (if you haven't guessed, I sometimes table big patches for later, then forget to come back rapidly).
This is the implementation of the previous patch now using virInterface* API. Ended up this patch got much more simpler, smaller and easier to review. Here is some details:
* MAC size and interface name are fixed due to specifications on HMC, both are created automatically and CAN'T be specified from user. They have the following format:
* MAC: 122980003002
HMC represents MAC as a decimal number? How hideous, but not your fault; and this comment in the commit message will be useful for anyone auditing the code in the future.
+ /* Getting the remote slot number */ + + char_ptr = NULL; + char_ptr = strchr(iface->mac, '\n');
Redundant assignments (delete the first line).
+ if (VIR_ALLOC_N(name, PHYP_IFACENAME_SIZE) < 0) { + virReportOOMError(); + goto err; + } + + if (VIR_ALLOC_N(mac, PHYP_MAC_SIZE) < 0) { + virReportOOMError(); + goto err; + }
Since these arrays are so small, it's faster to just stack-allocate them: char name[PHYP_IFACENAME_SIZE];
+ /* The next free slot itself: */ + slot++; + + /* Now addig the new network interface */
s/addig/adding/
+ if (exit_status < 0 || ret == NULL) + goto err; + + char_ptr = NULL; + char_ptr = strchr(ret, '\n');
Another redundant assignment.
+ if (memcpy(mac, ret, PHYP_IFACENAME_SIZE) == NULL) + goto err; + + VIR_FREE(cmd); + VIR_FREE(ret); + return virGetInterface(conn, name, mac); + + err: + VIR_FREE(name); + VIR_FREE(cmd); + VIR_FREE(ret); + return NULL;
This leaks name if you end up calling virGetInterface. And both paths leak mac. But if you change name and mac to be stack-allocated, then you don't have to worry about freeing them.
+ ret = phypExec(session, cmd, &exit_status, conn); + + if (exit_status < 0 || ret == NULL) + goto err; + + VIR_FREE(cmd); + return virGetInterface(conn, name, ret); + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return NULL;
This leaks ret if virGetInterface is called.
+ ret = phypExec(session, cmd, &exit_status, iface->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;
Another leak of ret.
+static int +phypListInterfaces(virConnectPtr conn, char **const names, int nnames)
s/int/size_t/
+ 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 {
Rather than indenting the rest of the function inside an else{} block, you can leave the code at the top level indentation since the if() block was an unconditional goto.
+ 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;
Another leak of ret.
int @@ -4117,7 +4651,7 @@ phypRegister(void) return -1; if (virRegisterStorageDriver(&phypStorageDriver) < 0) return -1; - if (virRegisterNetworkDriver(&phypNetworkDriver) < 0) + if (virRegisterInterfaceDriver(&phypInterfaceDriver) < 0)
Are you intending to replace NetworkDriver with InterfaceDriver, or should you be supporting both drivers simultaneously (although this may be more an indication of how unfamiliar I am with the difference between what the two drivers are supposed to provide). -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On 12/09/2010 07:16 PM, Eric Blake wrote:
On 11/22/2010 06:03 PM, Eduardo Otubo wrote:
Apologies for my review backlog (if you haven't guessed, I sometimes table big patches for later, then forget to come back rapidly).
No problem, I'll try to post earlier next time. Thanks anyway.
This is the implementation of the previous patch now using virInterface* API. Ended up this patch got much more simpler, smaller and easier to review. Here is some details:
* MAC size and interface name are fixed due to specifications on HMC, both are created automatically and CAN'T be specified from user. They have the following format:
* MAC: 122980003002
HMC represents MAC as a decimal number? How hideous, but not your fault; and this comment in the commit message will be useful for anyone auditing the code in the future.
Yeah, no way I understand this notation either. Keeping all the commit comments on the PATCHv3 I'll send right away.
+ /* Getting the remote slot number */ + + char_ptr = NULL; + char_ptr = strchr(iface->mac, '\n');
Redundant assignments (delete the first line).
ACK, fixed.
+ if (VIR_ALLOC_N(name, PHYP_IFACENAME_SIZE)< 0) { + virReportOOMError(); + goto err; + } + + if (VIR_ALLOC_N(mac, PHYP_MAC_SIZE)< 0) { + virReportOOMError(); + goto err; + }
Since these arrays are so small, it's faster to just stack-allocate them:
char name[PHYP_IFACENAME_SIZE];
ACK, fixed.
+ /* The next free slot itself: */ + slot++; + + /* Now addig the new network interface */
s/addig/adding/
ACK, fixed.
+ if (exit_status< 0 || ret == NULL) + goto err; + + char_ptr = NULL; + char_ptr = strchr(ret, '\n');
Another redundant assignment.
ACK, fixed.
+ if (memcpy(mac, ret, PHYP_IFACENAME_SIZE) == NULL) + goto err; + + VIR_FREE(cmd); + VIR_FREE(ret); + return virGetInterface(conn, name, mac); + + err: + VIR_FREE(name); + VIR_FREE(cmd); + VIR_FREE(ret); + return NULL;
This leaks name if you end up calling virGetInterface. And both paths leak mac. But if you change name and mac to be stack-allocated, then you don't have to worry about freeing them.
ACK, fixed.
+ ret = phypExec(session, cmd,&exit_status, conn); + + if (exit_status< 0 || ret == NULL) + goto err; + + VIR_FREE(cmd); + return virGetInterface(conn, name, ret); + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return NULL;
This leaks ret if virGetInterface is called.
ACK, fixed.
+ ret = phypExec(session, cmd,&exit_status, iface->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;
Another leak of ret.
ACK, fixed.
+static int +phypListInterfaces(virConnectPtr conn, char **const names, int nnames)
s/int/size_t/
+ 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 {
Rather than indenting the rest of the function inside an else{} block, you can leave the code at the top level indentation since the if() block was an unconditional goto.
ACK, fixed.
+ 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;
Another leak of ret.
ACK, fixed.
int @@ -4117,7 +4651,7 @@ phypRegister(void) return -1; if (virRegisterStorageDriver(&phypStorageDriver)< 0) return -1; - if (virRegisterNetworkDriver(&phypNetworkDriver)< 0) + if (virRegisterInterfaceDriver(&phypInterfaceDriver)< 0)
Are you intending to replace NetworkDriver with InterfaceDriver, or should you be supporting both drivers simultaneously (although this may be more an indication of how unfamiliar I am with the difference between what the two drivers are supposed to provide).
First option, I'll replace NetworkDriver with InterfaceDriver. I didn't know that there were an Interface API, my deep fault on this matter. As I said, I will keep all the commit comments for further needs. Sending now the PATCHv3. Thanks for the review. Regards, -- Eduardo Otubo Software Engineer Linux Technology Center IBM Systems & Technology Group Mobile: +55 19 8135 0885 eotubo@linux.vnet.ibm.com

This is the implementation of the previous patch now using virInterface* API. Ended up this patch got much more simpler, smaller and easier to review. Here is some details: * MAC size and interface name are fixed due to specifications on HMC, both are created automatically and CAN'T be specified from user. They have the following format: * MAC: 122980003002 * Interface name: U9124.720.067BE8B-V3-C0 * I did replaced all the |grep|sed following the comments Eric Blake did on the last patch. * According to my last email, It's not possible to create a network interface without assigning it to a specific lpar. Then, I am using this very minimalistic XML file for testing: <interface type='ethernet' name='LPAR01'> </interface> In this file I am using "name" as the lpar name which I am going to assign the new network interface. I couldn't find a better way to refer to it. Comments are welcome. * Regarding the fact I am sleeping one second waiting for the HMC to complete creation of the interface, I don't have means to check if the whole process is done. All I do is execute a command, wait until is complete (which is not enough in this case) check the return and the exit status. The process of actually creating a networking interface seems to take a little longer than just the return of the ssh control. --- src/phyp/phyp_driver.c | 565 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 546 insertions(+), 19 deletions(-) diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 3508891..40760a5 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -59,6 +59,7 @@ #include "storage_conf.h" #include "nodeinfo.h" #include "files.h" +#include "interface_conf.h" #include "phyp_driver.h" @@ -74,6 +75,8 @@ static unsigned const int HMC = 0; static unsigned const int IVM = 127; +static unsigned const int PHYP_IFACENAME_SIZE = 24; +static unsigned const int PHYP_MAC_SIZE= 12; static int waitsocket(int socket_fd, LIBSSH2_SESSION * session) @@ -3273,6 +3276,535 @@ phypGetStoragePoolXMLDesc(virStoragePoolPtr pool, unsigned int flags) } static int +phypInterfaceDestroy(virInterfacePtr iface, + unsigned int flags ATTRIBUTE_UNUSED) +{ + ConnectionData *connection_data = iface->conn->networkPrivateData; + phyp_driverPtr phyp_driver = iface->conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *managed_system = phyp_driver->managed_system; + int system_type = phyp_driver->system_type; + int exit_status = 0; + int slot_num = 0; + int lpar_id = 0; + char *char_ptr; + char *cmd = NULL; + char *ret = NULL; + + /* Getting the remote slot number */ + + char_ptr = strchr(iface->mac, '\n'); + + if (char_ptr) + *char_ptr = '\0'; + + 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|" + " sed -n '/%s/ s/^.*,//p'", iface->mac); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return -1; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, iface->conn); + + if (exit_status < 0 || ret == NULL) + goto err; + + if (virStrToLong_i(ret, &char_ptr, 10, &slot_num) == -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,lpar_id|" + " sed -n '/%s/ s/^.*,//p'", iface->mac); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return -1; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, iface->conn); + + if (exit_status < 0 || ret == NULL) + goto err; + + if (virStrToLong_i(ret, &char_ptr, 10, &lpar_id) == -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, iface->conn); + + if (exit_status < 0 || ret != NULL) + goto err; + + VIR_FREE(cmd); + VIR_FREE(ret); + return 0; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; +} + +static virInterfacePtr +phypInterfaceDefineXML(virConnectPtr conn, const char *xml, + unsigned int flags ATTRIBUTE_UNUSED) +{ + ConnectionData *connection_data = conn->networkPrivateData; + phyp_driverPtr phyp_driver = conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + 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 slot = 0; + char *ret = NULL; + char name[PHYP_IFACENAME_SIZE]; + char mac[PHYP_MAC_SIZE]; + virInterfaceDefPtr def; + + if (!(def = virInterfaceDefParseString(xml))) + 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_names=%s" + " |sort|tail -n 1", def->name); + + 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 adding the new network interface */ + virBufferAddLit(&buf, "chhwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth" + " -p %s -o a -s %d -a port_vlan_id=1," + "ieee_virtual_eth=0", def->name, 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" + " |sed '/lpar_name=%s/!d; /slot_num=%d/!d; " + "s/^.*drc_name=//'", def->name, 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 = strchr(ret, '\n'); + + if (char_ptr) + *char_ptr = '\0'; + + if (memcpy(name, ret, PHYP_IFACENAME_SIZE-1) == 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 " + " |sed '/lpar_name=%s/!d; /slot_num=%d/!d; " + "s/^.*mac_addr=//'", def->name, 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 (memcpy(mac, ret, PHYP_MAC_SIZE-1) == NULL) + goto err; + + VIR_FREE(cmd); + VIR_FREE(ret); + return virGetInterface(conn, name, mac); + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return NULL; +} + +static virInterfacePtr +phypInterfaceLookupByName(virConnectPtr conn, const char *name) +{ + ConnectionData *connection_data = conn->networkPrivateData; + phyp_driverPtr phyp_driver = conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *managed_system = phyp_driver->managed_system; + int system_type = phyp_driver->system_type; + int exit_status = 0; + char *char_ptr; + char *cmd = NULL; + char *ret = NULL; + int slot = 0; + int lpar_id = 0; + char mac[PHYP_MAC_SIZE]; + + /*Getting the slot number for the interface */ + virBufferAddLit(&buf, "lshwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype slot --level slot " + " -F drc_name,slot_num |" + " sed -n '/%s/ s/^.*,//p'", name); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL; + } + 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; + + if (char_ptr) + *char_ptr = '\0'; + + /*Getting the lpar_id for the interface */ + 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 |" + " sed -n '/%s/ s/^.*,//p'", name); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL; + } + 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, &lpar_id) == -1) + goto err; + + if (char_ptr) + *char_ptr = '\0'; + + /*Getting the interface mac */ + virBufferAddLit(&buf, "lshwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth --level lpar " + " -F lpar_id,slot_num,mac_addr|" + " sed -n '/%d,%d/ s/^.*,//p'", lpar_id, slot); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, conn); + + if (exit_status < 0 || ret == NULL) + goto err; + + if (memcpy(mac, ret, PHYP_MAC_SIZE-1) == NULL) + goto err; + + VIR_FREE(cmd); + VIR_FREE(ret); + return virGetInterface(conn, name, ret); + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return NULL; + +} + +static int +phypInterfaceIsActive(virInterfacePtr iface) +{ + ConnectionData *connection_data = iface->conn->networkPrivateData; + phyp_driverPtr phyp_driver = iface->conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + 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; + + 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 |" + " sed -n '/%s/ s/^.*,//p'", iface->mac); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return -1; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, iface->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); + VIR_FREE(ret); + return state; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; + +} + +static size_t +phypListInterfaces(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|" + " sed '/eth/!d; /lpar_id=%d/d; 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; + + 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; +} + +static int +phypNumOfInterfaces(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); + VIR_FREE(ret); + return nnets; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; + +} + +static int phypGetLparState(virConnectPtr conn, unsigned int lpar_id) { ConnectionData *connection_data = conn->networkPrivateData; @@ -4093,27 +4625,22 @@ static virStorageDriver phypStorageDriver = { .poolIsPersistent = NULL }; -static virNetworkDriver phypNetworkDriver = { +static virInterfaceDriver phypInterfaceDriver = { .name = "PHYP", .open = phypVIOSDriverOpen, .close = phypVIOSDriverClose, - .numOfNetworks = NULL, - .listNetworks = NULL, - .numOfDefinedNetworks = NULL, - .listDefinedNetworks = NULL, - .networkLookupByUUID = NULL, - .networkLookupByName = NULL, - .networkCreateXML = NULL, - .networkDefineXML = NULL, - .networkUndefine = NULL, - .networkCreate = NULL, - .networkDestroy = NULL, - .networkDumpXML = NULL, - .networkGetBridgeName = NULL, - .networkGetAutostart = NULL, - .networkSetAutostart = NULL, - .networkIsActive = NULL, - .networkIsPersistent = NULL + .numOfInterfaces = phypNumOfInterfaces, + .listInterfaces = phypListInterfaces, + .numOfDefinedInterfaces = NULL, + .listDefinedInterfaces = NULL, + .interfaceLookupByName = phypInterfaceLookupByName, + .interfaceLookupByMACString = NULL, + .interfaceGetXMLDesc = NULL, + .interfaceDefineXML = phypInterfaceDefineXML, + .interfaceUndefine = NULL, + .interfaceCreate = NULL, + .interfaceDestroy = phypInterfaceDestroy, + .interfaceIsActive = phypInterfaceIsActive }; int @@ -4123,7 +4650,7 @@ phypRegister(void) return -1; if (virRegisterStorageDriver(&phypStorageDriver) < 0) return -1; - if (virRegisterNetworkDriver(&phypNetworkDriver) < 0) + if (virRegisterInterfaceDriver(&phypInterfaceDriver) < 0) return -1; return 0; -- 1.7.1

On 12/13/2010 01:09 PM, Eduardo Otubo wrote:
This is the implementation of the previous patch now using virInterface* API. Ended up this patch got much more simpler, smaller and easier to review. Here is some details:
You may want to use --enable-compile-warnings=error at autogen.sh time, since it would have caught this bug: CC libvirt_driver_phyp_la-phyp_driver.lo cc1: warnings being treated as errors phyp/phyp_driver.c:4633:5: error: initialization from incompatible pointer type make[2]: *** [libvirt_driver_phyp_la-phyp_driver.lo] Error 1 Fixed by making phypListInterfaces return int.
static int +phypInterfaceDestroy(virInterfacePtr iface, + unsigned int flags ATTRIBUTE_UNUSED) +{
+ ret = phypExec(session, cmd, &exit_status, iface->conn); +
+ + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return -1;
Memory leak for ret; this should goto err rather than return.
+ } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, iface->conn);
Memory leak for the old value of ret; you need to VIR_FREE the old value before starting a new phypExec, or track the exec's in separate strings all of which get freed at the end.
+ if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return -1; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, iface->conn);
Two more leaks of ret.
+ +static virInterfacePtr +phypInterfaceDefineXML(virConnectPtr conn, const char *xml, + unsigned int flags ATTRIBUTE_UNUSED) +{ + ConnectionData *connection_data = conn->networkPrivateData; + phyp_driverPtr phyp_driver = conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + 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 slot = 0; + char *ret = NULL; + char name[PHYP_IFACENAME_SIZE]; + char mac[PHYP_MAC_SIZE]; + virInterfaceDefPtr def; +
Rather than marking flags as unused, it would be better to insert virCheckFlags(0,NULL).
+ + ret = phypExec(session, cmd, &exit_status, conn); + + if (exit_status < 0 || ret == NULL)
Can exit_status ever be less than 0? Or does it reflect the same values as a process exit status, where things like WIFEXITED apply, and where the result will always be in the range of uint16_t? But that's a question for the entire file, and not just this patch.
+ + ret = phypExec(session, cmd, &exit_status, conn);
Another case of leaking the old value of ret.
+ + ret = phypExec(session, cmd, &exit_status, conn);
and another.
+ + ret = phypExec(session, cmd, &exit_status, conn);
and another.
+static virInterfacePtr +phypInterfaceLookupByName(virConnectPtr conn, const char *name) +{ + + ret = phypExec(session, cmd, &exit_status, conn);
+ ret = phypExec(session, cmd, &exit_status, conn);
and another.
+ if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, conn);
again
+ + if (exit_status < 0 || ret == NULL) + goto err; + + if (memcpy(mac, ret, PHYP_MAC_SIZE-1) == NULL) + goto err; + + VIR_FREE(cmd); + VIR_FREE(ret); + return virGetInterface(conn, name, ret);
NULL pointer dereference, because you're trying to use ret after freeing it.
+static int +phypNumOfInterfaces(virConnectPtr conn) +{
+ + if (virStrToLong_i(ret, &char_ptr, 10, &nnets) == -1) + goto err; + + if (char_ptr) + *char_ptr = '\0';
What's this for? You don't use char_ptr in the rest of the function, and you're about to free ret, which is where char_ptr points. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On 12/14/2010 02:27 PM, Eric Blake wrote:
On 12/13/2010 01:09 PM, Eduardo Otubo wrote:
This is the implementation of the previous patch now using virInterface* API. Ended up this patch got much more simpler, smaller and easier to review. Here is some details:
You may want to use --enable-compile-warnings=error at autogen.sh time, since it would have caught this bug:
I actually didn't know about this option. Will use as default options from now on, thanks.
CC libvirt_driver_phyp_la-phyp_driver.lo cc1: warnings being treated as errors phyp/phyp_driver.c:4633:5: error: initialization from incompatible pointer type make[2]: *** [libvirt_driver_phyp_la-phyp_driver.lo] Error 1
Fixed by making phypListInterfaces return int.
Ack, fixed.
static int +phypInterfaceDestroy(virInterfacePtr iface, + unsigned int flags ATTRIBUTE_UNUSED) +{
+ ret = phypExec(session, cmd,&exit_status, iface->conn); +
+ + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return -1;
Memory leak for ret; this should goto err rather than return.
Ack, fixed.
+ } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd,&exit_status, iface->conn);
Memory leak for the old value of ret; you need to VIR_FREE the old value before starting a new phypExec, or track the exec's in separate strings all of which get freed at the end.
Ack, fixed.
+ if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return -1; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd,&exit_status, iface->conn);
Two more leaks of ret.
Ack, fixed.
+ +static virInterfacePtr +phypInterfaceDefineXML(virConnectPtr conn, const char *xml, + unsigned int flags ATTRIBUTE_UNUSED) +{ + ConnectionData *connection_data = conn->networkPrivateData; + phyp_driverPtr phyp_driver = conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + 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 slot = 0; + char *ret = NULL; + char name[PHYP_IFACENAME_SIZE]; + char mac[PHYP_MAC_SIZE]; + virInterfaceDefPtr def; +
Rather than marking flags as unused, it would be better to insert virCheckFlags(0,NULL).
Ack, fixed.
+ + ret = phypExec(session, cmd,&exit_status, conn); + + if (exit_status< 0 || ret == NULL)
Can exit_status ever be less than 0? Or does it reflect the same values as a process exit status, where things like WIFEXITED apply, and where the result will always be in the range of uint16_t? But that's a question for the entire file, and not just this patch.
Yes, exit_status can assume values less than zero. Actually HMC has lots of error message numbers, not exactly in the standards, so unfortunately int would fit better for this variable.
+ + ret = phypExec(session, cmd,&exit_status, conn);
Another case of leaking the old value of ret.
Ack, fixed.
+ + ret = phypExec(session, cmd,&exit_status, conn);
and another.
Ack, fixed.
+ + ret = phypExec(session, cmd,&exit_status, conn);
and another.
Ack, fixed.
+static virInterfacePtr +phypInterfaceLookupByName(virConnectPtr conn, const char *name) +{ + + ret = phypExec(session, cmd,&exit_status, conn);
+ ret = phypExec(session, cmd,&exit_status, conn);
and another.
Ack, fixed.
+ if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd,&exit_status, conn);
again
Ack, fixed.
+ + if (exit_status< 0 || ret == NULL) + goto err; + + if (memcpy(mac, ret, PHYP_MAC_SIZE-1) == NULL) + goto err; + + VIR_FREE(cmd); + VIR_FREE(ret); + return virGetInterface(conn, name, ret);
NULL pointer dereference, because you're trying to use ret after freeing it.
Ack, fixed.
+static int +phypNumOfInterfaces(virConnectPtr conn) +{
+ + if (virStrToLong_i(ret,&char_ptr, 10,&nnets) == -1) + goto err; + + if (char_ptr) + *char_ptr = '\0';
What's this for? You don't use char_ptr in the rest of the function, and you're about to free ret, which is where char_ptr points.
Yes, legacy code probably, sorry I didn't noticed this earlier. Sending the PATCHv4 right away, keeping all the same comments Thanks for the review. Regards and happy new year. -- Eduardo Otubo Software Engineer Linux Technology Center IBM Systems & Technology Group Mobile: +55 19 8135 0885 eotubo@linux.vnet.ibm.com

This is the implementation of the previous patch now using virInterface* API. Ended up this patch got much more simpler, smaller and easier to review. Here is some details: * MAC size and interface name are fixed due to specifications on HMC, both are created automatically and CAN'T be specified from user. They have the following format: * MAC: 122980003002 * Interface name: U9124.720.067BE8B-V3-C0 * I did replaced all the |grep|sed following the comments Eric Blake did on the last patch. * According to my last email, It's not possible to create a network interface without assigning it to a specific lpar. Then, I am using this very minimalistic XML file for testing: <interface type='ethernet' name='LPAR01'> </interface> In this file I am using "name" as the lpar name which I am going to assign the new network interface. I couldn't find a better way to refer to it. Comments are welcome. * Regarding the fact I am sleeping one second waiting for the HMC to complete creation of the interface, I don't have means to check if the whole process is done. All I do is execute a command, wait until is complete (which is not enough in this case) check the return and the exit status. The process of actually creating a networking interface seems to take a little longer than just the return of the ssh control. --- src/phyp/phyp_driver.c | 572 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 551 insertions(+), 21 deletions(-) diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 3508891..62a38a2 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -59,6 +59,7 @@ #include "storage_conf.h" #include "nodeinfo.h" #include "files.h" +#include "interface_conf.h" #include "phyp_driver.h" @@ -74,6 +75,11 @@ static unsigned const int HMC = 0; static unsigned const int IVM = 127; +static unsigned const int PHYP_IFACENAME_SIZE = 24; +static unsigned const int PHYP_MAC_SIZE= 12; + + +virCheckFlags(0,NULL); static int waitsocket(int socket_fd, LIBSSH2_SESSION * session) @@ -1113,7 +1119,7 @@ openSSHSession(virConnectPtr conn, virConnectAuthPtr auth, static virDrvOpenStatus phypOpen(virConnectPtr conn, - virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) + virConnectAuthPtr auth, int flags) { LIBSSH2_SESSION *session = NULL; ConnectionData *connection_data = NULL; @@ -3273,6 +3279,535 @@ phypGetStoragePoolXMLDesc(virStoragePoolPtr pool, unsigned int flags) } static int +phypInterfaceDestroy(virInterfacePtr iface, + unsigned int flags) +{ + ConnectionData *connection_data = iface->conn->networkPrivateData; + phyp_driverPtr phyp_driver = iface->conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *managed_system = phyp_driver->managed_system; + int system_type = phyp_driver->system_type; + int exit_status = 0; + int slot_num = 0; + int lpar_id = 0; + char *char_ptr; + char *cmd = NULL; + char *ret = NULL; + + /* Getting the remote slot number */ + + char_ptr = strchr(iface->mac, '\n'); + + if (char_ptr) + *char_ptr = '\0'; + + 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|" + " sed -n '/%s/ s/^.*,//p'", iface->mac); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, iface->conn); + + if (exit_status < 0 || ret == NULL) + goto err; + + if (virStrToLong_i(ret, &char_ptr, 10, &slot_num) == -1) + goto err; + + /* Getting the remote slot number */ + VIR_FREE(cmd); + VIR_FREE(ret); + + virBufferAddLit(&buf, "lshwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth --level lpar " + " -F mac_addr,lpar_id|" + " sed -n '/%s/ s/^.*,//p'", iface->mac); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, iface->conn); + + if (exit_status < 0 || ret == NULL) + goto err; + + if (virStrToLong_i(ret, &char_ptr, 10, &lpar_id) == -1) + goto err; + + /* excluding interface */ + VIR_FREE(cmd); + VIR_FREE(ret); + + 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, iface->conn); + + if (exit_status < 0 || ret != NULL) + goto err; + + VIR_FREE(cmd); + VIR_FREE(ret); + return 0; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; +} + +static virInterfacePtr +phypInterfaceDefineXML(virConnectPtr conn, const char *xml, + unsigned int flags) +{ + ConnectionData *connection_data = conn->networkPrivateData; + phyp_driverPtr phyp_driver = conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + 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 slot = 0; + char *ret = NULL; + char name[PHYP_IFACENAME_SIZE]; + char mac[PHYP_MAC_SIZE]; + virInterfaceDefPtr def; + + if (!(def = virInterfaceDefParseString(xml))) + 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_names=%s" + " |sort|tail -n 1", def->name); + + 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 adding the new network interface */ + virBufferAddLit(&buf, "chhwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth" + " -p %s -o a -s %d -a port_vlan_id=1," + "ieee_virtual_eth=0", def->name, 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" + " |sed '/lpar_name=%s/!d; /slot_num=%d/!d; " + "s/^.*drc_name=//'", def->name, 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 = strchr(ret, '\n'); + + if (char_ptr) + *char_ptr = '\0'; + + if (memcpy(name, ret, PHYP_IFACENAME_SIZE-1) == 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 " + " |sed '/lpar_name=%s/!d; /slot_num=%d/!d; " + "s/^.*mac_addr=//'", def->name, 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 (memcpy(mac, ret, PHYP_MAC_SIZE-1) == NULL) + goto err; + + VIR_FREE(cmd); + VIR_FREE(ret); + return virGetInterface(conn, name, mac); + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return NULL; +} + +static virInterfacePtr +phypInterfaceLookupByName(virConnectPtr conn, const char *name) +{ + ConnectionData *connection_data = conn->networkPrivateData; + phyp_driverPtr phyp_driver = conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *managed_system = phyp_driver->managed_system; + int system_type = phyp_driver->system_type; + int exit_status = 0; + char *char_ptr; + char *cmd = NULL; + char *ret = NULL; + int slot = 0; + int lpar_id = 0; + char mac[PHYP_MAC_SIZE]; + + /*Getting the slot number for the interface */ + virBufferAddLit(&buf, "lshwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype slot --level slot " + " -F drc_name,slot_num |" + " sed -n '/%s/ s/^.*,//p'", name); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL; + } + 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; + + if (char_ptr) + *char_ptr = '\0'; + + /*Getting the lpar_id for the interface */ + 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 |" + " sed -n '/%s/ s/^.*,//p'", name); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL; + } + 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, &lpar_id) == -1) + goto err; + + if (char_ptr) + *char_ptr = '\0'; + + /*Getting the interface mac */ + virBufferAddLit(&buf, "lshwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth --level lpar " + " -F lpar_id,slot_num,mac_addr|" + " sed -n '/%d,%d/ s/^.*,//p'", lpar_id, slot); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, conn); + + if (exit_status < 0 || ret == NULL) + goto err; + + if (memcpy(mac, ret, PHYP_MAC_SIZE-1) == NULL) + goto err; + + VIR_FREE(cmd); + return virGetInterface(conn, name, ret); + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return NULL; + +} + +static int +phypInterfaceIsActive(virInterfacePtr iface) +{ + ConnectionData *connection_data = iface->conn->networkPrivateData; + phyp_driverPtr phyp_driver = iface->conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + 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; + + 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 |" + " sed -n '/%s/ s/^.*,//p'", iface->mac); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return -1; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, iface->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); + VIR_FREE(ret); + return state; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; + +} + +static int +phypListInterfaces(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|" + " sed '/eth/!d; /lpar_id=%d/d; s/^.*drc_name=//g'", + vios_id); + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err; + } + 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; + + 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; +} + +static int +phypNumOfInterfaces(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; + + VIR_FREE(cmd); + VIR_FREE(ret); + return nnets; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; + +} + +static int phypGetLparState(virConnectPtr conn, unsigned int lpar_id) { ConnectionData *connection_data = conn->networkPrivateData; @@ -3932,7 +4467,7 @@ phypDomainSetCPU(virDomainPtr dom, unsigned int nvcpus) static virDrvOpenStatus phypVIOSDriverOpen(virConnectPtr conn, virConnectAuthPtr auth ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED) + int flags) { if (conn->driver->no != VIR_DRV_PHYP) return VIR_DRV_OPEN_DECLINED; @@ -4093,27 +4628,22 @@ static virStorageDriver phypStorageDriver = { .poolIsPersistent = NULL }; -static virNetworkDriver phypNetworkDriver = { +static virInterfaceDriver phypInterfaceDriver = { .name = "PHYP", .open = phypVIOSDriverOpen, .close = phypVIOSDriverClose, - .numOfNetworks = NULL, - .listNetworks = NULL, - .numOfDefinedNetworks = NULL, - .listDefinedNetworks = NULL, - .networkLookupByUUID = NULL, - .networkLookupByName = NULL, - .networkCreateXML = NULL, - .networkDefineXML = NULL, - .networkUndefine = NULL, - .networkCreate = NULL, - .networkDestroy = NULL, - .networkDumpXML = NULL, - .networkGetBridgeName = NULL, - .networkGetAutostart = NULL, - .networkSetAutostart = NULL, - .networkIsActive = NULL, - .networkIsPersistent = NULL + .numOfInterfaces = phypNumOfInterfaces, + .listInterfaces = phypListInterfaces, + .numOfDefinedInterfaces = NULL, + .listDefinedInterfaces = NULL, + .interfaceLookupByName = phypInterfaceLookupByName, + .interfaceLookupByMACString = NULL, + .interfaceGetXMLDesc = NULL, + .interfaceDefineXML = phypInterfaceDefineXML, + .interfaceUndefine = NULL, + .interfaceCreate = NULL, + .interfaceDestroy = phypInterfaceDestroy, + .interfaceIsActive = phypInterfaceIsActive }; int @@ -4123,7 +4653,7 @@ phypRegister(void) return -1; if (virRegisterStorageDriver(&phypStorageDriver) < 0) return -1; - if (virRegisterNetworkDriver(&phypNetworkDriver) < 0) + if (virRegisterInterfaceDriver(&phypInterfaceDriver) < 0) return -1; return 0; -- 1.7.1

Any chance to get a review for the next release? Thanks a lot :-) Regards, On 12/29/2010 04:04 PM, Eduardo Otubo wrote:
This is the implementation of the previous patch now using virInterface* API. Ended up this patch got much more simpler, smaller and easier to review. Here is some details:
* MAC size and interface name are fixed due to specifications on HMC, both are created automatically and CAN'T be specified from user. They have the following format:
* MAC: 122980003002 * Interface name: U9124.720.067BE8B-V3-C0
* I did replaced all the |grep|sed following the comments Eric Blake did on the last patch.
* According to my last email, It's not possible to create a network interface without assigning it to a specific lpar. Then, I am using this very minimalistic XML file for testing:
<interface type='ethernet' name='LPAR01'> </interface>
In this file I am using "name" as the lpar name which I am going to assign the new network interface. I couldn't find a better way to refer to it. Comments are welcome.
* Regarding the fact I am sleeping one second waiting for the HMC to complete creation of the interface, I don't have means to check if the whole process is done. All I do is execute a command, wait until is complete (which is not enough in this case) check the return and the exit status. The process of actually creating a networking interface seems to take a little longer than just the return of the ssh control. --- src/phyp/phyp_driver.c | 572 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 551 insertions(+), 21 deletions(-)
diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 3508891..62a38a2 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -59,6 +59,7 @@ #include "storage_conf.h" #include "nodeinfo.h" #include "files.h" +#include "interface_conf.h"
#include "phyp_driver.h"
@@ -74,6 +75,11 @@
static unsigned const int HMC = 0; static unsigned const int IVM = 127; +static unsigned const int PHYP_IFACENAME_SIZE = 24; +static unsigned const int PHYP_MAC_SIZE= 12; + + +virCheckFlags(0,NULL);
static int waitsocket(int socket_fd, LIBSSH2_SESSION * session) @@ -1113,7 +1119,7 @@ openSSHSession(virConnectPtr conn, virConnectAuthPtr auth,
static virDrvOpenStatus phypOpen(virConnectPtr conn, - virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) + virConnectAuthPtr auth, int flags) { LIBSSH2_SESSION *session = NULL; ConnectionData *connection_data = NULL; @@ -3273,6 +3279,535 @@ phypGetStoragePoolXMLDesc(virStoragePoolPtr pool, unsigned int flags) }
static int +phypInterfaceDestroy(virInterfacePtr iface, + unsigned int flags) +{ + ConnectionData *connection_data = iface->conn->networkPrivateData; + phyp_driverPtr phyp_driver = iface->conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *managed_system = phyp_driver->managed_system; + int system_type = phyp_driver->system_type; + int exit_status = 0; + int slot_num = 0; + int lpar_id = 0; + char *char_ptr; + char *cmd = NULL; + char *ret = NULL; + + /* Getting the remote slot number */ + + char_ptr = strchr(iface->mac, '\n'); + + if (char_ptr) + *char_ptr = '\0'; + + 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|" + " sed -n '/%s/ s/^.*,//p'", iface->mac); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd,&exit_status, iface->conn); + + if (exit_status< 0 || ret == NULL) + goto err; + + if (virStrToLong_i(ret,&char_ptr, 10,&slot_num) == -1) + goto err; + + /* Getting the remote slot number */ + VIR_FREE(cmd); + VIR_FREE(ret); + + virBufferAddLit(&buf, "lshwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth --level lpar " + " -F mac_addr,lpar_id|" + " sed -n '/%s/ s/^.*,//p'", iface->mac); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd,&exit_status, iface->conn); + + if (exit_status< 0 || ret == NULL) + goto err; + + if (virStrToLong_i(ret,&char_ptr, 10,&lpar_id) == -1) + goto err; + + /* excluding interface */ + VIR_FREE(cmd); + VIR_FREE(ret); + + 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, iface->conn); + + if (exit_status< 0 || ret != NULL) + goto err; + + VIR_FREE(cmd); + VIR_FREE(ret); + return 0; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; +} + +static virInterfacePtr +phypInterfaceDefineXML(virConnectPtr conn, const char *xml, + unsigned int flags) +{ + ConnectionData *connection_data = conn->networkPrivateData; + phyp_driverPtr phyp_driver = conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + 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 slot = 0; + char *ret = NULL; + char name[PHYP_IFACENAME_SIZE]; + char mac[PHYP_MAC_SIZE]; + virInterfaceDefPtr def; + + if (!(def = virInterfaceDefParseString(xml))) + 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_names=%s" + " |sort|tail -n 1", def->name); + + 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 adding the new network interface */ + virBufferAddLit(&buf, "chhwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth" + " -p %s -o a -s %d -a port_vlan_id=1," + "ieee_virtual_eth=0", def->name, 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" + " |sed '/lpar_name=%s/!d; /slot_num=%d/!d; " + "s/^.*drc_name=//'", def->name, 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 = strchr(ret, '\n'); + + if (char_ptr) + *char_ptr = '\0'; + + if (memcpy(name, ret, PHYP_IFACENAME_SIZE-1) == 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 " + " |sed '/lpar_name=%s/!d; /slot_num=%d/!d; " + "s/^.*mac_addr=//'", def->name, 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 (memcpy(mac, ret, PHYP_MAC_SIZE-1) == NULL) + goto err; + + VIR_FREE(cmd); + VIR_FREE(ret); + return virGetInterface(conn, name, mac); + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return NULL; +} + +static virInterfacePtr +phypInterfaceLookupByName(virConnectPtr conn, const char *name) +{ + ConnectionData *connection_data = conn->networkPrivateData; + phyp_driverPtr phyp_driver = conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *managed_system = phyp_driver->managed_system; + int system_type = phyp_driver->system_type; + int exit_status = 0; + char *char_ptr; + char *cmd = NULL; + char *ret = NULL; + int slot = 0; + int lpar_id = 0; + char mac[PHYP_MAC_SIZE]; + + /*Getting the slot number for the interface */ + virBufferAddLit(&buf, "lshwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype slot --level slot " + " -F drc_name,slot_num |" + " sed -n '/%s/ s/^.*,//p'", name); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL; + } + 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; + + if (char_ptr) + *char_ptr = '\0'; + + /*Getting the lpar_id for the interface */ + 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 |" + " sed -n '/%s/ s/^.*,//p'", name); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL; + } + 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,&lpar_id) == -1) + goto err; + + if (char_ptr) + *char_ptr = '\0'; + + /*Getting the interface mac */ + virBufferAddLit(&buf, "lshwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth --level lpar " + " -F lpar_id,slot_num,mac_addr|" + " sed -n '/%d,%d/ s/^.*,//p'", lpar_id, slot); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd,&exit_status, conn); + + if (exit_status< 0 || ret == NULL) + goto err; + + if (memcpy(mac, ret, PHYP_MAC_SIZE-1) == NULL) + goto err; + + VIR_FREE(cmd); + return virGetInterface(conn, name, ret); + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return NULL; + +} + +static int +phypInterfaceIsActive(virInterfacePtr iface) +{ + ConnectionData *connection_data = iface->conn->networkPrivateData; + phyp_driverPtr phyp_driver = iface->conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + 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; + + 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 |" + " sed -n '/%s/ s/^.*,//p'", iface->mac); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return -1; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd,&exit_status, iface->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); + VIR_FREE(ret); + return state; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; + +} + +static int +phypListInterfaces(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|" + " sed '/eth/!d; /lpar_id=%d/d; s/^.*drc_name=//g'", + vios_id); + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err; + } + 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; + + 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; +} + +static int +phypNumOfInterfaces(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; + + VIR_FREE(cmd); + VIR_FREE(ret); + return nnets; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; + +} + +static int phypGetLparState(virConnectPtr conn, unsigned int lpar_id) { ConnectionData *connection_data = conn->networkPrivateData; @@ -3932,7 +4467,7 @@ phypDomainSetCPU(virDomainPtr dom, unsigned int nvcpus) static virDrvOpenStatus phypVIOSDriverOpen(virConnectPtr conn, virConnectAuthPtr auth ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED) + int flags) { if (conn->driver->no != VIR_DRV_PHYP) return VIR_DRV_OPEN_DECLINED; @@ -4093,27 +4628,22 @@ static virStorageDriver phypStorageDriver = { .poolIsPersistent = NULL };
-static virNetworkDriver phypNetworkDriver = { +static virInterfaceDriver phypInterfaceDriver = { .name = "PHYP", .open = phypVIOSDriverOpen, .close = phypVIOSDriverClose, - .numOfNetworks = NULL, - .listNetworks = NULL, - .numOfDefinedNetworks = NULL, - .listDefinedNetworks = NULL, - .networkLookupByUUID = NULL, - .networkLookupByName = NULL, - .networkCreateXML = NULL, - .networkDefineXML = NULL, - .networkUndefine = NULL, - .networkCreate = NULL, - .networkDestroy = NULL, - .networkDumpXML = NULL, - .networkGetBridgeName = NULL, - .networkGetAutostart = NULL, - .networkSetAutostart = NULL, - .networkIsActive = NULL, - .networkIsPersistent = NULL + .numOfInterfaces = phypNumOfInterfaces, + .listInterfaces = phypListInterfaces, + .numOfDefinedInterfaces = NULL, + .listDefinedInterfaces = NULL, + .interfaceLookupByName = phypInterfaceLookupByName, + .interfaceLookupByMACString = NULL, + .interfaceGetXMLDesc = NULL, + .interfaceDefineXML = phypInterfaceDefineXML, + .interfaceUndefine = NULL, + .interfaceCreate = NULL, + .interfaceDestroy = phypInterfaceDestroy, + .interfaceIsActive = phypInterfaceIsActive };
int @@ -4123,7 +4653,7 @@ phypRegister(void) return -1; if (virRegisterStorageDriver(&phypStorageDriver)< 0) return -1; - if (virRegisterNetworkDriver(&phypNetworkDriver)< 0) + if (virRegisterInterfaceDriver(&phypInterfaceDriver)< 0) return -1;
return 0;
-- Eduardo Otubo Software Engineer Linux Technology Center IBM Systems & Technology Group Mobile: +55 19 8135 0885 eotubo@linux.vnet.ibm.com

On 12/29/2010 11:04 AM, Eduardo Otubo wrote:
This is the implementation of the previous patch now using virInterface* API. Ended up this patch got much more simpler, smaller and easier to review. Here is some details:
Finally getting around to reviewing this again. I'm not intentionally putting you off, it's just that I'm less familiar with phyp and it takes a good chunk of free time to review large patches in areas where I'm less familiar.
@@ -74,6 +75,11 @@
static unsigned const int HMC = 0; static unsigned const int IVM = 127; +static unsigned const int PHYP_IFACENAME_SIZE = 24; +static unsigned const int PHYP_MAC_SIZE= 12; + + +virCheckFlags(0,NULL);
This is misplaced, and causes a compile error. It should be one of the first statements (not declarations) in any function that takes a flags argument where you do not otherwise use flags, and not something done at the file scope.
static int waitsocket(int socket_fd, LIBSSH2_SESSION * session) @@ -1113,7 +1119,7 @@ openSSHSession(virConnectPtr conn, virConnectAuthPtr auth,
static virDrvOpenStatus phypOpen(virConnectPtr conn, - virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) + virConnectAuthPtr auth, int flags) { LIBSSH2_SESSION *session = NULL; ConnectionData *connection_data = NULL;
That is, somewhere in this function. Seeing as how this causes a compile error: CC libvirt_driver_phyp_la-phyp_driver.lo phyp/phyp_driver.c:82:1: error: expected identifier or '(' before 'do' phyp/phyp_driver.c:82:290: error: expected identifier or '(' before 'while' cc1: warnings being treated as errors phyp/phyp_driver.c: In function 'phypOpen': phyp/phyp_driver.c:1122:38: error: unused parameter 'flags' [-Wunused-parameter] phyp/phyp_driver.c: In function 'phypInterfaceDestroy': how can I even be sure that you've tested your patch, to spend my time reviewing it?
+static virInterfacePtr +phypInterfaceDefineXML(virConnectPtr conn, const char *xml, + unsigned int flags) +{
+ /* Now adding the new network interface */ + virBufferAddLit(&buf, "chhwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth" + " -p %s -o a -s %d -a port_vlan_id=1," + "ieee_virtual_eth=0", def->name, slot);
So if this succeeds,
+ /* 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" + " |sed '/lpar_name=%s/!d; /slot_num=%d/!d; " + "s/^.*drc_name=//'", def->name, slot);
but this fails, do you need to undo the reservation, or have you just leaked a resource?
+ + 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 = strchr(ret, '\n'); + + if (char_ptr) + *char_ptr = '\0'; + + if (memcpy(name, ret, PHYP_IFACENAME_SIZE-1) == NULL) + goto err;
Huh? memcpy() can never fail on valid input. No need for this if statement; just do the memcpy() and ignore the result (which will be name). Multiple times in this patch.
+ +static virInterfacePtr +phypInterfaceLookupByName(virConnectPtr conn, const char *name) +{
+ + ret = phypExec(session, cmd, &exit_status, conn); + + if (exit_status < 0 || ret == NULL) + goto err; + + if (memcpy(mac, ret, PHYP_MAC_SIZE-1) == NULL) + goto err; + + VIR_FREE(cmd); + return virGetInterface(conn, name, ret);
Memory leak; you never freed ret. You need to do something like: result = virGetInterface(conn, name, ret); VIR_FREE(ret); return result;
+static int +phypInterfaceIsActive(virInterfacePtr iface) +{
+ + if (virStrToLong_i(ret, &char_ptr, 10, &state) == -1) + goto err; + + if (char_ptr) + *char_ptr = '\0'; + + VIR_FREE(cmd); + VIR_FREE(ret); + return state;
The lines involving setting *char_ptr to '\0' are useless, and can safely be deleted. No need to NUL-terminate the integer portion of ret if you are just about to free it. Getting closer, but still not ready to merge in. Hopefully v5 will clinch it. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On 01/14/2011 10:07 PM, Eric Blake wrote:
On 12/29/2010 11:04 AM, Eduardo Otubo wrote:
This is the implementation of the previous patch now using virInterface* API. Ended up this patch got much more simpler, smaller and easier to review. Here is some details:
Finally getting around to reviewing this again. I'm not intentionally putting you off, it's just that I'm less familiar with phyp and it takes a good chunk of free time to review large patches in areas where I'm less familiar.
No problem, I understand your point on not having a way to test it. In, future work, I'll try to send smaller patches so it gets much easier for you all to review. And sorry for the delay on replying this email, I was on a vacation, so catching up all now.
@@ -74,6 +75,11 @@
static unsigned const int HMC = 0; static unsigned const int IVM = 127; +static unsigned const int PHYP_IFACENAME_SIZE = 24; +static unsigned const int PHYP_MAC_SIZE= 12; + + +virCheckFlags(0,NULL);
This is misplaced, and causes a compile error. It should be one of the first statements (not declarations) in any function that takes a flags argument where you do not otherwise use flags, and not something done at the file scope.
static int waitsocket(int socket_fd, LIBSSH2_SESSION * session) @@ -1113,7 +1119,7 @@ openSSHSession(virConnectPtr conn, virConnectAuthPtr auth,
static virDrvOpenStatus phypOpen(virConnectPtr conn, - virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) + virConnectAuthPtr auth, int flags) { LIBSSH2_SESSION *session = NULL; ConnectionData *connection_data = NULL;
That is, somewhere in this function.
Seeing as how this causes a compile error:
CC libvirt_driver_phyp_la-phyp_driver.lo phyp/phyp_driver.c:82:1: error: expected identifier or '(' before 'do' phyp/phyp_driver.c:82:290: error: expected identifier or '(' before 'while' cc1: warnings being treated as errors phyp/phyp_driver.c: In function 'phypOpen': phyp/phyp_driver.c:1122:38: error: unused parameter 'flags' [-Wunused-parameter] phyp/phyp_driver.c: In function 'phypInterfaceDestroy':
how can I even be sure that you've tested your patch, to spend my time reviewing it?
Works for me. otubo@vader ~ $ uname -a Linux vader 2.6.35-25-generic #44-Ubuntu SMP Fri Jan 21 17:40:48 UTC 2011 i686 GNU/Linux otubo@vader ~/develop/libvirt master $ gcc -v Using built-in specs. Target: i686-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.4.4-14ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.4 --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-targets=all --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=i686-linux-gnu --host=i686-linux-gnu --target=i686-linux-gnu Thread model: posix gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5) Don't know why or how, but it did compiled. I'll fix again and send it.
+static virInterfacePtr +phypInterfaceDefineXML(virConnectPtr conn, const char *xml, + unsigned int flags) +{
+ /* Now adding the new network interface */ + virBufferAddLit(&buf, "chhwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth" + " -p %s -o a -s %d -a port_vlan_id=1," + "ieee_virtual_eth=0", def->name, slot);
So if this succeeds,
+ /* 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" + " |sed '/lpar_name=%s/!d; /slot_num=%d/!d; " + "s/^.*drc_name=//'", def->name, slot);
but this fails, do you need to undo the reservation, or have you just leaked a resource?
I put now a roll-back on this part in case it couldn't get the correct interface name.
+ + 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 = strchr(ret, '\n'); + + if (char_ptr) + *char_ptr = '\0'; + + if (memcpy(name, ret, PHYP_IFACENAME_SIZE-1) == NULL) + goto err;
Huh? memcpy() can never fail on valid input. No need for this if statement; just do the memcpy() and ignore the result (which will be name). Multiple times in this patch.
Fixed.
+ +static virInterfacePtr +phypInterfaceLookupByName(virConnectPtr conn, const char *name) +{
+ + ret = phypExec(session, cmd,&exit_status, conn); + + if (exit_status< 0 || ret == NULL) + goto err; + + if (memcpy(mac, ret, PHYP_MAC_SIZE-1) == NULL) + goto err; + + VIR_FREE(cmd); + return virGetInterface(conn, name, ret);
Memory leak; you never freed ret. You need to do something like:
result = virGetInterface(conn, name, ret); VIR_FREE(ret); return result;
Fixed
+static int +phypInterfaceIsActive(virInterfacePtr iface) +{
+ + if (virStrToLong_i(ret,&char_ptr, 10,&state) == -1) + goto err; + + if (char_ptr) + *char_ptr = '\0'; + + VIR_FREE(cmd); + VIR_FREE(ret); + return state;
The lines involving setting *char_ptr to '\0' are useless, and can safely be deleted. No need to NUL-terminate the integer portion of ret if you are just about to free it.
Also fixed.
Getting closer, but still not ready to merge in. Hopefully v5 will clinch it.
Will send a patch right a way. I'll review and test a lot better before sending it. Hope this time we can push it. :-) Thank you very much. -- Eduardo Otubo Software Engineer Linux Technology Center IBM Systems & Technology Group Mobile: +55 19 8135 0885 eotubo@linux.vnet.ibm.com

This is the implementation of the previous patch now using virInterface* API. Ended up this patch got much more simpler, smaller and easier to review. Here is some details: * MAC size and interface name are fixed due to specifications on HMC, both are created automatically and CAN'T be specified from user. They have the following format: * MAC: 122980003002 * Interface name: U9124.720.067BE8B-V3-C0 * I did replaced all the |grep|sed following the comments Eric Blake did on the last patch. * According to my last email, It's not possible to create a network interface without assigning it to a specific lpar. Then, I am using this very minimalistic XML file for testing: <interface type='ethernet' name='LPAR01'> </interface> In this file I am using "name" as the lpar name which I am going to assign the new network interface. I couldn't find a better way to refer to it. Comments are welcome. * Regarding the fact I am sleeping one second waiting for the HMC to complete creation of the interface, I don't have means to check if the whole process is done. All I do is execute a command, wait until is complete (which is not enough in this case) check the return and the exit status. The process of actually creating a networking interface seems to take a little longer than just the return of the ssh control. --- src/phyp/phyp_driver.c | 648 +++++++++++++++++++++++++++++++++++++++++------- 1 files changed, 562 insertions(+), 86 deletions(-) diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index d954f2a..0b9c030 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -59,6 +59,7 @@ #include "storage_conf.h" #include "nodeinfo.h" #include "files.h" +#include "interface_conf.h" #include "phyp_driver.h" @@ -74,6 +75,8 @@ static unsigned const int HMC = 0; static unsigned const int IVM = 127; +static unsigned const int PHYP_IFACENAME_SIZE = 24; +static unsigned const int PHYP_MAC_SIZE= 12; static int waitsocket(int socket_fd, LIBSSH2_SESSION * session) @@ -1113,8 +1116,10 @@ openSSHSession(virConnectPtr conn, virConnectAuthPtr auth, static virDrvOpenStatus phypOpen(virConnectPtr conn, - virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) + virConnectAuthPtr auth, int flags) { + virCheckFlags(0, VIR_DRV_OPEN_DECLINED); + LIBSSH2_SESSION *session = NULL; ConnectionData *connection_data = NULL; char *string = NULL; @@ -1125,6 +1130,7 @@ phypOpen(virConnectPtr conn, char *char_ptr; char *managed_system = NULL; + if (!conn || !conn->uri) return VIR_DRV_OPEN_DECLINED; @@ -1176,9 +1182,6 @@ phypOpen(virConnectPtr conn, * */ char_ptr = strchr(managed_system, '/'); - if (char_ptr) - *char_ptr = '\0'; - if (escape_specialcharacters(conn->uri->path, string, len) == -1) { PHYP_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", @@ -1354,11 +1357,6 @@ phypGetLparNAME(LIBSSH2_SESSION * session, const char *managed_system, if (exit_status < 0 || ret == NULL) goto err; - char *char_ptr = strchr(ret, '\n'); - - if (char_ptr) - *char_ptr = '\0'; - VIR_FREE(cmd); return ret; @@ -1436,9 +1434,6 @@ phypGetLparMem(virConnectPtr conn, const char *managed_system, int lpar_id, char_ptr = strchr(ret, '\n'); - if (char_ptr) - *char_ptr = '\0'; - if (virStrToLong_i(ret, &char_ptr, 10, &memory) == -1) goto err; @@ -1488,9 +1483,6 @@ phypGetLparCPUGeneric(virConnectPtr conn, const char *managed_system, char_ptr = strchr(ret, '\n'); - if (char_ptr) - *char_ptr = '\0'; - if (virStrToLong_i(ret, &char_ptr, 10, &vcpus) == -1) goto err; @@ -1565,9 +1557,6 @@ phypGetRemoteSlot(virConnectPtr conn, const char *managed_system, char_ptr = strchr(ret, '\n'); - if (char_ptr) - *char_ptr = '\0'; - if (virStrToLong_i(ret, &char_ptr, 10, &remote_slot) == -1) goto err; @@ -1650,9 +1639,6 @@ phypGetBackingDevice(virConnectPtr conn, const char *managed_system, char_ptr = strchr(backing_device, '\n'); - if (char_ptr) - *char_ptr = '\0'; - VIR_FREE(cmd); VIR_FREE(ret); return backing_device; @@ -1694,11 +1680,6 @@ phypGetLparProfile(virConnectPtr conn, int lpar_id) if (exit_status < 0 || ret == NULL) goto err; - char *char_ptr = strchr(ret, '\n'); - - if (char_ptr) - *char_ptr = '\0'; - VIR_FREE(cmd); return ret; @@ -1916,11 +1897,6 @@ phypGetVIOSFreeSCSIAdapter(virConnectPtr conn) if (exit_status < 0 || ret == NULL) goto err; - char *char_ptr = strchr(ret, '\n'); - - if (char_ptr) - *char_ptr = '\0'; - VIR_FREE(cmd); return ret; @@ -2178,13 +2154,7 @@ phypVolumeGetKey(virConnectPtr conn, char *key, const char *name) if (exit_status < 0 || ret == NULL) goto err; - char *char_ptr = strchr(ret, '\n'); - - if (char_ptr) - *char_ptr = '\0'; - - if (memcpy(key, ret, MAX_KEY_SIZE) == NULL) - goto err; + memcpy(key, ret, MAX_KEY_SIZE); VIR_FREE(cmd); VIR_FREE(ret); @@ -2233,11 +2203,6 @@ phypGetStoragePoolDevice(virConnectPtr conn, char *name) if (exit_status < 0 || ret == NULL) goto err; - char *char_ptr = strchr(ret, '\n'); - - if (char_ptr) - *char_ptr = '\0'; - VIR_FREE(cmd); return ret; @@ -2498,11 +2463,6 @@ phypVolumeGetPhysicalVolumeByStoragePool(virStorageVolPtr vol, char *sp) if (exit_status < 0 || ret == NULL) goto err; - char *char_ptr = strchr(ret, '\n'); - - if (char_ptr) - *char_ptr = '\0'; - VIR_FREE(cmd); return ret; @@ -2551,11 +2511,6 @@ phypVolumeLookupByPath(virConnectPtr conn, const char *volname) if (exit_status < 0 || spname == NULL) return NULL; - char *char_ptr = strchr(spname, '\n'); - - if (char_ptr) - *char_ptr = '\0'; - if (VIR_ALLOC_N(key, MAX_KEY_SIZE) < 0) { virReportOOMError(); return NULL; @@ -2748,11 +2703,6 @@ phypVolumeGetPath(virStorageVolPtr vol) if (exit_status < 0 || sp == NULL) goto err; - char *char_ptr = strchr(sp, '\n'); - - if (char_ptr) - *char_ptr = '\0'; - char *pv = phypVolumeGetPhysicalVolumeByStoragePool(vol, sp); if (pv) { @@ -3273,6 +3223,542 @@ phypGetStoragePoolXMLDesc(virStoragePoolPtr pool, unsigned int flags) } static int +phypInterfaceDestroy(virInterfacePtr iface, + unsigned int flags) +{ + virCheckFlags(0, -1); + + ConnectionData *connection_data = iface->conn->networkPrivateData; + phyp_driverPtr phyp_driver = iface->conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *managed_system = phyp_driver->managed_system; + int system_type = phyp_driver->system_type; + int exit_status = 0; + int slot_num = 0; + int lpar_id = 0; + char *char_ptr; + char *cmd = NULL; + char *ret = NULL; + + /* Getting the remote slot number */ + + char_ptr = strchr(iface->mac, '\n'); + + 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|" + " sed -n '/%s/ s/^.*,//p'", iface->mac); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, iface->conn); + + if (exit_status < 0 || ret == NULL) + goto err; + + if (virStrToLong_i(ret, &char_ptr, 10, &slot_num) == -1) + goto err; + + /* Getting the remote slot number */ + VIR_FREE(cmd); + VIR_FREE(ret); + + virBufferAddLit(&buf, "lshwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth --level lpar " + " -F mac_addr,lpar_id|" + " sed -n '/%s/ s/^.*,//p'", iface->mac); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, iface->conn); + + if (exit_status < 0 || ret == NULL) + goto err; + + if (virStrToLong_i(ret, &char_ptr, 10, &lpar_id) == -1) + goto err; + + /* excluding interface */ + VIR_FREE(cmd); + VIR_FREE(ret); + + 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, iface->conn); + + if (exit_status < 0 || ret != NULL) + goto err; + + VIR_FREE(cmd); + VIR_FREE(ret); + return 0; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; +} + +static virInterfacePtr +phypInterfaceDefineXML(virConnectPtr conn, const char *xml, + unsigned int flags) +{ + virCheckFlags(0, NULL); + + ConnectionData *connection_data = conn->networkPrivateData; + phyp_driverPtr phyp_driver = conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + 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 slot = 0; + char *ret = NULL; + char name[PHYP_IFACENAME_SIZE]; + char mac[PHYP_MAC_SIZE]; + virInterfaceDefPtr def; + + if (!(def = virInterfaceDefParseString(xml))) + 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_names=%s" + " |sort|tail -n 1", def->name); + + 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 adding the new network interface */ + virBufferAddLit(&buf, "chhwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth" + " -p %s -o a -s %d -a port_vlan_id=1," + "ieee_virtual_eth=0", def->name, 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" + " |sed '/lpar_name=%s/!d; /slot_num=%d/!d; " + "s/^.*drc_name=//'", def->name, 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){ + /* roll back and excluding interface if error*/ + VIR_FREE(cmd); + VIR_FREE(ret); + + virBufferAddLit(&buf, "chhwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth" + " -p %s -o r -s %d", def->name, slot); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err; + } + goto err; + } + + char_ptr = strchr(ret, '\n'); + + memcpy(name, ret, PHYP_IFACENAME_SIZE-1); + + /* 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 " + " |sed '/lpar_name=%s/!d; /slot_num=%d/!d; " + "s/^.*mac_addr=//'", def->name, 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; + + memcpy(mac, ret, PHYP_MAC_SIZE-1); + + VIR_FREE(cmd); + VIR_FREE(ret); + return virGetInterface(conn, name, mac); + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return NULL; +} + +static virInterfacePtr +phypInterfaceLookupByName(virConnectPtr conn, const char *name) +{ + ConnectionData *connection_data = conn->networkPrivateData; + phyp_driverPtr phyp_driver = conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *managed_system = phyp_driver->managed_system; + int system_type = phyp_driver->system_type; + int exit_status = 0; + char *char_ptr; + char *cmd = NULL; + char *ret = NULL; + int slot = 0; + int lpar_id = 0; + char mac[PHYP_MAC_SIZE]; + + /*Getting the slot number for the interface */ + virBufferAddLit(&buf, "lshwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype slot --level slot " + " -F drc_name,slot_num |" + " sed -n '/%s/ s/^.*,//p'", name); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL; + } + 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; + + /*Getting the lpar_id for the interface */ + 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 |" + " sed -n '/%s/ s/^.*,//p'", name); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL; + } + 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, &lpar_id) == -1) + goto err; + + /*Getting the interface mac */ + virBufferAddLit(&buf, "lshwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth --level lpar " + " -F lpar_id,slot_num,mac_addr|" + " sed -n '/%d,%d/ s/^.*,//p'", lpar_id, slot); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, conn); + + if (exit_status < 0 || ret == NULL) + goto err; + + memcpy(mac, ret, PHYP_MAC_SIZE-1); + + virInterfacePtr result = virGetInterface(conn, name, ret); + + VIR_FREE(cmd); + VIR_FREE(ret); + return result; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return NULL; + +} + +static int +phypInterfaceIsActive(virInterfacePtr iface) +{ + ConnectionData *connection_data = iface->conn->networkPrivateData; + phyp_driverPtr phyp_driver = iface->conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + 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; + + 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 |" + " sed -n '/%s/ s/^.*,//p'", iface->mac); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return -1; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, iface->conn); + + if (exit_status < 0 || ret == NULL) + goto err; + + if (virStrToLong_i(ret, &char_ptr, 10, &state) == -1) + goto err; + + VIR_FREE(cmd); + VIR_FREE(ret); + return state; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; + +} + +static int +phypListInterfaces(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|" + " sed '/eth/!d; /lpar_id=%d/d; s/^.*drc_name=//g'", + vios_id); + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err; + } + 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; + + 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; +} + +static int +phypNumOfInterfaces(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; + + VIR_FREE(cmd); + VIR_FREE(ret); + return nnets; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; + +} + +static int phypGetLparState(virConnectPtr conn, unsigned int lpar_id) { ConnectionData *connection_data = conn->networkPrivateData; @@ -3305,9 +3791,6 @@ phypGetLparState(virConnectPtr conn, unsigned int lpar_id) char_ptr = strchr(ret, '\n'); - if (char_ptr) - *char_ptr = '\0'; - if (STREQ(ret, "Running")) state = VIR_DOMAIN_RUNNING; else if (STREQ(ret, "Not Activated")) @@ -3359,9 +3842,6 @@ phypDiskType(virConnectPtr conn, char *backing_device) char_ptr = strchr(ret, '\n'); - if (char_ptr) - *char_ptr = '\0'; - if (STREQ(ret, "LVPOOL")) disk_type = VIR_DOMAIN_DISK_TYPE_BLOCK; else if (STREQ(ret, "FBPOOL")) @@ -3795,6 +4275,7 @@ static virDomainPtr phypDomainCreateAndStart(virConnectPtr conn, const char *xml, unsigned int flags) { + virCheckFlags(0, NULL); ConnectionData *connection_data = conn->networkPrivateData; LIBSSH2_SESSION *session = connection_data->session; @@ -3806,8 +4287,6 @@ phypDomainCreateAndStart(virConnectPtr conn, unsigned int i = 0; char *managed_system = phyp_driver->managed_system; - virCheckFlags(0, NULL); - if (!(def = virDomainDefParseString(phyp_driver->caps, xml, VIR_DOMAIN_XML_SECURE))) goto err; @@ -3932,8 +4411,10 @@ phypDomainSetCPU(virDomainPtr dom, unsigned int nvcpus) static virDrvOpenStatus phypVIOSDriverOpen(virConnectPtr conn, virConnectAuthPtr auth ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED) + int flags) { + virCheckFlags(0, VIR_DRV_OPEN_DECLINED); + if (conn->driver->no != VIR_DRV_PHYP) return VIR_DRV_OPEN_DECLINED; @@ -4094,27 +4575,22 @@ static virStorageDriver phypStorageDriver = { .poolIsPersistent = NULL }; -static virNetworkDriver phypNetworkDriver = { +static virInterfaceDriver phypInterfaceDriver = { .name = "PHYP", .open = phypVIOSDriverOpen, .close = phypVIOSDriverClose, - .numOfNetworks = NULL, - .listNetworks = NULL, - .numOfDefinedNetworks = NULL, - .listDefinedNetworks = NULL, - .networkLookupByUUID = NULL, - .networkLookupByName = NULL, - .networkCreateXML = NULL, - .networkDefineXML = NULL, - .networkUndefine = NULL, - .networkCreate = NULL, - .networkDestroy = NULL, - .networkDumpXML = NULL, - .networkGetBridgeName = NULL, - .networkGetAutostart = NULL, - .networkSetAutostart = NULL, - .networkIsActive = NULL, - .networkIsPersistent = NULL + .numOfInterfaces = phypNumOfInterfaces, + .listInterfaces = phypListInterfaces, + .numOfDefinedInterfaces = NULL, + .listDefinedInterfaces = NULL, + .interfaceLookupByName = phypInterfaceLookupByName, + .interfaceLookupByMACString = NULL, + .interfaceGetXMLDesc = NULL, + .interfaceDefineXML = phypInterfaceDefineXML, + .interfaceUndefine = NULL, + .interfaceCreate = NULL, + .interfaceDestroy = phypInterfaceDestroy, + .interfaceIsActive = phypInterfaceIsActive }; int @@ -4124,7 +4600,7 @@ phypRegister(void) return -1; if (virRegisterStorageDriver(&phypStorageDriver) < 0) return -1; - if (virRegisterNetworkDriver(&phypNetworkDriver) < 0) + if (virRegisterInterfaceDriver(&phypInterfaceDriver) < 0) return -1; return 0; -- 1.7.1

On 02/16/2011 10:38 AM, Eduardo Otubo wrote:
This is the implementation of the previous patch now using virInterface* API. Ended up this patch got much more simpler, smaller and easier to review. Here is some details:
src/phyp/phyp_driver.c | 648 +++++++++++++++++++++++++++++++++++++++++------- 1 files changed, 562 insertions(+), 86 deletions(-)
All right - this version compiles, so we're already off to a better start than v4, but not ready to apply yet.
@@ -1113,8 +1116,10 @@ openSSHSession(virConnectPtr conn, virConnectAuthPtr auth,
static virDrvOpenStatus phypOpen(virConnectPtr conn, - virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) + virConnectAuthPtr auth, int flags) { + virCheckFlags(0, VIR_DRV_OPEN_DECLINED); + LIBSSH2_SESSION *session = NULL;
This introduces a declaration-after-statement. We require C99 for other reasons, therefore this will still compile, but we still like to stick with C89 decl-before-statement where it makes sense; that is, virCheckFlags is usually delayed until after all the declarations.
ConnectionData *connection_data = NULL; char *string = NULL; @@ -1125,6 +1130,7 @@ phypOpen(virConnectPtr conn, char *char_ptr; char *managed_system = NULL;
+ if (!conn || !conn->uri)
Why the spurious whitespace change?
return VIR_DRV_OPEN_DECLINED;
@@ -1176,9 +1182,6 @@ phypOpen(virConnectPtr conn, * */ char_ptr = strchr(managed_system, '/');
- if (char_ptr) - *char_ptr = '\0'; -
This hunk is a regression. Later on, you assign managed_system to phyp_driver->managed_system; without this hunk, that assignment will not contain any /, but after this patch, you've changed what gets assigned.
@@ -1354,11 +1357,6 @@ phypGetLparNAME(LIBSSH2_SESSION * session, const char *managed_system, if (exit_status < 0 || ret == NULL) goto err;
- char *char_ptr = strchr(ret, '\n'); - - if (char_ptr) - *char_ptr = '\0'; - VIR_FREE(cmd); return ret;
This hunk is unrelated to network interface management; and it also looks like a regression (you're now returning a newline and subsequent text, where before-hand you were not). Could you please separate this into multiple patches, each touching one smaller issue, rather than sending one giant patch that mixes both cleanups of existing code and addition of new code? Hint: 'git reset HEAD^; git add -p'.
@@ -1650,9 +1639,6 @@ phypGetBackingDevice(virConnectPtr conn, const char *managed_system,
char_ptr = strchr(backing_device, '\n');
- if (char_ptr) - *char_ptr = '\0'; - VIR_FREE(cmd); VIR_FREE(ret); return backing_device;
Another regression. I'll quit pointing them out, and instead focus on the new code for the rest of my review.
@@ -3273,6 +3223,542 @@ phypGetStoragePoolXMLDesc(virStoragePoolPtr pool, unsigned int flags) }
static int +phypInterfaceDestroy(virInterfacePtr iface, + unsigned int flags) +{ + virCheckFlags(0, -1);
Again, this line belongs...
+ + ConnectionData *connection_data = iface->conn->networkPrivateData; + phyp_driverPtr phyp_driver = iface->conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *managed_system = phyp_driver->managed_system; + int system_type = phyp_driver->system_type; + int exit_status = 0; + int slot_num = 0; + int lpar_id = 0; + char *char_ptr; + char *cmd = NULL; + char *ret = NULL;
...here, after declarations.
+ + /* Getting the remote slot number */ + + char_ptr = strchr(iface->mac, '\n');
Dead assignment - you don't use this value of char_ptr for anything...
+ + 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|" + " sed -n '/%s/ s/^.*,//p'", iface->mac); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, iface->conn); + + if (exit_status < 0 || ret == NULL) + goto err; + + if (virStrToLong_i(ret, &char_ptr, 10, &slot_num) == -1)
...before overwriting it here. As an idea for a separate cleanup patch, you reuse a particular idiom of constructing a command in a virBuffer, then checking if that buffer worked, then calling phypExec on the string conversion. Would it be worth a refactoring that changes phypExec from taking a char* to instead taking a virBuffer, to put the error checking in just one place and make all other callers use less code? ...
+ 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, iface->conn); + + if (exit_status < 0 || ret != NULL) + goto err;
Normally, your idiom has been to declare error if ret == NULL, but here you reversed the logic. Is this a command where you really expect a NULL return, or does phypExec return "" when the command otherwise had no output in which case your logic is backwards?
+static virInterfacePtr +phypInterfaceDefineXML(virConnectPtr conn, const char *xml, + unsigned int flags) +{
+ 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 adding the new network interface */ + virBufferAddLit(&buf, "chhwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth" + " -p %s -o a -s %d -a port_vlan_id=1," + "ieee_virtual_eth=0", def->name, slot); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, conn);
Mem leak. You assigned to ret twice without an intermediate VIR_FREE().
+ + 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);
Is a usleep for a few milliseconds sufficient, or does it have to be for the entire second? Is this racy, where a system under high load will need longer than a second?
+ + /* 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" + " |sed '/lpar_name=%s/!d; /slot_num=%d/!d; " + "s/^.*drc_name=//'", def->name, slot); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, conn);
Another leak of ret.
+ + if (exit_status < 0 || ret == NULL){
Formatting nit: s/){/) {/
+ /* roll back and excluding interface if error*/ + VIR_FREE(cmd); + VIR_FREE(ret); + + virBufferAddLit(&buf, "chhwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth" + " -p %s -o r -s %d", def->name, slot); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err; + } + goto err; + } + + char_ptr = strchr(ret, '\n'); + + memcpy(name, ret, PHYP_IFACENAME_SIZE-1);
This doesn't guarantee that name is NUL-terminated (and it's wasteful if name is much shorter than PHYP_IFACENAME_SIZE). Are you sure that's okay...
+ + /* 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 " + " |sed '/lpar_name=%s/!d; /slot_num=%d/!d; " + "s/^.*mac_addr=//'", def->name, 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; + + memcpy(mac, ret, PHYP_MAC_SIZE-1); + + VIR_FREE(cmd); + VIR_FREE(ret); + return virGetInterface(conn, name, mac);
...if you get here with a non-NUL-terminated name?
+static virInterfacePtr +phypInterfaceLookupByName(virConnectPtr conn, const char *name) +{
+ 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; + + /*Getting the lpar_id for the interface */ + 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 |" + " sed -n '/%s/ s/^.*,//p'", name); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, conn);
Another leak of ret. I'm starting to feel a bit frustrated that I've pointed this out in previous rounds of reviews, and you still haven't fixed the issues.
+ + if (exit_status < 0 || ret == NULL) + goto err; + + if (virStrToLong_i(ret, &char_ptr, 10, &lpar_id) == -1) + goto err; + + /*Getting the interface mac */ + virBufferAddLit(&buf, "lshwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth --level lpar " + " -F lpar_id,slot_num,mac_addr|" + " sed -n '/%d,%d/ s/^.*,//p'", lpar_id, slot); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, conn);
Another leak of ret. More of the same through the rest of the patch. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

I understand that sending a big giant patch is not the best way the get things done. I split the patch into two parts: The first part I'll send it right away, regarding ONLY the addition of the interface management stuff. The second, that I'll send it later on, regards the regressions, leaks and other non-related issues. Below I comment all the items I fixed on this interface-management-only patch. Regards,
+ + 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|" + " sed -n '/%s/ s/^.*,//p'", iface->mac); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd,&exit_status, iface->conn); + + if (exit_status< 0 || ret == NULL) + goto err; + + if (virStrToLong_i(ret,&char_ptr, 10,&slot_num) == -1)
...before overwriting it here.
As an idea for a separate cleanup patch, you reuse a particular idiom of constructing a command in a virBuffer, then checking if that buffer worked, then calling phypExec on the string conversion. Would it be worth a refactoring that changes phypExec from taking a char* to instead taking a virBuffer, to put the error checking in just one place and make all other callers use less code?
Just a comment on this refactoring: I was already planning a great refactoring on all phypExec execution flow. I'll send a patch only with this topic.
...
+ 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, iface->conn); + + if (exit_status< 0 || ret != NULL) + goto err;
Normally, your idiom has been to declare error if ret == NULL, but here you reversed the logic. Is this a command where you really expect a NULL return, or does phypExec return "" when the command otherwise had no output in which case your logic is backwards?
Yes, this one goes against the rules. This command, when successful, always returns an output. I'll Add a comment pointing this exception for further notice.
+static virInterfacePtr +phypInterfaceDefineXML(virConnectPtr conn, const char *xml, + unsigned int flags) +{
+ 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 adding the new network interface */ + virBufferAddLit(&buf, "chhwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth" + " -p %s -o a -s %d -a port_vlan_id=1," + "ieee_virtual_eth=0", def->name, slot); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd,&exit_status, conn);
Mem leak. You assigned to ret twice without an intermediate VIR_FREE().
Fixed all the occurrences of this issue. My bad, I messed up some git merges and I think I skip this one.
+ + 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);
Is a usleep for a few milliseconds sufficient, or does it have to be for the entire second? Is this racy, where a system under high load will need longer than a second?
I can't estimate exactly how much time the HMC takes to finish this process. But according to my tests, is does not takes more than one second perform the operation, no matter the system load.
+ + if (exit_status< 0 || ret == NULL){
Formatting nit: s/){/) {/
+ /* roll back and excluding interface if error*/ + VIR_FREE(cmd); + VIR_FREE(ret); + + virBufferAddLit(&buf, "chhwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth" + " -p %s -o r -s %d", def->name, slot); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err; + } + goto err; + } + + char_ptr = strchr(ret, '\n'); + + memcpy(name, ret, PHYP_IFACENAME_SIZE-1);
This doesn't guarantee that name is NUL-terminated (and it's wasteful if name is much shorter than PHYP_IFACENAME_SIZE). Are you sure that's okay...
The name of the interface is generated automatically and has exactly PHYP_IFACENAME_SIZE characters. -- Eduardo Otubo Software Engineer Linux Technology Center IBM Systems & Technology Group Mobile: +55 19 8135 0885 eotubo@linux.vnet.ibm.com

This is the implementation of the previous patch now using virInterface* API. Ended up this patch got much more simpler, smaller and easier to review. Here is some details: * MAC size and interface name are fixed due to specifications on HMC, both are created automatically and CAN'T be specified from user. They have the following format: * MAC: 122980003002 * Interface name: U9124.720.067BE8B-V3-C0 * I did replaced all the |grep|sed following the comments Eric Blake did on the last patch. * According to my last email, It's not possible to create a network interface without assigning it to a specific lpar. Then, I am using this very minimalistic XML file for testing: <interface type='ethernet' name='LPAR01'> </interface> In this file I am using "name" as the lpar name which I am going to assign the new network interface. I couldn't find a better way to refer to it. Comments are welcome. * Regarding the fact I am sleeping one second waiting for the HMC to complete creation of the interface, I don't have means to check if the whole process is done. All I do is execute a command, wait until is complete (which is not enough in this case) check the return and the exit status. The process of actually creating a networking interface seems to take a little longer than just the return of the ssh control. --- src/phyp/phyp_driver.c | 583 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 564 insertions(+), 19 deletions(-) diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 51f9ff6..b8e7b2f 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -59,6 +59,7 @@ #include "storage_conf.h" #include "nodeinfo.h" #include "files.h" +#include "interface_conf.h" #include "phyp_driver.h" @@ -74,6 +75,8 @@ static unsigned const int HMC = 0; static unsigned const int IVM = 127; +static unsigned const int PHYP_IFACENAME_SIZE = 24; +static unsigned const int PHYP_MAC_SIZE= 12; static int waitsocket(int socket_fd, LIBSSH2_SESSION * session) @@ -3273,6 +3276,552 @@ phypGetStoragePoolXMLDesc(virStoragePoolPtr pool, unsigned int flags) } static int +phypInterfaceDestroy(virInterfacePtr iface, + unsigned int flags) +{ + virCheckFlags(0, -1); + + ConnectionData *connection_data = iface->conn->networkPrivateData; + phyp_driverPtr phyp_driver = iface->conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *managed_system = phyp_driver->managed_system; + int system_type = phyp_driver->system_type; + int exit_status = 0; + int slot_num = 0; + int lpar_id = 0; + char *char_ptr; + char *cmd = NULL; + char *ret = NULL; + + /* 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|" + " sed -n '/%s/ s/^.*,//p'", iface->mac); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, iface->conn); + + if (exit_status < 0 || ret == NULL) + goto err; + + if (virStrToLong_i(ret, &char_ptr, 10, &slot_num) == -1) + goto err; + + /* Getting the remote slot number */ + VIR_FREE(cmd); + VIR_FREE(ret); + + virBufferAddLit(&buf, "lshwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth --level lpar " + " -F mac_addr,lpar_id|" + " sed -n '/%s/ s/^.*,//p'", iface->mac); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err; + } + cmd = virBufferContentAndReset(&buf); + + VIR_FREE(ret); + + ret = phypExec(session, cmd, &exit_status, iface->conn); + + if (exit_status < 0 || ret == NULL) + goto err; + + if (virStrToLong_i(ret, &char_ptr, 10, &lpar_id) == -1) + goto err; + + /* excluding interface */ + VIR_FREE(cmd); + VIR_FREE(ret); + + 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); + + VIR_FREE(ret); + + ret = phypExec(session, cmd, &exit_status, iface->conn); + + if (exit_status < 0 || ret != NULL) + goto err; + + VIR_FREE(cmd); + VIR_FREE(ret); + return 0; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; +} + +static virInterfacePtr +phypInterfaceDefineXML(virConnectPtr conn, const char *xml, + unsigned int flags) +{ + virCheckFlags(0, NULL); + + ConnectionData *connection_data = conn->networkPrivateData; + phyp_driverPtr phyp_driver = conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + 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 slot = 0; + char *ret = NULL; + char name[PHYP_IFACENAME_SIZE]; + char mac[PHYP_MAC_SIZE]; + virInterfaceDefPtr def; + + if (!(def = virInterfaceDefParseString(xml))) + 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_names=%s" + " |sort|tail -n 1", def->name); + + 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 adding the new network interface */ + virBufferAddLit(&buf, "chhwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth" + " -p %s -o a -s %d -a port_vlan_id=1," + "ieee_virtual_eth=0", def->name, slot); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err; + } + cmd = virBufferContentAndReset(&buf); + + VIR_FREE(ret); + + 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" + " |sed '/lpar_name=%s/!d; /slot_num=%d/!d; " + "s/^.*drc_name=//'", def->name, slot); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err; + } + cmd = virBufferContentAndReset(&buf); + + VIR_FREE(ret); + + ret = phypExec(session, cmd, &exit_status, conn); + + if (exit_status < 0 || ret == NULL) { + /* roll back and excluding interface if error*/ + VIR_FREE(cmd); + VIR_FREE(ret); + + virBufferAddLit(&buf, "chhwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth" + " -p %s -o r -s %d", def->name, slot); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err; + } + goto err; + } + + memcpy(name, ret, PHYP_IFACENAME_SIZE-1); + + /* 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 " + " |sed '/lpar_name=%s/!d; /slot_num=%d/!d; " + "s/^.*mac_addr=//'", def->name, slot); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err; + } + cmd = virBufferContentAndReset(&buf); + + VIR_FREE(ret); + + ret = phypExec(session, cmd, &exit_status, conn); + + if (exit_status < 0 || ret == NULL) + goto err; + + memcpy(mac, ret, PHYP_MAC_SIZE-1); + + VIR_FREE(cmd); + VIR_FREE(ret); + return virGetInterface(conn, name, mac); + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return NULL; +} + +static virInterfacePtr +phypInterfaceLookupByName(virConnectPtr conn, const char *name) +{ + ConnectionData *connection_data = conn->networkPrivateData; + phyp_driverPtr phyp_driver = conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *managed_system = phyp_driver->managed_system; + int system_type = phyp_driver->system_type; + int exit_status = 0; + char *char_ptr; + char *cmd = NULL; + char *ret = NULL; + int slot = 0; + int lpar_id = 0; + char mac[PHYP_MAC_SIZE]; + + /*Getting the slot number for the interface */ + virBufferAddLit(&buf, "lshwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype slot --level slot " + " -F drc_name,slot_num |" + " sed -n '/%s/ s/^.*,//p'", name); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL; + } + 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; + + /*Getting the lpar_id for the interface */ + 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 |" + " sed -n '/%s/ s/^.*,//p'", name); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL; + } + cmd = virBufferContentAndReset(&buf); + + VIR_FREE(ret); + + ret = phypExec(session, cmd, &exit_status, conn); + + if (exit_status < 0 || ret == NULL) + goto err; + + if (virStrToLong_i(ret, &char_ptr, 10, &lpar_id) == -1) + goto err; + + /*Getting the interface mac */ + virBufferAddLit(&buf, "lshwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth --level lpar " + " -F lpar_id,slot_num,mac_addr|" + " sed -n '/%d,%d/ s/^.*,//p'", lpar_id, slot); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL; + } + cmd = virBufferContentAndReset(&buf); + + VIR_FREE(ret); + + ret = phypExec(session, cmd, &exit_status, conn); + + if (exit_status < 0 || ret == NULL) + goto err; + + memcpy(mac, ret, PHYP_MAC_SIZE-1); + + virInterfacePtr result = virGetInterface(conn, name, ret); + + VIR_FREE(cmd); + VIR_FREE(ret); + return result; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return NULL; + +} + +static int +phypInterfaceIsActive(virInterfacePtr iface) +{ + ConnectionData *connection_data = iface->conn->networkPrivateData; + phyp_driverPtr phyp_driver = iface->conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + 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; + + 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 |" + " sed -n '/%s/ s/^.*,//p'", iface->mac); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return -1; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, iface->conn); + + if (exit_status < 0 || ret == NULL) + goto err; + + if (virStrToLong_i(ret, &char_ptr, 10, &state) == -1) + goto err; + + VIR_FREE(cmd); + VIR_FREE(ret); + return state; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; + +} + +static int +phypListInterfaces(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|" + " sed '/eth/!d; /lpar_id=%d/d; s/^.*drc_name=//g'", + vios_id); + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err; + } + 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; + + 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; +} + +static int +phypNumOfInterfaces(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; + + VIR_FREE(cmd); + VIR_FREE(ret); + return nnets; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; + +} + +static int phypGetLparState(virConnectPtr conn, unsigned int lpar_id) { ConnectionData *connection_data = conn->networkPrivateData; @@ -3795,6 +4344,7 @@ static virDomainPtr phypDomainCreateAndStart(virConnectPtr conn, const char *xml, unsigned int flags) { + virCheckFlags(0, NULL); ConnectionData *connection_data = conn->networkPrivateData; LIBSSH2_SESSION *session = connection_data->session; @@ -4098,27 +4648,22 @@ static virStorageDriver phypStorageDriver = { .poolIsPersistent = NULL }; -static virNetworkDriver phypNetworkDriver = { +static virInterfaceDriver phypInterfaceDriver = { .name = "PHYP", .open = phypVIOSDriverOpen, .close = phypVIOSDriverClose, - .numOfNetworks = NULL, - .listNetworks = NULL, - .numOfDefinedNetworks = NULL, - .listDefinedNetworks = NULL, - .networkLookupByUUID = NULL, - .networkLookupByName = NULL, - .networkCreateXML = NULL, - .networkDefineXML = NULL, - .networkUndefine = NULL, - .networkCreate = NULL, - .networkDestroy = NULL, - .networkDumpXML = NULL, - .networkGetBridgeName = NULL, - .networkGetAutostart = NULL, - .networkSetAutostart = NULL, - .networkIsActive = NULL, - .networkIsPersistent = NULL + .numOfInterfaces = phypNumOfInterfaces, + .listInterfaces = phypListInterfaces, + .numOfDefinedInterfaces = NULL, + .listDefinedInterfaces = NULL, + .interfaceLookupByName = phypInterfaceLookupByName, + .interfaceLookupByMACString = NULL, + .interfaceGetXMLDesc = NULL, + .interfaceDefineXML = phypInterfaceDefineXML, + .interfaceUndefine = NULL, + .interfaceCreate = NULL, + .interfaceDestroy = phypInterfaceDestroy, + .interfaceIsActive = phypInterfaceIsActive }; int @@ -4128,7 +4673,7 @@ phypRegister(void) return -1; if (virRegisterStorageDriver(&phypStorageDriver) < 0) return -1; - if (virRegisterNetworkDriver(&phypNetworkDriver) < 0) + if (virRegisterInterfaceDriver(&phypInterfaceDriver) < 0) return -1; return 0; -- 1.7.1

On 03/28/2011 02:07 PM, Eduardo Otubo wrote:
This is the implementation of the previous patch now using virInterface* API. Ended up this patch got much more simpler, smaller and easier to review. Here is some details:
+++ b/src/phyp/phyp_driver.c
static int +phypInterfaceDestroy(virInterfacePtr iface, + unsigned int flags)
+ /* excluding interface */ + VIR_FREE(cmd); + VIR_FREE(ret); + + 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); + + VIR_FREE(ret);
Redundant VIR_FREE.
+static virInterfacePtr +phypInterfaceDefineXML(virConnectPtr conn, const char *xml, + unsigned int flags) +{ + virCheckFlags(0, NULL); + + ConnectionData *connection_data = conn->networkPrivateData; + phyp_driverPtr phyp_driver = conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virBuffer buf = VIR_BUFFER_INITIALIZER; + 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 slot = 0; + char *ret = NULL; + char name[PHYP_IFACENAME_SIZE]; + char mac[PHYP_MAC_SIZE]; + virInterfaceDefPtr def; + + if (!(def = virInterfaceDefParseString(xml))) + goto err;
Memory leak. This allocates def...
+ + /* 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_names=%s" + " |sort|tail -n 1", def->name); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err;
but err: does not clean it up on at least this error path. Also, the regular path doesn't clean it up. You need virInterfaceDefFree(def) to avoid the leak.
+ } + cmd = virBufferContentAndReset(&buf);
Memory leak. This allocates cmd...
+ + 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 adding the new network interface */ + virBufferAddLit(&buf, "chhwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth" + " -p %s -o a -s %d -a port_vlan_id=1," + "ieee_virtual_eth=0", def->name, slot); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err; + } + cmd = virBufferContentAndReset(&buf);
but this silently overwrites it with a new allocation.
+ + VIR_FREE(ret); + + 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" + " |sed '/lpar_name=%s/!d; /slot_num=%d/!d; " + "s/^.*drc_name=//'", def->name, slot); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err; + } + cmd = virBufferContentAndReset(&buf);
as does this.
+ + VIR_FREE(ret); + + ret = phypExec(session, cmd, &exit_status, conn); + + if (exit_status < 0 || ret == NULL) { + /* roll back and excluding interface if error*/ + VIR_FREE(cmd); + VIR_FREE(ret); + + virBufferAddLit(&buf, "chhwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth" + " -p %s -o r -s %d", def->name, slot); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err; + } + goto err;
Why are you building up a rollback command but never executing it?
+ } + + memcpy(name, ret, PHYP_IFACENAME_SIZE-1); + + /* 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 " + " |sed '/lpar_name=%s/!d; /slot_num=%d/!d; " + "s/^.*mac_addr=//'", def->name, slot); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + goto err; + } + cmd = virBufferContentAndReset(&buf);
And yet another clobber of cmd.
+ + VIR_FREE(ret); + + ret = phypExec(session, cmd, &exit_status, conn); + + if (exit_status < 0 || ret == NULL) + goto err; + + memcpy(mac, ret, PHYP_MAC_SIZE-1); + + VIR_FREE(cmd); + VIR_FREE(ret); + return virGetInterface(conn, name, mac); + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return NULL; +} + +static virInterfacePtr +phypInterfaceLookupByName(virConnectPtr conn, const char *name) +{
+ 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; + + /*Getting the lpar_id for the interface */ + 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 |" + " sed -n '/%s/ s/^.*,//p'", name); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL; + } + cmd = virBufferContentAndReset(&buf);
Yep, another leak. I'll quit pointing them out.
+ + VIR_FREE(ret); + + ret = phypExec(session, cmd, &exit_status, conn); + + if (exit_status < 0 || ret == NULL) + goto err; + + if (virStrToLong_i(ret, &char_ptr, 10, &lpar_id) == -1) + goto err; + + /*Getting the interface mac */ + virBufferAddLit(&buf, "lshwres "); + if (system_type == HMC) + virBufferVSprintf(&buf, "-m %s ", managed_system); + + virBufferVSprintf(&buf, + " -r virtualio --rsubtype eth --level lpar " + " -F lpar_id,slot_num,mac_addr|" + " sed -n '/%d,%d/ s/^.*,//p'", lpar_id, slot); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL;
Oops; this should be goto err, or you leak.
+static int +phypListInterfaces(virConnectPtr conn, char **const names, int nnames) +{
+ 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;
Style. HACKING states that a multi-line if followed by one-line else must have {} around the one-line side.
@@ -3795,6 +4344,7 @@ static virDomainPtr phypDomainCreateAndStart(virConnectPtr conn, const char *xml, unsigned int flags) { + virCheckFlags(0, NULL);
Unrelated to this patch, but I'll let it slide in. This patch has dragged on for long enough, so I'm applying the following fixes, and pushing (finally!): diff --git i/src/phyp/phyp_driver.c w/src/phyp/phyp_driver.c index ad54693..b5145db 100644 --- i/src/phyp/phyp_driver.c +++ w/src/phyp/phyp_driver.c @@ -3382,12 +3382,10 @@ phypInterfaceDestroy(virInterfacePtr iface, if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); - return -1; + goto err; } cmd = virBufferContentAndReset(&buf); - VIR_FREE(ret); - ret = phypExec(session, cmd, &exit_status, iface->conn); if (exit_status < 0 || ret != NULL) @@ -3456,6 +3454,9 @@ phypInterfaceDefineXML(virConnectPtr conn, const char *xml, slot++; /* Now adding the new network interface */ + VIR_FREE(cmd); + VIR_FREE(ret); + virBufferAddLit(&buf, "chhwres "); if (system_type == HMC) virBufferVSprintf(&buf, "-m %s ", managed_system); @@ -3472,8 +3473,6 @@ phypInterfaceDefineXML(virConnectPtr conn, const char *xml, } cmd = virBufferContentAndReset(&buf); - VIR_FREE(ret); - ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret != NULL) @@ -3485,6 +3484,9 @@ phypInterfaceDefineXML(virConnectPtr conn, const char *xml, sleep(1); /* Getting the new interface name */ + VIR_FREE(cmd); + VIR_FREE(ret); + virBufferAddLit(&buf, "lshwres "); if (system_type == HMC) virBufferVSprintf(&buf, "-m %s ", managed_system); @@ -3501,8 +3503,6 @@ phypInterfaceDefineXML(virConnectPtr conn, const char *xml, } cmd = virBufferContentAndReset(&buf); - VIR_FREE(ret); - ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) { @@ -3523,12 +3523,19 @@ phypInterfaceDefineXML(virConnectPtr conn, const char *xml, virReportOOMError(); goto err; } + + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, conn); goto err; } memcpy(name, ret, PHYP_IFACENAME_SIZE-1); /* Getting the new interface mac addr */ + VIR_FREE(cmd); + VIR_FREE(ret); + virBufferAddLit(&buf, "lshwres "); if (system_type == HMC) virBufferVSprintf(&buf, "-m %s ", managed_system); @@ -3545,8 +3552,6 @@ phypInterfaceDefineXML(virConnectPtr conn, const char *xml, } cmd = virBufferContentAndReset(&buf); - VIR_FREE(ret); - ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) @@ -3556,11 +3561,13 @@ phypInterfaceDefineXML(virConnectPtr conn, const char *xml, VIR_FREE(cmd); VIR_FREE(ret); + virInterfaceDefFree(def); return virGetInterface(conn, name, mac); err: VIR_FREE(cmd); VIR_FREE(ret); + virInterfaceDefFree(def); return NULL; } @@ -3594,7 +3601,7 @@ phypInterfaceLookupByName(virConnectPtr conn, const char *name) if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); - return NULL; + goto err; } cmd = virBufferContentAndReset(&buf); @@ -3607,6 +3614,9 @@ phypInterfaceLookupByName(virConnectPtr conn, const char *name) goto err; /*Getting the lpar_id for the interface */ + VIR_FREE(cmd); + VIR_FREE(ret); + virBufferAddLit(&buf, "lshwres "); if (system_type == HMC) virBufferVSprintf(&buf, "-m %s ", managed_system); @@ -3623,8 +3633,6 @@ phypInterfaceLookupByName(virConnectPtr conn, const char *name) } cmd = virBufferContentAndReset(&buf); - VIR_FREE(ret); - ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) @@ -3772,8 +3780,9 @@ phypListInterfaces(virConnectPtr conn, char **const names, int nnames) } char_ptr2++; networks = char_ptr2; - } else + } else { break; + } } VIR_FREE(cmd); -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org
participants (3)
-
Daniel P. Berrange
-
Eduardo Otubo
-
Eric Blake