To get started, first you need to get an
from infi.storagemodel import get_storage_model model = get_storage_model()
The storagemodel object is a global instance, so every call to
get_storage_model returns the same instance.
The storage model is layer-based. The first layer is the SCSI layer. Access to it is done by:
scsi = model.get_scsi()
The function is cached, so calling it again returns the same
Now let's see what objects this gives us:
block_devices = scsi.get_all_scsi_block_devices() target_controllers = scsi.get_all_storage_controller_devices()
These two functions return all the disks and controllers that are visible to the operating system. You can also ask for a specific device:
device = scsi.find_scsi_block_device_by_block_access_path("/dev/sda") device = scsi.find_scsi_block_device_by_scsi_access_path("/dev/sg0")
and on Windows:
device = scsi.find_scsi_block_device_by_scsi_access_path(r"\?\GLOBALROOT\Device 0001a")
As with the rest of the API everything is cached within the model, so if "/dev/sda" and "/dev/sg0" are actually the same device, you'll get the same instance.
You can also get a device by its SCSI address:
from infi.dtypes.hctl import HCTL device.find_scsi_block_device_by_hctl(HCTL(1,0,0,1))
These methods return either
or lists of them. Check their documentation to see what information they hold.
Now, let's get the multipath devices. In mose cases, we'd want to work with the native multipath driver,
mpio = model.get_native_multipath() devices = mpio.get_all_multipath_block_devices()
Typically you'd also want to differentiate between the multipath disks and the non-multipath ones:
block_devices = scsi.get_all_scsi_block_devices() mp_disks = mpio.get_all_multipath_block_devices() non_mp_disks = mpio.filter_non_multipath_scsi_block_devices(block_devices)
If you want disks of a specific product only:
from infi.storagemodel.vendor.infinidat.infinibox import vid_pid infinidat_mp_disks = mpio.filter_vendor_specific_devices(mp_disks, vid_pid) infinidat_non_mp_disks = mpio.filter_vendor_specific_devices(block_devices, vid_pid)
infi.storagemodel.base.multipath.MultipathDevice provides cross-platform abstraction of
infi.storagemodel.base.multipath.LoadBalancePolicy. The platform-specific implementation translates the
configuration into the supported :ref:
Doing a rescan on the SCSI bus is an expensive operation.
Usually, issuing a rescan on an operating system does not report on comlpetion, and it takes some time for the upper layers to finish their work.
Since rescan is usually done when there's a change in connectivity or mapping, storagemodel provides an interfaces that blocks until an expected condition is met.
rescan_and_wait_for accepts a predicate and blocks until the predicate returns
True, or timeout is raised.
Let's see some examples.
The most common use case is that a volume has been mapped, and you want to wait for it to appear.
Waiting for a new disk is straightforward using the
from infi.storagemodel import get_storage_model from infi.storagemodel.predicates import DiskExists get_storage_model().rescan_and_wait_for(DiskExists("123456"))
This predicate works for both multipath disks and non-multipath disks
If you want to rescan after unmapping a volume, use the
If you performed a connectivity change, you can wait for it to happen.
from infi.storagemodel.predicates import FiberChannelMappingExists predicate = FiberChannelMappingExists("01020304060708", "0a:0b:0c:0d:0e:0f:0g:0h", 0) get_storage_model().rescan_and_wait_for(predicate)
This predicate needs three arguments: the initiator WWN, the target WWN and the LUN.
WWNs can be formatted however you like - lowercase, uppercase, with separators or without them.
You can also wait for several conditions together:
from infi.storagemodel.predicates import DiskExists, DiskNotExists, PredicateList predicates = PredicateList([DiskExists("123"), DiskNotExists("456")]) get_storage_model().rescan_and_wait_for(predicates)
returns a global instance of a