[libvirt] [PATCH v3 17/18] util: Alter virNodeDevice{Create|Delete}Vport to use nodedev APIs

John Ferlan jferlan at redhat.com
Wed Mar 15 18:22:03 UTC 2017



On 03/15/2017 10:46 AM, Daniel P. Berrange wrote:
> On Fri, Mar 10, 2017 at 04:10:49PM -0500, John Ferlan wrote:
>> If we have a connection pointer there's no sense walking through the
>> sysfs in order to create/destroy the vHBA. Instead, let's make use of
>> the node device create/destroy API's.
> 
> In general we should *not* call out to the public API entry points,
> from inside libvirt code. Instead we should have an internal only
> function that is called from both the public API entry point, and
> from whatever other context needs the same functionality.
> 
> Calling the public API entry points directly imposes access control
> checks on the internal code which is not good. Also if public APIs
> are triggered in clean up code paths, then it'll blow away any
> reported error.
> 

OK - so I'll take a different tack with this...

>>
>> Since we don't have to rewrite all the various parent options for
>> the test driver in order to test whether the storage pool creation
>> works as the node device creation has been tested already, let's just
>> use the altered API to test the storage pool paths.
>>
>> Fix a "bug" in the storage pool test driver code which "assumed"
>> testStoragePoolObjSetDefaults should fill in the configFile for
>> both the Define/Create (persistent) and CreateXML (transient) pools
>> by just VIR_FREE() of the pool during CreateXML.  Because the
>> configFile was filled in, during Destroy, the pool wouldn't be
>> free causing a test using the same name pool to fail.
>>
>> Signed-off-by: John Ferlan <jferlan at redhat.com>
>> ---
>>  src/conf/node_device_conf.c | 121 ++++++++++++++++++++++++++++++++++++++++++++
>>  src/test/test_driver.c      |   6 +++
>>  tests/fchosttest.c          |  15 ++++++
>>  3 files changed, 142 insertions(+)
>>
>> diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c
>> index 66cb78d..0c25f58 100644
>> --- a/src/conf/node_device_conf.c
>> +++ b/src/conf/node_device_conf.c
>> @@ -1916,6 +1916,82 @@ nodeDeviceCheckParent(virConnectPtr conn,
>>  
>>  /**
>>   * @conn: Connection pointer
>> + * @fchost: Pointer to the vHBA adapter
>> + *
>> + * If we have a valid connection, then use the node device create
>> + * XML API rather than traversing through the sysfs to create the vHBA.
>> + * Generate the Node Device XML using the Storage vHBA Adapter providing
>> + * either the parent name, parent wwnn/wwpn, or parent fabric_name if
>> + * available to the Node Device code.  Since the Storage XML processing
>> + * requires the wwnn/wwpn to be used for the vHBA to be provided (and
>> + * not generated), we can use that as the fc_host wwnn/wwpn. This will
>> + * allow for easier search later when we need it.
>> + *
>> + * Returns vHBA name on success, NULL on failure with an error message set
>> + */
>> +static char *
>> +nodeDeviceCreateNodeDeviceVport(virConnectPtr conn,
>> +                                virStorageAdapterFCHostPtr fchost)
>> +{
>> +    virBuffer buf = VIR_BUFFER_INITIALIZER;
>> +    char *vhbaStr = NULL;
>> +    virNodeDevicePtr dev = NULL;
>> +    char *name;
>> +    bool created = false;
>> +
>> +    /* If the nodedev already knows about this vHBA, then we're not
>> +     * managing it - we'll just use it. */
>> +    if ((dev = virNodeDeviceLookupSCSIHostByWWN(conn, fchost->wwnn,
>> +                                                fchost->wwpn, 0)))
>> +        goto skip_create;
>> +
>> +    virBufferAddLit(&buf, "<device>\n");
>> +    virBufferAdjustIndent(&buf, 2);
>> +    if (fchost->parent)
>> +        virBufferEscapeString(&buf, "<parent>%s</parent>\n",
>> +                              fchost->parent);
>> +    else if (fchost->parent_wwnn && fchost->parent_wwpn)
>> +        virBufferAsprintf(&buf, "<parent wwnn='%s' wwpn='%s'/>\n",
>> +                          fchost->parent_wwnn, fchost->parent_wwpn);
>> +    else if (fchost->parent_fabric_wwn)
>> +        virBufferAsprintf(&buf, "<parent fabric_wnn='%s'/>\n",
>> +                          fchost->parent_fabric_wwn);
>> +    virBufferAddLit(&buf, "<capability type='scsi_host'>\n");
>> +    virBufferAdjustIndent(&buf, 2);
>> +    virBufferAsprintf(&buf, "<capability type='fc_host' wwnn='%s' wwpn='%s'>\n",
>> +                      fchost->wwnn, fchost->wwpn);
>> +    virBufferAddLit(&buf, "</capability>\n");
>> +    virBufferAdjustIndent(&buf, -2);
>> +    virBufferAddLit(&buf, "</capability>\n");
>> +    virBufferAdjustIndent(&buf, -2);
>> +    virBufferAddLit(&buf, "</device>\n");
> 
> We really shouldn't be generating XML internally just to immediately give
> back to ourselves. We should populate the appropriate internal config data
> struct instead and avoid XML entirely.
> 

I think I originally got the idea from qemuMigrationPrecreateDisk and a
desire (at the time) to not create an API for perhaps some less obvious
to some backporting reasons.  Also since NodeDeviceCreateXML essentially
has a single purpose - I guess it just felt "bounded"...


John

>> +
>> +    if (!(vhbaStr = virBufferContentAndReset(&buf))) {
>> +        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> +                       _("unable to create node device XML"));
>> +        goto cleanup;
>> +    }
>> +
>> +    if (!(dev = virNodeDeviceCreateXML(conn, vhbaStr, 0)))
>> +        goto cleanup;
>> +    created = true;
>> +
>> + skip_create:
>> +    if (VIR_STRDUP(name, virNodeDeviceGetName(dev)) < 0) {
>> +        /* If we created, then destroy it */
>> +        if (created)
>> +            ignore_value(virNodeDeviceDestroy(dev));
>> +    }
>> +
>> + cleanup:
>> +    VIR_FREE(vhbaStr);
>> +    virObjectUnref(dev);
>> +    return name;
>> +}
>> +
> 
> Regards,
> Daniel
> 




More information about the libvir-list mailing list