On Wed, Nov 19, 2008 at 01:50:09PM -0500, Shahar Frank wrote: > Hi All, here is an initial version of the operations required for SolidICE > and the proposed high level interface. > > I would like to discuss how to map it to libvirt calls and what libvirt > calls are missing. > > Thanks, > > Shahar Frank > > HostLevel > --------- > enumarateLuns(): > return: > returns all luns visible by the host. > In case multipathing is enabled then only the multipath > device should be in the return list. libvirt does not yet have support for SCSI FiberChannel, but it will be added following this forthcoming release. libvirt's storage model has two core concepts, a 'pool' object, which contains multiple 'volume' objects. There are different types of pool for each type of storage, so we intend to add a 'scsi' storage pool. The way it will work is that each SCSI HBA will be seen as its own storage pool. The LUNs for a HBA will then be volumes within the pool. So for enumerateLuns, a combination of API calls would be relevant. - virConnectFindStoragePoolSources() with a type='scsi' will discover all available HBAs, and return XML describing them. For each HBA you care about, you would define a storage pool and active it using - virStoragePoolDefineXML() - virStoragePoolStart() Then, for each storage pool you can get the list of LUNs by asking for its volumes with - virStoragePoolListVolumes() > enumerateISCSILuns(target): > params: > target - ISCSI target > Description: > enumerate all ISCSI luns on a specific target > return: > list of This will work in exactly the same way as for SCIS, except that instead of calling virConnectFindStoragePoolSources with type='scsi', you'd call it with type='iscsi'. You'd also need to give a 'srcSpec' XML document with details of the host providing the iSCSI server. With this libvirt will connect to the iSCSI server, and ask it for all its exported iSCSI targets. The returned XML will provide details on each target. For each target you wish to use, then you call virStoragePoolDefinXML and virStoragePoolStart(), as before. > getBlockInfo(name or UUID): > return: > at least uuid & size Once you have a virStorageVolPtr object, you can use the API virStorageVolGetInfo this gives you logical capacity, and actual allocation - allocation may be less than capacity if querying a file based volume like a sparse file, or qcow2. To get a persistent name, akin to a UUID, you can use the API virStorageVolGetKey() for SCSI LUNS, the volume key will be based off the UUID avialable. > enumerateVGs(): > return: > VG UUID list This is very similar to the other enumerate methods. You'd call virConnectFindStoragePoolSources() with type='logical' this gives you back XML describing all available volume groups on a machine. For each volume group you want to use, you can then define a storage pool, and query volumes within it. > open issues - should we assume ISCSI auto connect or FC login? libvirt can take care of that when needed, which is why we have a two step process for accessing a storage pool - virStoragePoolDefineXML() will write out a persistent configuratipon file with details of the pool. - virStoragePoolCreate() will actually login to the iSCSI target, or activate the LVM volume group, or equivalent operations needed for the type of storage being accessed. NB 'Create' is probably better thought of as 'Start' You can later call virStoragePoolDestroy() to logout if desired. If you want login to happen automatically when the machine boots you can call virStoragePoolSetAutostart() to turn on the autostart flag. Authentication is an open, unresolved issue & welcome suggestions for how to deal with this. Our original thoughts were to just embed the iSCSI username/password in the XML configuration file for the storage pool, but we've not implemented this in the backend yet. > StoragePool level > ----------------- > createVolumeGroup(name, devices): > params: > name = name > devices - a list of UUIDs > description: > Should create a volume group out of the UUID list > In case multipathing is enabled then only the multipath > device should be used > In case it is not a PV yet then a PV is to be created. > Return: > Uuid of the VG This is accomplished with a combination of two methods. First you define the configuration for the pool, which requires giving the volume group name, and list of devices to become PVs in the VG. This is done with virStoragePoolDefineXML(). Then you actually format the PVs & construct the VG by invoking the virStoragePoolBuild() method. Once this is done, the virStoragePoolCreate() method will activate the VG. > > removeVolumeGroup(VG): > params: > VG - uuid of the Volume group > Description: > Remove all remains for the VolumeGroup (LVs, PVs ...) > Return: > Sucsess/failure Given a existing virStoragePoolPtr object, you can blow away the entire volume group using the API virStoragePoolDelete > mountNFS(server, remotePath, localPath, params) > params: > server - the NFS server name or IP > temotePath - remote server export path > localPath - local path to mount on > params - nfs mount params > description: > mounts the remote export onto the local path using the > mount params > return: > success/failure Each NFS mount is modelled as a storage pool. So as before, you'd create a XML document providing the configuration for server, remotePath, localPath, and then invoke virStoragePoolDefineXML() Then you can use virStoragePoolCreate() to mount the NFS server. Once done, you can use virStoragePoolListVolumes() to query files within the mount. > unmount(localPath, forceFlag) > params: > localPath - the local path to unmount > forceFlag - a flag indicating whether to force unmount > description: > unmounts local path (trivial) > return: > success/failure The virStoragePoolDestory() method will unmount the NFS volume. If you wish to also remove the persistent libvirt config file for the pool, then also issue virStoragePoolUndefine > Open issues: > 1. NFS configuration persistency? > 2. What happens in case the libvirt is restarted should it be > reconfigured? Most objects in the libvirt API have two modes of setup, one which is persistent, and one which is transient. The examples I've given earlier all describe persistent use. The general pattern is - virStoragePoolDefineXML() writes the persistent config - virStoragePoolCreate() activates the backend from persistent config - virStoragePoolDestroy() de-activates the backend - virStoragePoolUndefine() deletes the persistent config If you instead prefer to use transient objects, then you can do - virStoragePoolCreateXML() - activates a backend directly from XML - virStoragePoolDestroy() - de-actives the backend With this style, no persistent configuration file is written out to disk, so once destroyed, libvirt looses all knowledge of it. If libvirtd is restarted, all information about transient objects is lost. Persistent objects will be identified when libvirtd is started again. For persistent objects you can also set a autostart flag, so that libvirt will immediately activate them, if not already running. > VolumeGroup level > ----------------- > listPV(VG): > params: > VG - Volume group UUID > Description: > Lists all PV in a specific volume group > Return: > A list of PV UUIDs The XML description for a virStoragePoolPtr object pointing to a VG, will include information about the physical volumes it contains. > infoPV(VG, PV) > params: > VG - Volume group UUID > PV - Physical volume UUID > description: > trivial > return: > returns the PV information (at least size & path) Given a device path or device key (akin to UUID) you can use one of the methods virStorageVolLookupByPath virStorageVolLookupByKey to retrieve a virStorageVolPtr object for it. Once you have one of these, then you can call virStorageVolGetInfo, to find out its capacity / allocation > extendVolumeGroup(VG, devices): > params: > VG - Volume Group UUID > devices - a list of UUIDs > description: > This function adds Phisical Volume to the VolumeGroup. > Each UUID device is checked, In case multipathing is > enabled > then only the multipath device should be used (PV create > in case > it's not) and added to the volume group > return: > success/fauilure > > > removePV(VG, PV): > params: > VG - Volume Group UUID > PV - Physical volume's UUID to be removed > description: > removes the physical volume > return: > success failure These two are not currently implemented in libvirt. The intent is though, that you can re-define the XML for an existing virStoragePoolPtr object, with PV devices added/removed from the XML. Then invoke the virStoragePoolBuild() method to actually make the changes to the underlying volume group. > LV operations > -------------- > listLVs(VG): > params: > VG - Volume Group UUID > description: > trivial > return: > list of all LV UUIDs This is again possible with the virStoragePoolListVolumes() method once you have an active virStoragePoolPtr object for a volume group. > infoLV(VG, LV): > params: > VG - Volume Group UUID > LV - Logical Volume UUID > description: > trivial > return: > returns LV information (at least size and path) Given a virStorageVolPtr object for a LV, you can call virStorageVolGetInfo to get size information, or virStorageVolGetXMLDesc() for more general metadata. > createLV(VG, LvName, size): > params: > VG - Volume Group UUID > LvName - name of the logical volume Given a virStoragePoolPtr object refering to a volume group, you can use virStorageVolCreateXML() to allocate a new logical volume within it. Similarly virStorageVolDelete will remove a logical volume. All the method names I'm refering to here are the C apis. If you just want to experiment & play with the APIs to get a better understanding of them, the 'virsh' command line tool exposes practically all of the functionality in a fairly friendly manner. For example, using the virConnectFindStoragePoolSources() method to disocver LVM volume groups is possible with: # virsh find-storage-pool-sources-as logical <sources> <source> <device path='/dev/sda2'/> <name>HostVG</name> <format type='lvm2'/> </source> </sources> You can then use, virStoragePoolDefineXML with info by running the 'virsh pool-define' command, and so on - 'virsh help' will show you all the possible commands. Regards, Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list