Hello Folks, This is the result of a couple of months of hard work. I added the storage management driver to the Power Hypervisor driver. This is a big but simple patch, it's just a new set of functions, nothing more. I could split it into multiple commits, but the feature freeze starts in some hours and I really reed this feature to be included in the next release. This patch includes: * Storage driver: The set of pool-* and vol-* functions. * attach-disk function. * Support for IVM on the new functions. I've been looking at this code for a long time, so I apologize now for the silly mistakes that might be present. Looking forward to see the comments. Thanks! --- src/phyp/phyp_driver.c | 1638 +++++++++++++++++++++++++++++++++++++++++++++++- src/phyp/phyp_driver.h | 52 ++ 2 files changed, 1688 insertions(+), 2 deletions(-) diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index cefb8be..77a74ef 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -56,6 +56,7 @@ #include "virterror_internal.h" #include "uuid.h" #include "domain_conf.h" +#include "storage_conf.h" #include "nodeinfo.h" #include "phyp_driver.h" @@ -1680,6 +1681,466 @@ phypDomainSetCPU(virDomainPtr dom, unsigned int nvcpus) } +static char * +phypGetLparProfile(virConnectPtr conn, int lpar_id) +{ + 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 exit_status = 0; + char *cmd = NULL; + char *ret = NULL; + virBuffer buf = VIR_BUFFER_INITIALIZER; + + virBufferAddLit(&buf, "lssyscfg"); + if (system_type == HMC) + virBufferVSprintf(&buf, " -m %s ", managed_system); + virBufferVSprintf(&buf, + " -r prof --filter lpar_ids=%d -F name|head -n 1", + lpar_id); + 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; + + char *char_ptr = strchr(ret, '\n'); + + if (char_ptr) + *char_ptr = '\0'; + + VIR_FREE(cmd); + return ret; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return NULL; +} + +static int +phypGetVIOSNextSlotNumber(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; + char *char_ptr; + char *cmd = NULL; + char *ret = NULL; + char *profile = NULL; + int slot = 0; + virBuffer buf = VIR_BUFFER_INITIALIZER; + + if (!(profile = phypGetLparProfile(conn, vios_id))) { + VIR_ERROR("%s", "Unable to get VIOS profile name."); + goto err; + } + + virBufferAddLit(&buf, "echo $((`lssyscfg"); + if (system_type == HMC) + virBufferVSprintf(&buf, " -m %s ", managed_system); + virBufferVSprintf(&buf, "-r prof --filter " + "profile_names=%s -F virtual_eth_adapters," + "virtual_opti_pool_id,virtual_scsi_adapters," + "virtual_serial_adapters|sed -e 's/\"//g' -e " + "'s/,/\\n/g'|sed -e 's/\\(^[0-9][0-9]\\*\\).*$/\\1/'" + "|sort|tail -n 1` +1 ))", profile); + 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, &slot) == -1) + goto err; + + VIR_FREE(cmd); + VIR_FREE(ret); + return slot; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; +} + +static int +phypCreateServerSCSIAdapter(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; + char *cmd = NULL; + char *ret = NULL; + char *profile = NULL; + int slot = 0; + char *vios_name = NULL; + virBuffer buf = VIR_BUFFER_INITIALIZER; + + if (! + (vios_name = + phypGetLparNAME(session, managed_system, vios_id, conn))) { + VIR_ERROR("%s", "Unable to get VIOS name"); + goto err; + } + + if (!(profile = phypGetLparProfile(conn, vios_id))) { + VIR_ERROR("%s", "Unable to get VIOS profile name."); + goto err; + } + + if ((slot = phypGetVIOSNextSlotNumber(conn)) == -1) { + VIR_ERROR("%s", "Unable to get free slot number"); + goto err; + } + + /* Listing all the virtual_scsi_adapter interfaces, the new adapter must + * be appended to this list + * */ + virBufferAddLit(&buf, "lssyscfg"); + if (system_type == HMC) + virBufferVSprintf(&buf, " -m %s ", managed_system); + virBufferVSprintf(&buf, "-r prof --filter lpar_ids=%d,profile_names=%s" + " -F virtual_scsi_adapters|sed -e s/\"//g", + vios_id, profile); + 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; + + /* Here I change the VIOS configuration to append the new adapter + * with the free slot I got with phypGetVIOSNextSlotNumber. + * */ + virBufferAddLit(&buf, "chsyscfg"); + if (system_type == HMC) + virBufferVSprintf(&buf, " -m %s ", managed_system); + virBufferVSprintf(&buf, "-r prof -i 'name=%s,lpar_id=%d," + "\"virtual_scsi_adapters=%s,%d/server/any/any/1\"'", + vios_name, vios_id, ret, slot); + 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; + + /* Finally I add the new scsi adapter to VIOS using the same slot + * I used in the VIOS configuration. + * */ + virBufferAddLit(&buf, "chhwres -r virtualio --rsubtype scsi "); + if (system_type == HMC) + virBufferVSprintf(&buf, " -m %s ", managed_system); + virBufferVSprintf(&buf, + "-p %s -o a -s %d -d 0 -a \"adapter_type=server\"", + vios_name, slot); + 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; + + VIR_FREE(profile); + VIR_FREE(vios_name); + VIR_FREE(cmd); + VIR_FREE(ret); + return 0; + + err: + VIR_FREE(profile); + VIR_FREE(vios_name); + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; +} + +static char * +phypGetVIOSFreeSCSIAdapter(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; + char *cmd = NULL; + char *ret = NULL; + virBuffer buf = VIR_BUFFER_INITIALIZER; + + if (system_type == HMC) { + virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c ", + managed_system, vios_id); + virBufferVSprintf(&buf, "'lsmap -all -field svsa backing -fmt ,'"); + } else { + virBufferVSprintf(&buf, "lsmap -all -field svsa backing -fmt ,"); + } + virBufferVSprintf(&buf, "|grep -v ',[^.*]'|head -n 1|sed -e 's/,//g'"); + + 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; + + char *char_ptr = strchr(ret, '\n'); + + if (char_ptr) + *char_ptr = '\0'; + + VIR_FREE(cmd); + return ret; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return NULL; +} + + +int +phypAttachDevice(virDomainPtr domain, const char *xml) +{ + + virConnectPtr conn = domain->conn; + ConnectionData *connection_data = domain->conn->networkPrivateData; + phyp_driverPtr phyp_driver = domain->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; + char *char_ptr = NULL; + char *cmd = NULL; + char *ret = NULL; + char *scsi_adapter = NULL; + int slot = 0; + char *vios_name = NULL; + char *profile = NULL; + virDomainDeviceDefPtr dev = NULL; + virDomainDefPtr def = NULL; + virBuffer buf = VIR_BUFFER_INITIALIZER; + + def->os.type = strdup("aix"); + + if (def->os.type == NULL) { + virReportOOMError(); + goto err; + } + + dev = virDomainDeviceDefParse(phyp_driver->caps, def, xml, + VIR_DOMAIN_XML_INACTIVE); + if (!dev) { + virReportOOMError(); + goto err; + } + + if (! + (vios_name = + phypGetLparNAME(session, managed_system, vios_id, conn))) { + VIR_ERROR("%s", "Unable to get VIOS name"); + goto err; + } + + /* First, let's look for a free SCSI Adapter + * */ + if (!(scsi_adapter = phypGetVIOSFreeSCSIAdapter(conn))) { + /* If not found, let's create one. + * */ + if (phypCreateServerSCSIAdapter(conn) == -1) { + VIR_ERROR("%s", "Unable to create new virtual adapter"); + goto err; + } else { + if (!(scsi_adapter = phypGetVIOSFreeSCSIAdapter(conn))) { + VIR_ERROR("%s", "Unable to create new virtual adapter"); + goto err; + } + } + } + + if (system_type == HMC) { + virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c ", + managed_system, vios_id); + virBufferVSprintf(&buf, "'mkvdev -vdev %s -vadapter %s'", + dev->data.disk->src, scsi_adapter); + } else { + virBufferVSprintf(&buf, "mkvdev -vdev %s -vadapter %s", + dev->data.disk->src, scsi_adapter); + } + + 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 (!(profile = phypGetLparProfile(conn, domain->id))) { + VIR_ERROR("%s", "Unable to get VIOS profile name."); + goto err; + } + + /* Let's get the slot number for the adapter we just created + * */ + virBufferAddLit(&buf, "lshwres -r virtualio --rsubtype scsi "); + if (system_type == HMC) + virBufferVSprintf(&buf, " -m %s", managed_system); + virBufferVSprintf(&buf, + "slot_num,backing_device|grep %s|cut -d, -f1", + dev->data.disk->src); + 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, &slot) == -1) + goto err; + + /* Listing all the virtual_scsi_adapter interfaces, the new adapter must + * be appended to this list + * */ + virBufferAddLit(&buf, "lssyscfg"); + if (system_type == HMC) + virBufferVSprintf(&buf, " -m %s ", managed_system); + virBufferVSprintf(&buf, + "-r prof --filter lpar_ids=%d,profile_names=%s" + " -F virtual_scsi_adapters|sed -e s/\"//g", + vios_id, profile); + 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; + + /* Here I change the LPAR configuration to append the new adapter + * with the new slot we just created + * */ + virBufferAddLit(&buf, "chsyscfg"); + if (system_type == HMC) + virBufferVSprintf(&buf, " -m %s ", managed_system); + virBufferVSprintf(&buf, + "-r prof -i 'name=%s,lpar_id=%d," + "\"virtual_scsi_adapters=%s,%d/client/%d/%s/0\"'", + domain->name, domain->id, ret, slot, + vios_id, vios_name); + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return -1; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, conn); + + if (virStrToLong_i(ret, &char_ptr, 10, &slot) == -1) + goto err; + + /* Finally I add the new scsi adapter to VIOS using the same slot + * I used in the VIOS configuration. + * */ + virBufferAddLit(&buf, "chhwres -r virtualio --rsubtype scsi "); + if (system_type == HMC) + virBufferVSprintf(&buf, " -m %s ", managed_system); + virBufferVSprintf(&buf, + " -p %s -o a -s %d -d 0 -a \"adapter_type=server\"", + domain->name, slot); + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return -1; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, conn); + + if (exit_status < 0 || ret == NULL) { + VIR_ERROR0(_ + ("Possibly you don't have IBM Tools installed in your LPAR." + "Contact your support to enable this feature.")); + goto err; + } + + VIR_FREE(cmd); + VIR_FREE(ret); + VIR_FREE(def); + VIR_FREE(dev); + VIR_FREE(vios_name); + VIR_FREE(scsi_adapter); + return 0; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + VIR_FREE(def); + VIR_FREE(dev); + VIR_FREE(vios_name); + VIR_FREE(scsi_adapter); + return -1; +} + virDriver phypDriver = { VIR_DRV_PHYP, "PHYP", phypOpen, /* open */ phypClose, /* close */ @@ -1725,7 +2186,7 @@ virDriver phypDriver = { NULL, /* domainCreateWithFlags */ NULL, /* domainDefineXML */ NULL, /* domainUndefine */ - NULL, /* domainAttachDevice */ + phypAttachDevice, /* domainAttachDevice */ NULL, /* domainAttachDeviceFlags */ NULL, /* domainDetachDevice */ NULL, /* domainDetachDeviceFlags */ @@ -1779,6 +2240,1175 @@ virDriver phypDriver = { NULL, /* domainSnapshotDelete */ }; +virStorageDriver phypStorageDriver = { + .name = "PHYP", + .open = phypStorageOpen, + .close = phypStorageClose, + + .numOfPools = phypNumOfStoragePools, + .listPools = phypListStoragePools, + .numOfDefinedPools = NULL, + .listDefinedPools = NULL, + .findPoolSources = NULL, + .poolLookupByName = phypStoragePoolLookupByName, + .poolLookupByUUID = phypGetStoragePoolLookUpByUUID, + .poolLookupByVolume = NULL, + .poolCreateXML = phypStoragePoolCreateXML, + .poolDefineXML = NULL, + .poolBuild = NULL, + .poolUndefine = NULL, + .poolCreate = NULL, + .poolDestroy = phypDestroyStoragePool, + .poolDelete = NULL, + .poolRefresh = NULL, + .poolGetInfo = NULL, + .poolGetXMLDesc = phypGetStoragePoolXMLDesc, + .poolGetAutostart = NULL, + .poolSetAutostart = NULL, + .poolNumOfVolumes = phypStoragePoolNumOfVolumes, + .poolListVolumes = phypStoragePoolListVolumes, + + .volLookupByName = phypVolumeLookupByName, + .volLookupByKey = NULL, + .volLookupByPath = phypVolumeLookupByPath, + .volCreateXML = NULL, + .volCreateXMLFrom = NULL, + .volDelete = NULL, + .volGetInfo = NULL, + .volGetXMLDesc = phypVolumeGetXMLDesc, + .volGetPath = phypVolumeGetPath, + .poolIsActive = NULL, + .poolIsPersistent = NULL +}; + +static int +phypVolumeGetKey(virConnectPtr conn, char *key, const char *name) +{ + + 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; + char *cmd = NULL; + char *ret = NULL; + virBuffer buf = VIR_BUFFER_INITIALIZER; + + if (system_type == HMC) { + virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c ", + managed_system, vios_id); + virBufferVSprintf(&buf, "'lslv %s -field lvid'", name); + } else { + virBufferVSprintf(&buf, "lslv %s -field lvid", name); + } + virBufferVSprintf(&buf, "|sed -e 's/^LV IDENTIFIER://' -e 's/\\ //g'"); + + 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; + + char *char_ptr = strchr(ret, '\n'); + + if (char_ptr) + *char_ptr = '\0'; + + if (memmove(key, ret, PATH_MAX) == NULL) + goto err; + + VIR_FREE(cmd); + VIR_FREE(ret); + return 0; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; +} + +static char * +phypGetStoragePoolDevice(virConnectPtr conn, char *name) +{ + 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; + char *cmd = NULL; + char *ret = NULL; + virBuffer buf = VIR_BUFFER_INITIALIZER; + + if (system_type == HMC) { + virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c ", + managed_system, vios_id); + virBufferVSprintf(&buf, "'lssp -detail -sp %s -field name'", name); + } else { + virBufferVSprintf(&buf, "lssp -detail -sp %s -field name", name); + } + virBufferVSprintf(&buf, "|sed '1d'|sed -e 's/\\ //g'"); + + 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; + + char *char_ptr = strchr(ret, '\n'); + + if (char_ptr) + *char_ptr = '\0'; + + VIR_FREE(cmd); + return ret; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return NULL; +} + +static unsigned long int +phypGetStoragePoolSize(virConnectPtr conn, char *name) +{ + 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 exit_status = 0; + int vios_id = phyp_driver->vios_id; + char *cmd = NULL; + char *ret = NULL; + int sp_size = 0; + char *char_ptr; + virBuffer buf = VIR_BUFFER_INITIALIZER; + + if (system_type == HMC) { + virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c ", + managed_system, vios_id); + virBufferVSprintf(&buf, "'lssp -detail -sp %s -field size'", name); + } else { + virBufferVSprintf(&buf, "lssp -detail -sp %s -field size", name); + } + virBufferVSprintf(&buf, "|sed '1d'|sed -e 's/\\ //g'"); + + 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, &sp_size) == -1) + goto err; + + VIR_FREE(cmd); + VIR_FREE(ret); + return sp_size; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; +} + +static int +phypBuildVolume(virConnectPtr conn, const char *lvname, const char *spname, + unsigned int capacity, char *key) +{ + ConnectionData *connection_data = conn->networkPrivateData; + phyp_driverPtr phyp_driver = conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + int vios_id = phyp_driver->vios_id; + int system_type = phyp_driver->system_type; + char *managed_system = phyp_driver->managed_system; + char *cmd = NULL; + char *ret = NULL; + int exit_status = 0; + virBuffer buf = VIR_BUFFER_INITIALIZER; + + if (system_type == HMC) { + virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c ", + managed_system, vios_id); + virBufferVSprintf(&buf, "'mklv -lv %s %s %d'", lvname, spname, + capacity); + } else { + virBufferVSprintf(&buf, "mklv -lv %s %s %d", lvname, spname, + capacity); + } + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return -1; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, conn); + + if (exit_status < 0) { + VIR_ERROR("%s\"%s\"", "Unable to create Volume. Reason: ", ret); + goto err; + } + + if (phypVolumeGetKey(conn, key, lvname) == -1) + goto err;; + + VIR_FREE(cmd); + VIR_FREE(ret); + return 0; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; +} + +virStorageVolPtr +phypStorageVolCreateXML(virStoragePoolPtr pool, const char *xml, + unsigned int flags ATTRIBUTE_UNUSED) +{ + + virStorageVolDefPtr voldef = NULL; + virStoragePoolDefPtr spdef = NULL; + virStorageVolPtr vol = NULL; + char *key = NULL; + + if (VIR_ALLOC(spdef) < 0) { + virReportOOMError(); + return NULL; + } + + if (VIR_ALLOC_N(key, PATH_MAX) < 0) { + virReportOOMError(); + return NULL; + } + + /* Filling spdef manually + * */ + if (pool->name != NULL) { + spdef->name = pool->name; + } else { + VIR_ERROR("%s", "Unable to determine storage pool's name."); + goto err; + } + + if (memmove(spdef->uuid, pool->uuid, VIR_UUID_BUFLEN) == NULL) { + VIR_ERROR("%s", "Unable to determine storage pool's uuid."); + goto err; + } + + if ((spdef->capacity = + phypGetStoragePoolSize(pool->conn, pool->name)) == -1) { + VIR_ERROR("%s", "Unable to determine storage pools's size."); + goto err; + } + + /* Information not avaliable */ + spdef->allocation = 0; + spdef->available = 0; + + spdef->source.ndevice = 1; + + /*XXX source adapter not working properly, should show hdiskX */ + if ((spdef->source.adapter = + phypGetStoragePoolDevice(pool->conn, pool->name)) == NULL) { + VIR_ERROR("%s", + "Unable to determine storage pools's source adapter."); + goto err; + } + + if ((voldef = virStorageVolDefParseString(spdef, xml)) == NULL) { + VIR_ERROR("%s", "Error parsing volume XML."); + goto err; + } + + /* checking if this name already exists on this system */ + if (phypVolumeLookupByName(pool, voldef->name) != NULL) { + VIR_ERROR("%s", "StoragePool name already exists."); + goto err; + } + + /* The key must be NULL, the Power Hypervisor creates a key + * in the moment you create the volume. + * */ + if (voldef->key) { + VIR_ERROR("%s", + "Key must be empty, Power Hypervisor will create one for you."); + goto err; + } + + if (voldef->capacity) { + VIR_ERROR("%s", "Capacity cannot be empty."); + goto err; + } + + if (phypBuildVolume + (pool->conn, voldef->name, spdef->name, voldef->capacity, + key) == -1) + goto err; + + if ((vol = + virGetStorageVol(pool->conn, pool->name, voldef->name, + key)) == NULL) + goto err; + + return vol; + + err: + virStorageVolDefFree(voldef); + virStoragePoolDefFree(spdef); + if (vol) + virUnrefStorageVol(vol); + return NULL; +} + +static char * +phypVolumeGetPhysicalVolumeByStoragePool(virStorageVolPtr vol, char *sp) +{ + virConnectPtr conn = vol->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; + char *cmd = NULL; + char *ret = NULL; + virBuffer buf = VIR_BUFFER_INITIALIZER; + + if (system_type == HMC) { + virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c ", + managed_system, vios_id); + virBufferVSprintf(&buf, "'lssp -detail -sp %s -field pvname'", sp); + } else { + virBufferVSprintf(&buf, "lssp -detail -sp %s -field pvname", sp); + } + virBufferVSprintf(&buf, "|sed 1d"); + + 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; + + char *char_ptr = strchr(ret, '\n'); + + if (char_ptr) + *char_ptr = '\0'; + + VIR_FREE(cmd); + return ret; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return NULL; + +} + +virStorageVolPtr +phypVolumeLookupByPath(virConnectPtr conn, const char *volname) +{ + 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; + char *cmd = NULL; + char *spname = NULL; + char *key = NULL; + virBuffer buf = VIR_BUFFER_INITIALIZER; + + if (system_type == HMC) { + virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c ", + managed_system, vios_id); + virBufferVSprintf(&buf, "'lslv %s -field vgname'", volname); + } else { + virBufferVSprintf(&buf, "lslv %s -field vgname", volname); + } + virBufferVSprintf(&buf, + "|sed -e 's/^VOLUME\\ GROUP://g' -e 's/\\ //g'"); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL; + } + cmd = virBufferContentAndReset(&buf); + + spname = phypExec(session, cmd, &exit_status, conn); + + 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, PATH_MAX) < 0) { + virReportOOMError(); + return NULL; + } + + if (phypVolumeGetKey(conn, key, volname) == -1) + return NULL; + + return virGetStorageVol(conn, spname, volname, key); +} + +char * +phypVolumeGetXMLDesc(virStorageVolPtr vol, + unsigned int flags ATTRIBUTE_UNUSED) +{ + virStorageVolDef voldef; + memset(&voldef, 0, sizeof(virStorageVolDef)); + + virStoragePoolPtr sp = + phypStoragePoolLookupByName(vol->conn, vol->pool); + + if (!sp) + goto err; + + virStoragePoolDef pool; + memset(&pool, 0, sizeof(virStoragePoolDef)); + + if (VIR_ALLOC_N(voldef.key, PATH_MAX) < 0) { + virReportOOMError(); + return NULL; + } + + if (sp->name != NULL) { + pool.name = sp->name; + } else { + VIR_ERROR("%s", "Unable to determine storage sp's name."); + goto err; + } + + if (memmove(pool.uuid, sp->uuid, VIR_UUID_BUFLEN) == NULL) { + VIR_ERROR("%s", "Unable to determine storage sp's uuid."); + goto err; + } + + if ((pool.capacity = phypGetStoragePoolSize(sp->conn, sp->name)) == -1) { + VIR_ERROR("%s", "Unable to determine storage sps's size."); + goto err; + } + + /* Information not avaliable */ + pool.allocation = 0; + pool.available = 0; + + pool.source.ndevice = 1; + + if ((pool.source.adapter = + phypGetStoragePoolDevice(sp->conn, sp->name)) == NULL) { + VIR_ERROR("%s", + "Unable to determine storage sps's source adapter."); + goto err; + } + + if (vol->name != NULL) + voldef.name = vol->name; + else { + VIR_ERROR("%s", "Unable to determine storage pool's name."); + goto err; + } + + if (memmove(voldef.key, vol->key, PATH_MAX) == NULL) { + VIR_ERROR("%s", "Unable to determine volume's key."); + goto err; + } + + voldef.type = VIR_STORAGE_POOL_LOGICAL; + + return virStorageVolDefFormat(&pool, &voldef); + + err: + return NULL; +} + +/* The Volume Group path here will be treated as suggested in the + * email on the libvirt mailling list. As soon as I can't get the + * path for every volume, the path will be a representation in + * the form: + * + * /physical_volume/storage_pool/logical_volume + * + * */ +char * +phypVolumeGetPath(virStorageVolPtr vol) +{ + virConnectPtr conn = vol->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; + char *cmd = NULL; + char *sp = NULL; + char *path = NULL; + virBuffer buf = VIR_BUFFER_INITIALIZER; + + if (system_type == HMC) { + virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c ", + managed_system, vios_id); + virBufferVSprintf(&buf, "'lslv %s -field vgname'", vol->name); + } else { + virBufferVSprintf(&buf, "lslv %s -field vgname", vol->name); + } + virBufferVSprintf(&buf, + "|sed -e 's/^VOLUME\\ GROUP://g' -e 's/\\ //g'"); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return NULL; + } + cmd = virBufferContentAndReset(&buf); + + sp = phypExec(session, cmd, &exit_status, conn); + + 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) { + if (virAsprintf(&path, "/%s/%s/%s", pv, sp, vol->name) < 0) { + virReportOOMError(); + goto err; + } + } else { + goto err; + } + + VIR_FREE(cmd); + return path; + + err: + VIR_FREE(cmd); + VIR_FREE(sp); + VIR_FREE(path); + return NULL; + +} + +virStorageVolPtr +phypVolumeLookupByName(virStoragePoolPtr pool, const char *volname) +{ + + char key[PATH_MAX]; + + if (phypVolumeGetKey(pool->conn, key, volname) == -1) + return NULL; + + return virGetStorageVol(pool->conn, pool->name, volname, key); +} + +int +phypStoragePoolListVolumes(virStoragePoolPtr pool, char **const volumes, + int nvolumes) +{ + virConnectPtr conn = pool->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 got = 0; + int i; + char *cmd = NULL; + char *ret = NULL; + char *volumes_list = NULL; + char *char_ptr2 = NULL; + virBuffer buf = VIR_BUFFER_INITIALIZER; + + if (system_type == HMC) { + virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c ", + managed_system, vios_id); + virBufferVSprintf(&buf, "'lsvg -lv %s -field lvname'", pool->name); + } else { + virBufferVSprintf(&buf, "lsvg -lv %s -field lvname", pool->name); + } + virBufferVSprintf(&buf, "|sed '1d'|sed '1d'"); + + 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 volumes */ + if (exit_status < 0 || ret == NULL) + goto err; + else { + volumes_list = ret; + + while (got < nvolumes) { + char_ptr2 = strchr(volumes_list, '\n'); + + if (char_ptr2) { + *char_ptr2 = '\0'; + if ((volumes[got++] = strdup(volumes_list)) == NULL) { + virReportOOMError(); + goto err; + } + char_ptr2++; + volumes_list = char_ptr2; + } else + break; + } + } + + VIR_FREE(cmd); + VIR_FREE(ret); + return got; + + err: + for (i = 0; i < got; i++) + VIR_FREE(volumes[i]); + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; +} + +int +phypStoragePoolNumOfVolumes(virStoragePoolPtr pool) +{ + virConnectPtr conn = pool->conn; + ConnectionData *connection_data = conn->networkPrivateData; + phyp_driverPtr phyp_driver = conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + int system_type = phyp_driver->system_type; + int exit_status = 0; + int nvolumes = 0; + char *cmd = NULL; + char *ret = NULL; + char *managed_system = phyp_driver->managed_system; + int vios_id = phyp_driver->vios_id; + char *char_ptr; + virBuffer buf = VIR_BUFFER_INITIALIZER; + + if (system_type == HMC) { + virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c ", + managed_system, vios_id); + virBufferVSprintf(&buf, "'lsvg -lv %s -field lvname'", pool->name); + } else { + virBufferVSprintf(&buf, "lsvg -lv %s -field lvname", pool->name); + } + virBufferVSprintf(&buf, "|sed '1d'|sed '1d'|grep -c '^.*$'"); + + 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, &nvolumes) == -1) + goto err; + + VIR_FREE(cmd); + VIR_FREE(ret); + return nvolumes; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; +} + +int +phypDestroyStoragePool(virStoragePoolPtr pool) +{ + virConnectPtr conn = pool->conn; + ConnectionData *connection_data = conn->networkPrivateData; + phyp_driverPtr phyp_driver = conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + int vios_id = phyp_driver->vios_id; + char *managed_system = phyp_driver->managed_system; + int system_type = phyp_driver->system_type; + char *cmd = NULL; + char *ret = NULL; + int exit_status = 0; + virBuffer buf = VIR_BUFFER_INITIALIZER; + + if (system_type == HMC) { + virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c ", + managed_system, vios_id); + virBufferVSprintf(&buf, "'rmsp %s'", pool->name); + } else { + virBufferVSprintf(&buf, "'rmsp %s'", pool->name); + } + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return -1; + } + cmd = virBufferContentAndReset(&buf); + + if (virAsprintf(&cmd, + "viosvrcmd -m %s --id %d -c " + "'rmsp %s'", managed_system, vios_id, + pool->name) < 0) { + virReportOOMError(); + goto err; + } + + ret = phypExec(session, cmd, &exit_status, conn); + + if (exit_status < 0) { + VIR_ERROR("%s\"%s\"", "Unable to create Storage Pool. Reason: ", + ret); + goto err; + } + + VIR_FREE(cmd); + VIR_FREE(ret); + return 0; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; +} + +static int +phypBuildStoragePool(virConnectPtr conn, virStoragePoolDefPtr def) +{ + ConnectionData *connection_data = conn->networkPrivateData; + phyp_driverPtr phyp_driver = conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + virStoragePoolSource source = def->source; + int vios_id = phyp_driver->vios_id; + int system_type = phyp_driver->system_type; + char *managed_system = phyp_driver->managed_system; + char *cmd = NULL; + char *ret = NULL; + int exit_status = 0; + virBuffer buf = VIR_BUFFER_INITIALIZER; + + if (system_type == HMC) { + virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c ", + managed_system, vios_id); + virBufferVSprintf(&buf, "'mksp -f %schild %s'", def->name, + source.adapter); + } else { + virBufferVSprintf(&buf, "mksp -f %schild %s", def->name, + source.adapter); + } + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + virReportOOMError(); + return -1; + } + cmd = virBufferContentAndReset(&buf); + + ret = phypExec(session, cmd, &exit_status, conn); + + if (exit_status < 0) { + VIR_ERROR("%s\"%s\"", "Unable to create Storage Pool. Reason: ", + ret); + goto err; + } + + VIR_FREE(cmd); + VIR_FREE(ret); + return 0; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; + +} + +virStoragePoolPtr +phypStoragePoolCreateXML(virConnectPtr conn, + const char *xml, + unsigned int flags ATTRIBUTE_UNUSED) +{ + + virStoragePoolDefPtr def = NULL; + virStoragePoolPtr sp = NULL; + + if (!(def = virStoragePoolDefParseString(xml))) + goto err; + + /* checking if this name already exists on this system */ + if (phypStoragePoolLookupByName(conn, def->name) != NULL) { + VIR_WARN0("StoragePool name already exists."); + goto err; + } + + /* checking if ID or UUID already exists on this system */ + if (phypGetStoragePoolLookUpByUUID(conn, def->uuid) != NULL) { + VIR_WARN0("StoragePool uuid already exists."); + goto err; + } + + if ((sp = virGetStoragePool(conn, def->name, def->uuid)) == NULL) + goto err; + + if (phypBuildStoragePool(conn, def) == -1) + goto err; + + return sp; + + err: + virStoragePoolDefFree(def); + if (sp) + virUnrefStoragePool(sp); + return NULL; +} + +char * +phypGetStoragePoolXMLDesc(virStoragePoolPtr pool, + unsigned int flags ATTRIBUTE_UNUSED) +{ + virStoragePoolDef def; + memset(&def, 0, sizeof(virStoragePoolDef)); + + if (pool->name != NULL) + def.name = pool->name; + else { + VIR_ERROR("%s", "Unable to determine storage pool's name."); + goto err; + } + + if (memmove(def.uuid, pool->uuid, VIR_UUID_BUFLEN) == NULL) { + VIR_ERROR("%s", "Unable to determine storage pool's uuid."); + goto err; + } + + if ((def.capacity = + phypGetStoragePoolSize(pool->conn, pool->name)) == -1) { + VIR_ERROR("%s", "Unable to determine storage pools's size."); + goto err; + } + + /* Information not avaliable */ + def.allocation = 0; + def.available = 0; + + def.source.ndevice = 1; + + /*XXX source adapter not working properly, should show hdiskX */ + if ((def.source.adapter = + phypGetStoragePoolDevice(pool->conn, pool->name)) == NULL) { + VIR_ERROR("%s", + "Unable to determine storage pools's source adapter."); + goto err; + } + + return virStoragePoolDefFormat(&def); + + err: + return NULL; +} + +static int +phypGetStoragePoolUUID(virConnectPtr conn, unsigned char *uuid, + const char *name) +{ + 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; + char *cmd = NULL; + char *ret = NULL; + virBuffer buf = VIR_BUFFER_INITIALIZER; + + if (system_type == HMC) { + virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c ", + managed_system, vios_id); + virBufferVSprintf(&buf, "'lsdev -dev %s -attr vgserial_id'", name); + } else { + virBufferVSprintf(&buf, "lsdev -dev %s -attr vgserial_id", name); + } + virBufferVSprintf(&buf, "|sed '1d'|sed '1d'"); + + 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 (memmove(uuid, ret, VIR_UUID_BUFLEN) == NULL) + goto err; + + VIR_FREE(cmd); + VIR_FREE(ret); + return 0; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; +} + +virStoragePoolPtr +phypGetStoragePoolLookUpByUUID(virConnectPtr conn, + const unsigned char *uuid) +{ + virStoragePoolPtr sp = NULL; + int npools = 0; + int gotpools = 0; + char **pools = NULL; + unsigned int i = 0; + unsigned char *local_uuid = NULL; + + if (VIR_ALLOC_N(local_uuid, VIR_UUID_BUFLEN) < 0) { + virReportOOMError(); + goto err; + } + + if ((npools = phypNumOfStoragePools(conn)) == -1) { + virReportOOMError(); + goto err; + } + + if (VIR_ALLOC_N(pools, npools) < 0) { + virReportOOMError(); + goto err; + } + + if ((gotpools = phypListStoragePools(conn, pools, npools)) == -1) { + virReportOOMError(); + goto err; + } + + if (gotpools != npools) { + virReportOOMError(); + goto err; + } + + for (i = 0; i < gotpools; i++) { + if (phypGetStoragePoolUUID(conn, local_uuid, pools[i]) == -1) + continue; + + if (STREQLEN((char *) local_uuid, (char *) uuid, VIR_UUID_BUFLEN)) { + sp = virGetStoragePool(conn, pools[i], uuid); + VIR_FREE(local_uuid); + VIR_FREE(pools); + + if (sp) + return sp; + else + goto err; + } + } + + err: + VIR_FREE(local_uuid); + VIR_FREE(pools); + return NULL; +} + +virStoragePoolPtr +phypStoragePoolLookupByName(virConnectPtr conn, const char *name) +{ + unsigned char uuid[VIR_UUID_BUFLEN]; + + if (phypGetStoragePoolUUID(conn, uuid, name) == -1) + return NULL; + + return virGetStoragePool(conn, name, uuid); +} + +int +phypNumOfStoragePools(virConnectPtr conn) +{ + ConnectionData *connection_data = conn->networkPrivateData; + phyp_driverPtr phyp_driver = conn->privateData; + LIBSSH2_SESSION *session = connection_data->session; + int system_type = phyp_driver->system_type; + int exit_status = 0; + int nsp = 0; + char *cmd = NULL; + char *ret = NULL; + char *managed_system = phyp_driver->managed_system; + int vios_id = phyp_driver->vios_id; + char *char_ptr; + virBuffer buf = VIR_BUFFER_INITIALIZER; + + if (system_type == HMC) { + virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c ", + managed_system, vios_id); + virBufferVSprintf(&buf, "'lsvg'"); + } else { + virBufferVSprintf(&buf, "lsvg"); + } + virBufferVSprintf(&buf, "grep -c '^.*$'"); + + 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, &nsp) == -1) + goto err; + + VIR_FREE(cmd); + VIR_FREE(ret); + return nsp; + + err: + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; +} + +int +phypListStoragePools(virConnectPtr conn, char **const pools, int npools) +{ + 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 got = 0; + int i; + char *cmd = NULL; + char *ret = NULL; + char *storage_pools = NULL; + char *char_ptr2 = NULL; + virBuffer buf = VIR_BUFFER_INITIALIZER; + + if (system_type == HMC) { + virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c ", + managed_system, vios_id); + virBufferVSprintf(&buf, "'lsvg'"); + } else { + virBufferVSprintf(&buf, "lsvg"); + } + + 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 storage pools */ + if (exit_status < 0 || ret == NULL) + goto err; + else { + storage_pools = ret; + + while (got < npools) { + char_ptr2 = strchr(storage_pools, '\n'); + + if (char_ptr2) { + *char_ptr2 = '\0'; + if ((pools[got++] = strdup(storage_pools)) == NULL) { + virReportOOMError(); + goto err; + } + char_ptr2++; + storage_pools = char_ptr2; + } else + break; + } + } + + VIR_FREE(cmd); + VIR_FREE(ret); + return got; + + err: + for (i = 0; i < got; i++) + VIR_FREE(pools[i]); + VIR_FREE(cmd); + VIR_FREE(ret); + return -1; +} +virDrvOpenStatus +phypStorageOpen(virConnectPtr conn ATTRIBUTE_UNUSED, + virConnectAuthPtr auth ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED) +{ + return VIR_DRV_OPEN_SUCCESS; +} + +int +phypStorageClose(virConnectPtr conn ATTRIBUTE_UNUSED) +{ + return 0; +} + int phypBuildLpar(virConnectPtr conn, virDomainDefPtr def) { @@ -2360,6 +3990,10 @@ waitsocket(int socket_fd, LIBSSH2_SESSION * session) int phypRegister(void) { - virRegisterDriver(&phypDriver); + if (virRegisterDriver(&phypDriver) < 0) + return -1; + if (virRegisterStorageDriver(&phypStorageDriver) < 0) + return -1; + return 0; } diff --git a/src/phyp/phyp_driver.h b/src/phyp/phyp_driver.h index 80ff0c3..2606fe4 100644 --- a/src/phyp/phyp_driver.h +++ b/src/phyp/phyp_driver.h @@ -75,6 +75,58 @@ struct _phyp_driver { char *managed_system; }; + +/* + * Storage functions + * */ +virStorageVolPtr +phypStorageVolCreateXML(virStoragePoolPtr pool, const char *xmldesc, + unsigned int flags ATTRIBUTE_UNUSED); + +virStorageVolPtr phypVolumeLookupByPath (virConnectPtr pool, const char *path); + +char *phypVolumeGetXMLDesc(virStorageVolPtr vol, + unsigned int flags ATTRIBUTE_UNUSED); + +char *phypVolumeGetPath(virStorageVolPtr vol); + +virStorageVolPtr phypVolumeLookupByName(virStoragePoolPtr pool, + const char *name); + +int phypStoragePoolListVolumes(virStoragePoolPtr pool, + char **const volumes, int maxvolumes); + +int phypStoragePoolNumOfVolumes(virStoragePoolPtr pool); + +int phypDestroyStoragePool(virStoragePoolPtr pool); + +virStoragePoolPtr phypStoragePoolCreateXML(virConnectPtr conn, + const char *xml, + unsigned int flags + ATTRIBUTE_UNUSED); + +int phypNumOfStoragePools(virConnectPtr conn); + +int phypListStoragePools(virConnectPtr conn, char **const pools, + int npools); + +virStoragePoolPtr phypStoragePoolLookupByName(virConnectPtr conn, const char *name); + +virStoragePoolPtr phypGetStoragePoolLookUpByUUID(virConnectPtr conn, const unsigned char *uuid); + +char * phypGetStoragePoolXMLDesc(virStoragePoolPtr pool, unsigned int flags); + +virDrvOpenStatus phypStorageOpen(virConnectPtr conn ATTRIBUTE_UNUSED, + virConnectAuthPtr auth ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED); + +int phypStorageClose(virConnectPtr conn); + +/* + * Driver functions + * */ +int phypAttachDevice(virDomainPtr domain, const char *xml); + int phypCheckSPFreeSapce(virConnectPtr conn, int required_size, char *sp); int phypGetSystemType(virConnectPtr conn); -- 1.7.0.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list