This introduces 4 new attributes for storage pool source adapter. E.g. <adapter type='fc_host' parent='scsi_host5' wwnn='20000000c9831b4b' wwpn='10000000c9831b4b'/> Attribute 'type' can be either 'scsi_host' or 'fc_host', and defaults to 'scsi_host' if attribute 'name' is specified. I.e. It's optional for 'scsi_host' adapter, for back-compact reason. However, it's mandatory for 'fc_host' adapter and any new future adapter types. Attribute 'parent' is required for vHBA, but optional for HBA. * docs/formatstorage.html.in: - Add documents for the 4 new attrs * docs/schemas/storagepool.rng: - Add RNG schema * src/conf/storage_conf.c: - Parse and format the new XMLs * src/conf/storage_conf.h: - New struct virStoragePoolSourceAdapter, replace "char *adapter" with it; - New enum virStoragePoolSourceAdapterType * src/libvirt_private.syms: - Export TypeToString and TypeFromString * src/phyp/phyp_driver.c: - Replace "adapter" with "adapter.data.name", which is member of the union of the new struct virStoragePoolSourceAdapter now * src/storage/storage_backend_scsi.c: - Like above * tests/storagepoolxml2xmlin/pool-scsi1.xml: - New test for 'fc_host' adapter * tests/storagepoolxml2xmlout/pool-scsi.xml: - Change the expected output, as the 'type' defaults to 'scsi_host' if 'name" specified now * tests/storagepoolxml2xmlout/pool-scsi1.xml: - New test * tests/storagepoolxml2xmltest.c: - Include the test --- docs/formatstorage.html.in | 13 +++- docs/schemas/storagepool.rng | 33 +++++++- src/conf/storage_conf.c | 123 +++++++++++++++++++++++++-- src/conf/storage_conf.h | 23 +++++- src/libvirt_private.syms | 2 + src/phyp/phyp_driver.c | 8 +- src/storage/storage_backend_scsi.c | 6 +- tests/storagepoolxml2xmlin/pool-scsi1.xml | 15 ++++ tests/storagepoolxml2xmlout/pool-scsi.xml | 2 +- tests/storagepoolxml2xmlout/pool-scsi1.xml | 18 ++++ tests/storagepoolxml2xmltest.c | 1 + 11 files changed, 220 insertions(+), 24 deletions(-) create mode 100644 tests/storagepoolxml2xmlin/pool-scsi1.xml create mode 100644 tests/storagepoolxml2xmlout/pool-scsi1.xml diff --git a/docs/formatstorage.html.in b/docs/formatstorage.html.in index 9f93db8..0849618 100644 --- a/docs/formatstorage.html.in +++ b/docs/formatstorage.html.in @@ -88,8 +88,17 @@ <span class="since">Since 0.4.1</span></dd> <dt><code>adapter</code></dt> <dd>Provides the source for pools backed by SCSI adapters. May - only occur once. Contains a single attribute <code>name</code> - which is the SCSI adapter name (ex. "host1"). + only occur once. Attribute <code>name</code> is the SCSI adapter + name (ex. "host1"). Attribute <code>type</code> + (<span class="since">1.0.2</span>) specifies the adapter type, + valid value is "fc_host" or "scsi_host", defaults to "scsi_host" + if <code>name</code> is specified. To keep back-compact, + <code>type</code> is optional for "scsi_host" adapter, but + mandatory for "fc_host" adapter. Attribute <code>wwnn</code> and + <code>wwpn</code> (<span class="since">1.0.2</span>) indicates + the (v)HBA. The optional attribute <code>parent</code> + (<span class="since">1.0.2</span>) specifies the parent device of + the (v)HBA. It's optional for HBA, but required for vHBA. <span class="since">Since 0.6.2</span></dd> <dt><code>host</code></dt> <dd>Provides the source for pools backed by storage from a diff --git a/docs/schemas/storagepool.rng b/docs/schemas/storagepool.rng index 983f664..73e8ff7 100644 --- a/docs/schemas/storagepool.rng +++ b/docs/schemas/storagepool.rng @@ -275,9 +275,36 @@ <define name='sourceinfoadapter'> <element name='adapter'> - <attribute name='name'> - <text/> - </attribute> + <choice> + <group> + <!-- To keep back-compact, 'type' is not mandatory for + scsi_host adapter --> + <optional> + <attribute name='type'> + <value>scsi_host</value> + </attribute> + </optional> + <attribute name='name'> + <text/> + </attribute> + </group> + <group> + <attribute name='type'> + <value>fc_host</value> + </attribute> + <optional> + <attribute name='parent'> + <text/> + </attribute> + </optional> + <attribute name='wwnn'> + <ref name='wwn'/> + </attribute> + <attribute name='wwpn'> + <ref name='wwn'/> + </attribute> + </group> + </choice> <empty/> </element> </define> diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c index 7a39998..ddb2945 100644 --- a/src/conf/storage_conf.c +++ b/src/conf/storage_conf.c @@ -90,6 +90,10 @@ VIR_ENUM_IMPL(virStoragePartedFsType, "ext2", "ext2", "extended") +VIR_ENUM_IMPL(virStoragePoolSourceAdapterType, + VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_LAST, + "default", "scsi_host", "fc_host") + typedef const char *(*virStorageVolFormatToString)(int format); typedef int (*virStorageVolFormatFromString)(const char *format); @@ -304,6 +308,18 @@ virStorageVolDefFree(virStorageVolDefPtr def) { VIR_FREE(def); } +static void +virStoragePoolSourceAdapterClear(virStoragePoolSourceAdapter adapter) +{ + if (adapter.type == VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) { + VIR_FREE(adapter.data.fchost.wwnn); + VIR_FREE(adapter.data.fchost.wwpn); + } else if (adapter.type == + VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST) { + VIR_FREE(adapter.data.name); + } +} + void virStoragePoolSourceClear(virStoragePoolSourcePtr source) { @@ -324,7 +340,7 @@ virStoragePoolSourceClear(virStoragePoolSourcePtr source) VIR_FREE(source->devices); VIR_FREE(source->dir); VIR_FREE(source->name); - VIR_FREE(source->adapter); + virStoragePoolSourceAdapterClear(source->adapter); VIR_FREE(source->initiator.iqn); VIR_FREE(source->vendor); VIR_FREE(source->product); @@ -489,6 +505,7 @@ virStoragePoolDefParseSource(xmlXPathContextPtr ctxt, virStoragePoolOptionsPtr options; char *name = NULL; char *port = NULL; + char *adapter_type = NULL; int n; relnode = ctxt->node; @@ -580,7 +597,45 @@ virStoragePoolDefParseSource(xmlXPathContextPtr ctxt, } source->dir = virXPathString("string(./dir/@path)", ctxt); - source->adapter = virXPathString("string(./adapter/@name)", ctxt); + + if ((adapter_type = virXPathString("string(./adapter/@type)", ctxt))) { + if ((source->adapter.type = + virStoragePoolSourceAdapterTypeTypeFromString(adapter_type)) <= 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Unknown pool adapter type '%s'"), + adapter_type); + goto cleanup; + } + + if (source->adapter.type == + VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) { + source->adapter.data.fchost.parent = + virXPathString("string(./adapter/@parent)", ctxt); + source->adapter.data.fchost.wwnn = + virXPathString("string(./adapter/@wwnn)", ctxt); + source->adapter.data.fchost.wwpn = + virXPathString("string(./adapter/@wwpn)", ctxt); + } else if (source->adapter.type == + VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST) { + source->adapter.data.name = + virXPathString("string(./adapter/@name)", ctxt); + } + } else { + if (virXPathString("string(./adapter/@wwnn)", ctxt) || + virXPathString("string(./adapter/@wwpn)", ctxt)) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("'type' for 'fc_host' adapter must be specified")); + goto cleanup; + } + + /* To keep back-compact, 'type' is not required to specify + * for scsi_host adapter. + */ + if ((source->adapter.data.name = + virXPathString("string(./adapter/@name)", ctxt))) + source->adapter.type = + VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST; + } authType = virXPathString("string(./auth/@type)", ctxt); if (authType == NULL) { @@ -618,6 +673,7 @@ cleanup: VIR_FREE(port); VIR_FREE(authType); VIR_FREE(nodeset); + VIR_FREE(adapter_type); return ret; } @@ -819,11 +875,33 @@ virStoragePoolDefParseXML(xmlXPathContextPtr ctxt) { } if (options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER) { - if (!ret->source.adapter) { - virReportError(VIR_ERR_XML_ERROR, - "%s", _("missing storage pool source adapter name")); + if (!ret->source.adapter.type) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("missing storage pool source adapter")); goto cleanup; } + + if (ret->source.adapter.type == + VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) { + if (!ret->source.adapter.data.fchost.wwnn || + !ret->source.adapter.data.fchost.wwpn) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("'wwnn' and 'wwpn' must be specified for adapter " + "type 'fchost'")); + goto cleanup; + } + + if (!virValidateWWN(ret->source.adapter.data.fchost.wwnn) || + !virValidateWWN(ret->source.adapter.data.fchost.wwpn)) + goto cleanup; + } else if (ret->source.adapter.type == + VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST) { + if (!ret->source.adapter.data.name) { + virReportError(VIR_ERR_XML_ERROR, + "%s", _("missing storage pool source adapter name")); + goto cleanup; + } + } } /* If DEVICE is the only source type, then its required */ @@ -953,9 +1031,23 @@ virStoragePoolSourceFormat(virBufferPtr buf, if ((options->flags & VIR_STORAGE_POOL_SOURCE_DIR) && src->dir) virBufferAsprintf(buf," <dir path='%s'/>\n", src->dir); - if ((options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER) && - src->adapter) - virBufferAsprintf(buf," <adapter name='%s'/>\n", src->adapter); + if ((options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER)) { + if (src->adapter.type == VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST || + src->adapter.type == VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST) + virBufferAsprintf(buf, " <adapter type='%s'", + virStoragePoolSourceAdapterTypeTypeToString(src->adapter.type)); + + if (src->adapter.type == VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) { + virBufferEscapeString(buf, " parent='%s'", + src->adapter.data.fchost.parent); + virBufferAsprintf(buf," wwnn='%s' wwpn='%s'/>\n", + src->adapter.data.fchost.wwnn, + src->adapter.data.fchost.wwpn); + } else if (src->adapter.type == + VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST) { + virBufferAsprintf(buf," name='%s'/>\n", src->adapter.data.name); + } + } if ((options->flags & VIR_STORAGE_POOL_SOURCE_NAME) && src->name) virBufferAsprintf(buf," <name>%s</name>\n", src->name); @@ -1856,8 +1948,19 @@ int virStoragePoolSourceFindDuplicate(virStoragePoolObjListPtr pools, matchpool = pool; break; case VIR_STORAGE_POOL_SCSI: - if (STREQ(pool->def->source.adapter, def->source.adapter)) - matchpool = pool; + if (pool->def->source.adapter.type == + VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) { + if (STREQ(pool->def->source.adapter.data.fchost.wwnn, + def->source.adapter.data.fchost.wwnn) && + STREQ(pool->def->source.adapter.data.fchost.wwpn, + def->source.adapter.data.fchost.wwpn)) + matchpool = pool; + } else if (pool->def->source.adapter.type == + VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST){ + if (STREQ(pool->def->source.adapter.data.name, + def->source.adapter.data.name)) + matchpool = pool; + } break; case VIR_STORAGE_POOL_ISCSI: { diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h index ad16eca..60b8034 100644 --- a/src/conf/storage_conf.h +++ b/src/conf/storage_conf.h @@ -233,7 +233,28 @@ struct _virStoragePoolSourceDevice { } geometry; }; +enum virStoragePoolSourceAdapterType { + VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_DEFAULT = 0, + VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST, + VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST, + VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_LAST, +}; +VIR_ENUM_DECL(virStoragePoolSourceAdapterType) + +typedef struct _virStoragePoolSourceAdapter virStoragePoolSourceAdapter; +struct _virStoragePoolSourceAdapter { + int type; /* enum virStoragePoolSourceAdapterType */ + + union { + char *name; + struct { + char *parent; + char *wwnn; + char *wwpn; + } fchost; + } data; +}; typedef struct _virStoragePoolSource virStoragePoolSource; typedef virStoragePoolSource *virStoragePoolSourcePtr; @@ -250,7 +271,7 @@ struct _virStoragePoolSource { char *dir; /* Or an adapter */ - char *adapter; + virStoragePoolSourceAdapter adapter; /* Or a name */ char *name; diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 21df094..96f56cd 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -776,6 +776,8 @@ virStoragePoolObjLock; virStoragePoolObjRemove; virStoragePoolObjSaveDef; virStoragePoolObjUnlock; +virStoragePoolSourceAdapterTypeTypeFromString; +virStoragePoolSourceAdapterTypeTypeToString; virStoragePoolSourceClear; virStoragePoolSourceFindDuplicate; virStoragePoolSourceFindDuplicateDevices; diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 74f04ff..a12a430 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -2058,7 +2058,7 @@ phypStorageVolCreateXML(virStoragePoolPtr pool, spdef->source.ndevice = 1; /*XXX source adapter not working properly, should show hdiskX */ - if ((spdef->source.adapter = + if ((spdef->source.adapter.data.name = phypGetStoragePoolDevice(pool->conn, pool->name)) == NULL) { VIR_ERROR(_("Unable to determine storage pools's source adapter.")); goto err; @@ -2280,7 +2280,7 @@ phypVolumeGetXMLDesc(virStorageVolPtr vol, unsigned int flags) pool.source.ndevice = 1; - if ((pool.source.adapter = + if ((pool.source.adapter.data.name = phypGetStoragePoolDevice(sp->conn, sp->name)) == NULL) { VIR_ERROR(_("Unable to determine storage sps's source adapter.")); goto cleanup; @@ -2520,7 +2520,7 @@ phypBuildStoragePool(virConnectPtr conn, virStoragePoolDefPtr def) managed_system, vios_id); virBufferAsprintf(&buf, "mksp -f %schild %s", def->name, - source.adapter); + source.adapter.data.name); if (system_type == HMC) virBufferAddChar(&buf, '\''); @@ -2761,7 +2761,7 @@ phypGetStoragePoolXMLDesc(virStoragePoolPtr pool, unsigned int flags) def.source.ndevice = 1; /*XXX source adapter not working properly, should show hdiskX */ - if ((def.source.adapter = + if ((def.source.adapter.data.name = phypGetStoragePoolDevice(pool->conn, pool->name)) == NULL) { VIR_ERROR(_("Unable to determine storage pools's source adapter.")); goto err; diff --git a/src/storage/storage_backend_scsi.c b/src/storage/storage_backend_scsi.c index 90bbf59..c1c163e 100644 --- a/src/storage/storage_backend_scsi.c +++ b/src/storage/storage_backend_scsi.c @@ -639,7 +639,7 @@ virStorageBackendSCSICheckPool(virConnectPtr conn ATTRIBUTE_UNUSED, char *path; *isActive = false; - if (virAsprintf(&path, "/sys/class/scsi_host/%s", pool->def->source.adapter) < 0) { + if (virAsprintf(&path, "/sys/class/scsi_host/%s", pool->def->source.adapter.data.name) < 0) { virReportOOMError(); return -1; } @@ -661,9 +661,9 @@ virStorageBackendSCSIRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED, pool->def->allocation = pool->def->capacity = pool->def->available = 0; - if (sscanf(pool->def->source.adapter, "host%u", &host) != 1) { + if (sscanf(pool->def->source.adapter.data.name, "host%u", &host) != 1) { VIR_DEBUG("Failed to get host number from '%s'", - pool->def->source.adapter); + pool->def->source.adapter.data.name); retval = -1; goto out; } diff --git a/tests/storagepoolxml2xmlin/pool-scsi1.xml b/tests/storagepoolxml2xmlin/pool-scsi1.xml new file mode 100644 index 0000000..1e9826d --- /dev/null +++ b/tests/storagepoolxml2xmlin/pool-scsi1.xml @@ -0,0 +1,15 @@ +<pool type='scsi'> + <name>hba0</name> + <uuid>e9392370-2917-565e-692b-d057f46512d6</uuid> + <source> + <adapter type='fc_host' parent='scsi_host5' wwnn='20000000c9831b4b' wwpn='10000000c9831b4b'/> + </source> + <target> + <path>/dev/disk/by-path</path> + <permissions> + <mode>0700</mode> + <owner>0</owner> + <group>0</group> + </permissions> + </target> +</pool> diff --git a/tests/storagepoolxml2xmlout/pool-scsi.xml b/tests/storagepoolxml2xmlout/pool-scsi.xml index 321dc2b..faf5342 100644 --- a/tests/storagepoolxml2xmlout/pool-scsi.xml +++ b/tests/storagepoolxml2xmlout/pool-scsi.xml @@ -5,7 +5,7 @@ <allocation unit='bytes'>0</allocation> <available unit='bytes'>0</available> <source> - <adapter name='host0'/> + <adapter type='scsi_host' name='host0'/> </source> <target> <path>/dev/disk/by-path</path> diff --git a/tests/storagepoolxml2xmlout/pool-scsi1.xml b/tests/storagepoolxml2xmlout/pool-scsi1.xml new file mode 100644 index 0000000..fb1079f --- /dev/null +++ b/tests/storagepoolxml2xmlout/pool-scsi1.xml @@ -0,0 +1,18 @@ +<pool type='scsi'> + <name>hba0</name> + <uuid>e9392370-2917-565e-692b-d057f46512d6</uuid> + <capacity unit='bytes'>0</capacity> + <allocation unit='bytes'>0</allocation> + <available unit='bytes'>0</available> + <source> + <adapter type='fc_host' parent='scsi_host5' wwnn='20000000c9831b4b' wwpn='10000000c9831b4b'/> + </source> + <target> + <path>/dev/disk/by-path</path> + <permissions> + <mode>0700</mode> + <owner>0</owner> + <group>0</group> + </permissions> + </target> +</pool> diff --git a/tests/storagepoolxml2xmltest.c b/tests/storagepoolxml2xmltest.c index 8cac978..c04eb69 100644 --- a/tests/storagepoolxml2xmltest.c +++ b/tests/storagepoolxml2xmltest.c @@ -90,6 +90,7 @@ mymain(void) DO_TEST("pool-iscsi-auth"); DO_TEST("pool-netfs"); DO_TEST("pool-scsi"); + DO_TEST("pool-scsi1"); DO_TEST("pool-mpath"); DO_TEST("pool-iscsi-multiiqn"); DO_TEST("pool-iscsi-vendor-product"); -- 1.7.7.6 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list