13.7. Using an NPIV Virtual Adapter (vHBA) with SCSI Devices

NPIV (N_Port ID Virtualization) is a software technology that allows sharing of a single physical Fibre Channel host bus adapter (HBA).
This allows multiple guests to see the same storage from multiple physical hosts, and thus allows for easier migration paths for the storage. As a result, there is no need for the migration to create or copy storage, as long as the correct storage path is specified.
In virtualization, the virtual host bus adapter, or vHBA, controls the LUNs for virtual machines. For a host to share one Fibre Channel device path between multiple KVM guests, a vHBA must be created for each virtual machine. A single vHBA must not be used by multiple KVM guests.
Each vHBA for NPIV is identified by its parent HBA and its own World Wide Node Name (WWNN) and World Wide Port Name (WWPN). The path to the storage is determined by the WWNN and WWPN values. The parent HBA can be defined as scsi_host# or as a WWNN/WWPN pair.

Note

If a parent HBA is defined as scsi_host# and hardware is added to the host machine, the scsi_host# assignment may change. Therefore, it is recommended that you define a parent HBA using a WWNN/WWPN pair.
This section provides instructions for configuring a vHBA persistently on a virtual machine.

Note

Before creating a vHBA, it is recommended to configure storage array (SAN)-side zoning in the host LUN to provide isolation between guests and prevent the possibility of data corruption.

13.7.1. Creating a vHBA

Procedure 13.8. Creating a vHBA

  1. Locate HBAs on the host system

    To locate the HBAs on your host system, use the virsh nodedev-list --cap vports command.
    For example, the following output shows a host that has two HBAs that support vHBA:
    # virsh nodedev-list --cap vports
    scsi_host3
    scsi_host4
  2. Check the HBA's details

    Use the virsh nodedev-dumpxml HBA_device command to see the HBA's details.
    The XML output from the virsh nodedev-dumpxml command will list the fields <name>, <wwnn>, and <wwpn>, which are used to create a vHBA. The <max_vports> value shows the maximum number of supported vHBAs.
     # virsh nodedev-dumpxml scsi_host3
    <device>
      <name>scsi_host3</name>
      <path>/sys/devices/pci0000:00/0000:00:04.0/0000:10:00.0/host3</path>
      <parent>pci_0000_10_00_0</parent>
      <capability type='scsi_host'>
        <host>3</host>
        <unique_id>0</unique_id>
        <capability type='fc_host'>
          <wwnn>20000000c9848140</wwnn>
          <wwpn>10000000c9848140</wwpn>
          <fabric_wwn>2002000573de9a81</fabric_wwn>
        </capability>
        <capability type='vport_ops'>
          <max_vports>127</max_vports>
          <vports>0</vports>
        </capability>
      </capability>
    </device>   
    In this example, the <max_vports> value shows there are a total 127 virtual ports available for use in the HBA configuration. The <vports> value shows the number of virtual ports currently being used. These values update after creating a vHBA.
  3. Create a vHBA host device

    Create an XML file similar to one of the following for the vHBA host. In this examples, the file is named vhba_host3.xml.
    This example uses scsi_host# to describe the parent vHBA.
    # cat vhba_host3.xml
       <device>
         <parent>scsi_host3</parent>
         <capability type='scsi_host'>
           <capability type='fc_host'>
           </capability>
         </capability>
       </device>   
    This example uses a WWNN/WWPN pair to describe the parent vHBA.
    # cat vhba_host3.xml
      <device>
        <name>vhba</name>
        <parent wwnn='20000000c9848140' wwpn='10000000c9848140'/>
          <capability type='scsi_host'>
            <capability type='fc_host'>
            </capability>
          </capability>
        </device>   

    Note

    The WWNN and WWPN values must match those in the HBA details seen in Step 2.
    The <parent> field specifies the HBA device to associate with this vHBA device. The details in the <device> tag are used in the next step to create a new vHBA device for the host. For more information on the nodedev XML format, see the libvirt upstream pages.
  4. Create a new vHBA on the vHBA host device

    To create a vHBA on vhba_host3, use the virsh nodedev-create command:
    # virsh nodedev-create vhba_host3.xml
    Node device scsi_host5 created from vhba_host3.xml
  5. Verify the vHBA

    Verify the new vHBA's details (scsi_host5) with the virsh nodedev-dumpxml command:
    # virsh nodedev-dumpxml scsi_host5
    <device>
      <name>scsi_host5</name>
      <path>/sys/devices/pci0000:00/0000:00:04.0/0000:10:00.0/host3/vport-3:0-0/host5</path>
      <parent>scsi_host3</parent>
      <capability type='scsi_host'>
        <host>5</host>
        <unique_id>2</unique_id>
        <capability type='fc_host'>
          <wwnn>5001a4a93526d0a1</wwnn>
          <wwpn>5001a4ace3ee047d</wwpn>
          <fabric_wwn>2002000573de9a81</fabric_wwn>
        </capability>
      </capability>
    </device>  

13.7.2. Creating a Storage Pool Using the vHBA

It is recommended to define a libvirt storage pool based on the vHBA in order to preserve the vHBA configuration.
Using a storage pool has two primary advantages:
  • the libvirt code can easily find the LUN's path via virsh command output, and
  • virtual machine migration requires only defining and starting a storage pool with the same vHBA name on the target machine. To do this, the vHBA LUN, libvirt storage pool and volume name must be specified in the virtual machine's XML configuration. Refer to Section 13.7.3, “Configuring the Virtual Machine to Use a vHBA LUN” for an example.
  1. Create a SCSI storage pool

    To create a persistent vHBA configuration, first create a libvirt 'scsi' storage pool XML file using the format below. When creating a single vHBA that uses a storage pool on the same physical HBA, it is recommended to use a stable location for the <path> value, such as one of the /dev/disk/by-{path|id|uuid|label} locations on your system.
    When creating multiple vHBAs that use storage pools on the same physical HBA, the value of the <path> field must be only /dev/, otherwise storage pool volumes are visible only to one of the vHBAs, and devices from the host cannot be exposed to multiple guests with the NPIV configuration.
    More information on <path> and the elements within <target> can be found at http://libvirt.org/formatstorage.html.

    Example 13.3. Sample SCSI storage pool SML syntax

    In the following example, the 'scsi' storage pool is named vhbapool_host3.xml:
      <pool type='scsi'>
          <name>vhbapool_host3</name>
          <source>
            <adapter type='fc_host' wwnn='5001a4a93526d0a1' wwpn='5001a4ace3ee047d'/>
          </source>
          <target>
            <path>/dev/disk/by-path</path>
            <permissions>
              <mode>0700</mode>
              <owner>0</owner>
              <group>0</group>
            </permissions>
          </target>
        </pool> 
    Alternatively, the following syntax is used when vhbapool_host3.xml is one of more vHBA storage pools on a single HBA:
      <pool type='scsi'>
          <name>vhbapool_host3</name>
          <source>
            <adapter type='fc_host' wwnn='5001a4a93526d0a1' wwpn='5001a4ace3ee047d'/>
          </source>
          <target>
            <path>/dev/</path>
            <permissions>
              <mode>0700</mode>
              <owner>0</owner>
              <group>0</group>
            </permissions>
          </target>
        </pool> 

    Important

    In both cases, the pool must be type='scsi' and the source adapter type must be 'fc_host'. For a persistent configuration across host reboots, the wwnn and wwpn attributes must be the values assigned to the vHBA (scsi_host5 in this example) by libvirt.
    Optionally, the 'parent' attribute can be used in the <adapter> field to identify the parent scsi_host device as the vHBA. Note, the value is not the scsi_host of the vHBA created by virsh nodedev-create, but it is the parent of that vHBA.
    Providing the 'parent' attribute is also useful for duplicate pool definition checks. This is more important in environments where both the 'fc_host' and 'scsi_host' source adapter pools are being used, to ensure a new definition does not duplicate using the same scsi_host of another existing storage pool.
    The following example shows the optional 'parent' attribute used in the <adapter> field in a storage pool configuration:
    <adapter type='fc_host' parent='scsi_host3' wwnn='5001a4a93526d0a1' wwpn='5001a4ace3ee047d'/>
  2. Define the pool

    To define the storage pool (named vhbapool_host3 in this example) persistently, use the virsh pool-define command:
    # virsh pool-define vhbapool_host3.xml
    Pool vhbapool_host3 defined from vhbapool_host3.xml
    
  3. Start the pool

    Start the storage pool with the following command:
    # virsh pool-start vhbapool_host3
    Pool vhbapool_host3 started
    

    Note

    When starting the pool, libvirt will check if a vHBA with the same wwpn:wwnn identifier already exists. If it does not yet exist, a new vHBA with the provided wwpn:wwnn will be created. Correspondingly, when destroying the pool, libvirt will destroy the vHBA that uses the same wwpn:wwnn values as well.
  4. Enable autostart

    Finally, to ensure that subsequent host reboots will automatically define vHBAs for use in virtual machines, set the storage pool autostart feature (in this example, for a pool named vhbapool_host3):
    # virsh pool-autostart vhbapool_host3

13.7.3. Configuring the Virtual Machine to Use a vHBA LUN

After a storage pool is created for a vHBA, add the vHBA LUN to the virtual machine configuration by creating a disk volume on the virtual machine in the virtual machine's XML. Specify the storage pool and the volume in the <source> parameter, using the following as an example:
   <disk type='volume' device='disk'>
     <driver name='qemu' type='raw'/>
     <source pool='vhbapool_host3' volume='unit:0:4:0'/>
     <target dev='hda' bus='ide'/>
   </disk>    
To specify a lun device instead of a disk, refer to the following example:
    <disk type='volume' device='lun' sgio='unfiltered'>
      <driver name='qemu' type='raw'/>
      <source pool='vhbapool_host3' volume='unit:0:4:0' mode='host'/>
      <target dev='sda' bus='scsi'/>
      <shareable />
    </disk>
For XML configuration examples of adding SCSI LUN-based storage to a guest, see Section 14.5.3, “Adding SCSI LUN-based Storage to a Guest”.
Note that to ensure successful reconnection to a LUN in case of a hardware failure, it is recommended to edit the fast_io_fail_tmo and dev_loss_tmo options. For more information, see Reconnecting to an exposed LUN after a hardware failure.

13.7.4. Destroying the vHBA Storage Pool

A vHBA created by the storage pool can be destroyed by the virsh pool-destroy command:
# virsh pool-destroy vhbapool_host3
Note that executing the virsh pool-destroy command will also remove the vHBA that was created in Section 13.7.1, “Creating a vHBA”.
To verify the pool and vHBA have been destroyed, run:
# virsh nodedev-list --cap scsi_host
scsi_host5 will no longer appear in the list of results.