grthtrhthjhtyjytjytkergtrhtrjytjerhrfh4:24 29/09/2026a d�td”•ã @sždZddlZddlZddlZddlZddlZddlZddlmZddl m Z ddl m Z ddl mZmZmZmZmZddl mZmZdd l mZmZdd l mZmZd Zd d „ZGdd„de ƒZGdd„deƒZGdd„deƒZGdd„deƒZGdd„deƒZGdd„deƒZ Gdd„de!ƒZ"eeeeeee dœZ#ee$dd�ee$dd d!�ee$d"d�ee$d#d$d!�e e$d%d�iZ%ia&Gd&d'„d'e ƒZ'd(d)„Z(e)d*k�rše(ƒdS)+a¼ Implements the RTS Target backstore and storage object classes. This file is part of RTSLib. Copyright (c) 2011-2013 by Datera, Inc Copyright (c) 2011-2014 by Red Hat, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. éN)Úrangeé)ÚALUATargetPortGroup)ÚCFSNode)ÚfreadÚfwriteÚ generate_wwnÚ RTSLibErrorÚRTSLibNotInCFS)Úconvert_scsi_path_to_hctlÚconvert_scsi_hctl_to_path)Ú is_dev_in_useÚget_blockdev_type)Úget_size_for_blk_devÚget_size_for_disk_namez/var/run/rtslib_backstore.lockcCs4zt| d¡ƒdkrWdSWnty.Yn0dS)zM Helper function that can be called by passthrough type of backends. Z alua_supportrTF)ÚintÚ get_attributer )Zso©rú./usr/lib/python3.9/site-packages/rtslib/tcm.pyÚ$storage_object_get_alua_support_attr&s   rcs`eZdZdZdd„ZdA‡fdd„ ZdBdd„Zd d „Zd d „Zd d„Z e dd„ƒZ e dd„ƒZ dd„Z dd„Zdd„Zdd„Zdd„Zdd„Zdd „Zd!d"„Zd#d$„Zd%d&„Zd'd(„Zd)d*„Zd+d,„Zd-d.„Zd/d0„ZdC‡fd2d3„ Zd4d5„Zeed6d7�Zeed8d7�Z eed9d7�Z!ee ed:d7�Z"eed;d7�Z#eedd7�Z&‡fd?d@„Z'‡Z(S)DÚ StorageObjectz This is an interface to storage objects in configFS. A StorageObject is identified by its backstore and its name. cCsd|jj|j|jfS)Nz <%s %s/%s>)Ú __class__Ú__name__ÚpluginÚname©ÚselfrrrÚ__repr__;szStorageObject.__repr__Ncsœtt|ƒ ¡d|vs.d|vs.d|vs.d|vr8tdƒ‚n||_t|t|ƒ||ƒ|_d|jj|j f|_ |jj |_ z|  |¡Wn|j  ¡‚Yn0dS)Nú/ú ú Ú zAA storage object's name cannot contain /, newline or spaces/tabsú%s/%s)ÚsuperrÚ__init__r Ú_nameÚ _BackstoreÚtypeÚ _backstoreÚpathrÚ_pathrÚ_create_in_cfs_ineÚdelete)rrÚmodeÚindex©rrrr$>s    zStorageObject.__init__cCs|s tdƒ}||_| ¡dS)NZ unit_serial)rÚwwnÚ_config_pr_aptpl©rr0rrrÚ _configureNszStorageObject._configurecCs|j|jko|j|jkS©N)rr©rÚotherrrrÚ__eq__UszStorageObject.__eq__cCs ||k Sr4rr5rrrÚ__ne__XszStorageObject.__ne__cCsºddlm}d|ƒj}ztd||jfƒ ¡}WnYdS0|d d¡sTdSg}|D]8}| d¡rpg}q\| d¡r†| |¡q\| | ¡¡q\|D]}t |j d d   |¡ƒqšdS) z¾ LIO actually *writes* pr aptpl info to the filesystem, so we need to read it in and squirt it back into configfs when we configure the storage object. BLEH. r©ÚRTSRootz%s/prz %s/aptpl_%sNrz PR_REG_START:z PR_REG_END:z/pr/res_aptpl_metadataú,) Úrootr:Zdbrootrr0ÚsplitÚ startswithÚappendÚstriprr)Újoin)rr:Z aptpl_dirÚlinesZ reservationsÚlineZres_listÚresrrrr1[s"     zStorageObject._config_pr_aptplccs2t d|j¡D]}tj |¡r| |¡VqdS)Nz %s/core/*_*/*)ÚglobÚ configfs_dirÚosr)ÚisdirÚ so_from_path)ÚclsZso_dirrrrÚallxs zStorageObject.allcCs6tj |¡}| d¡d dd¡\}}t|||d�S)zQ Build a StorageObject of the correct type from a configfs path. réþÿÿÿÚ_r)r.)rGr)Úbasenamer=ÚrsplitÚ so_mapping)rJr)Zso_nameZso_typeZso_indexrrrrI~s zStorageObject.so_from_pathcCs<| ¡| ¡r0d|j}t|ƒ d¡d ¡Stdƒ‚dS)Nú%s/wwn/vpd_unit_serialú:ézDCannot read a T10 WWN Unit Serial from an unconfigured StorageObject)Ú _check_selfÚ is_configuredr)rÚ partitionr@r ©rr)rrrÚ_get_wwn‡s  zStorageObject._get_wwncCs6| ¡| ¡r*d|j}t|d|ƒntdƒ‚dS)NrQz%s zCCannot write a T10 WWN Unit Serial to an unconfigured StorageObject)rTrUr)rr )rr0r)rrrÚ_set_wwn�s  zStorageObject._set_wwncCs$| ¡d|j}t|d|ƒdS)Nú %s/udev_pathú%s©rTr)r)rÚ udev_pathr)rrrÚ_set_udev_path™s zStorageObject._set_udev_pathcCs<| ¡d|j}t|ƒ}|s8|jjdkr8| d¡ ¡}|S)NrZÚfileioÚFile)rTr)rr(rÚ _parse_infor@)rr)r]rrrÚ_get_udev_pathžs  zStorageObject._get_udev_pathcCs|jjSr4)r(ÚversionrrrrÚ _get_version¦szStorageObject._get_versioncCs|jSr4)r%rrrrÚ _get_name©szStorageObject._get_namecCs | ¡d|j}t|dƒdS)Nú %s/enablez1 r\rWrrrÚ_enable¬s zStorageObject._enablecCs,| ¡d|j}t|dt|ƒ ¡ƒdS)Nz %s/controlr[©rTr)rÚstrr@)rZcommandr)rrrÚ_control±s zStorageObject._controlcCs,| ¡d|j}t|dt|ƒ ¡ƒdS)Nz%s/fdr[rh)rÚcontentsr)rrrÚ _write_fd¶s zStorageObject._write_fdcCsR| ¡td|jƒ}z"t d|d | ¡¡¡ d¡WStyLYdS0dS)Nú%s/infoú.*%s: ([^: ]+).*rr© rTrr)ÚreÚsearchrAr=ÚgroupÚAttributeError©rÚkeyÚinforrrra»sÿ ÿÿ zStorageObject._parse_infocCs| ¡| d¡ ¡S)NZStatus)rTraÚlowerrrrrÚ _get_statusÄszStorageObject._get_statusc cs6tjj}tjj}tj}tjj}|j}ddlm}ddlm }m }m } ddl m } dd„|ƒjDƒD]Î\} } || ƒD]¼} | | vrrd| | f}||ƒD]š}d||f}||ƒr’||ƒD]x}d||f}||ƒD]^}d||f}||ƒrÊ||ƒ|krÊ|d |}| d ¡}| | | ƒ}||||dƒ|d ƒVqÊq²q’qrqbd S) zž Fast scan of luns attached to a storage object. This is an order of magnitude faster than using root.luns and matching path on them. rr9)ÚLUNÚTPGÚTarget)Útarget_names_excludescss|]}|jr|j|fVqdSr4)Úexistsr))Ú.0ÚfmrrrÚ Öóz3StorageObject._gen_attached_luns..r"z %s/%s/lunrMéN)rGr)rHÚislinkÚlistdirÚrealpathr<r:Útargetryrzr{Zfabricr|Zfabric_modulesr=)rrHrƒr„r…r)r:ryrzr{r|ÚbaserZtgt_dirZ tpgts_baseZtpgt_dirZ luns_baseZlun_dirZ links_baseZlun_fileÚlinkÚvalr†rrrÚ_gen_attached_lunsÈs0             z StorageObject._gen_attached_lunsccs | ¡| ¡D] }|VqdS)zB Generates all luns attached to a storage object. N)rTrŠ)rÚlunrrrÚ_list_attached_lunsçs z!StorageObject._list_attached_lunsccs4| ¡t d|j¡D]}|jrt||ƒVqdS)zF Generate all ALUA groups attach to a storage object. z%s/aluaN)rTrGr„r)Úalua_supportedr)rÚtpgrrrÚ_list_alua_tpgsïszStorageObject._list_alua_tpgscCs | ¡dS)zU Children should override if the backend did not always support ALUA T)rTrrrrÚ_get_alua_supportedøsz!StorageObject._get_alua_supportedFcs¤| ¡| ¡D]}|jdkr| ¡q| ¡rV| ¡D]}|jdkrLqVq8| ¡q8tt|ƒ ¡|j  ¡|r ddl m }m }|ƒ  |d|jd|j¡dS)a$ Recursively deletes a StorageObject object. This will delete all attached LUNs currently using the StorageObject object, and then the StorageObject itself. The underlying file and block storages will not be touched, but all ramdisk data will be lost. Zdefault_tg_pt_gpZ activatedr)r:Údefault_save_filez /backstores/rN)rTr�rr,rUrŠÚstatusr#rr(r<r:r‘Z save_to_filerr%)rZsaveZalua_tpgr‹r:r‘r/rrr,s       zStorageObject.deletecCs6| ¡d|j}tj |¡r.ttt|ƒƒƒSdSdS)zV @return: True if the StorageObject is configured, else returns False rfTN)rTr)rGÚisfileÚboolrrrWrrrrUs   zStorageObject.is_configuredz0Get the version of the StorageObject's backstore©Údocz'Get the StorageObject name as a string.z,Get the StorageObject udev_path as a string.z8Get or set the StorageObject T10 WWN Serial as a string.zOGet the storage object status, depending on whether or not itis used by any LUNz)Get the list of all LUN objects attached.z-Get list of ALUA Target Port Groups attached.ú:Returns true if ALUA can be setup. False if not supported.cs:tt|ƒ ¡}|j|d<|j|d<dd„|jDƒ|d<|S)NrrcSsg|] }| ¡‘qSr)Údump)r~rŽrrrÚ ?r�z&StorageObject.dump..Ú alua_tpgs)r#rr˜rrrš©rÚdr/rrr˜;s   zStorageObject.dump)N)N)F))rÚ __module__Ú __qualname__Ú__doc__rr$r3r7r8r1Ú classmethodrKrIrXrYr^rbrdrergrjrlrarxrŠrŒr�r�r,rUÚpropertyrcrr]r0r’Z attached_lunsršr�r˜Ú __classcell__rrr/rr4sj         ÿÿÿÿÿÿÿÿrcsòeZdZdZd%‡fdd„ Z‡fdd„Zdd„Zd d „Zd d „Zd d„Z dd„Z dd„Z dd„Z dd„Z dd„Zeejedd�Zeedd�Zeedd�Zee dd�Zee dd�Zee dd�Zee d d�Zee d!d�Zeed"d�Z‡fd#d$„Z‡ZS)&ÚPSCSIStorageObjectzG An interface to configFS storage objects for pscsi backstore. Ncs\|durDtt|ƒ |d|¡z| |¡WqX| ¡‚YqX0ntt|ƒ |d|¡dS)a A PSCSIStorageObject can be instantiated in two ways: - B{Creation mode}: If I{dev} is specified, the underlying configFS object will be created with that parameter. No PSCSIStorageObject with the same I{name} can pre-exist in the parent PSCSIBackstore in that mode, or instantiation will fail. - B{Lookup mode}: If I{dev} is not set, then the PSCSIStorageObject will be bound to the existing configFS object in the parent PSCSIBackstore having the specified I{name}. The underlying configFS object must already exist in that mode, or instantiation will fail. @param name: The name of the PSCSIStorageObject. @type name: string @param dev: You have two choices: - Use the SCSI id of the device: I{dev="H:C:T:L"}. - Use the path to the SCSI device: I{dev="/path/to/dev"}. @type dev: string @return: A PSCSIStorageObject object. NÚcreateÚlookup)r#r£r$r3r,)rrÚdevr.r/rrr$Js zPSCSIStorageObject.__init__c s | ¡zt|ƒ\}}}}| ¡}Wntz6| d¡\}}}}t|ƒ}t|ƒ}t|ƒ}t|ƒ}Wn"ty„tdd|ƒ‚Yn0t||||ƒ}Yn0t|ƒrÀtdd|||||fdƒ‚|  d|d|d |d |¡|  |¡|  ¡t t |ƒ ¡dS) NrRzBCannot find SCSI device by path, and dev parameter not in H:C:T:L z format: %sú'Cannot configure StorageObject because zdevice %s (SCSI %d:%d:%d:%d) zis already in usezscsi_host_id=%d,zscsi_channel_id=%d,zscsi_target_id=%d,zscsi_lun_id=%d)rTr r@r=rÚ ValueErrorr r r rjr^rgr#r£r3)rr¦ZhostidZ channelidZtargetidZlunidr]r/rrr3isRÿ    ý ý ÿÿÿü ÿþý zPSCSIStorageObject._configurecCsdSr4rr2rrrrY—szPSCSIStorageObject._set_wwncCs:| ¡td|jƒ}tt dd | ¡¡¡ d¡ƒ  ¡S)Nrmz.*Model:(.*)Rev:rr© rTrr)rirprqrAr=rrr@©rrvrrrÚ _get_model›s ÿÿzPSCSIStorageObject._get_modelcCs:| ¡td|jƒ}tt dd | ¡¡¡ d¡ƒ  ¡S)Nrmz.*Vendor:(.*)Model:rrr©rªrrrÚ _get_vendor¡s ÿÿzPSCSIStorageObject._get_vendorcCs| ¡| d¡S)NZRev©rTrarrrrÚ _get_revision§sz PSCSIStorageObject._get_revisioncCs| ¡t| d¡ƒS)Nz Channel ID©rTrrarrrrÚ_get_channel_id«sz"PSCSIStorageObject._get_channel_idcCs| ¡t| d¡ƒS)Nz Target IDr¯rrrrÚ_get_target_id¯sz!PSCSIStorageObject._get_target_idcCs| ¡t| d¡ƒS)Nryr¯rrrrÚ_get_lun³szPSCSIStorageObject._get_luncCs| ¡t| d¡ƒS)NzHost IDr¯rrrrÚ _get_host_id·szPSCSIStorageObject._get_host_idcCs| ¡t|ƒSr4©rTrrrrrr�»sz&PSCSIStorageObject._get_alua_supportedziGet the StorageObject T10 WWN Unit Serial as a string. You cannot set it for pscsi-backed StorageObjects.r•z Get the SCSI device model stringz!Get the SCSI device vendor stringz#Get the SCSI device revision stringzGet the SCSI device host idzGet the SCSI device channel idzGet the SCSI device target idzGet the SCSI device LUNr—cstt|ƒ ¡}|j|d<|S)Nr¦)r#r£r˜r]r›r/rrr˜Õs zPSCSIStorageObject.dump)NN)rr�ržrŸr$r3rYr«r¬r®r°r±r²r³r�r¡rrXr0ZmodelZvendorZrevisionZhost_idZ channel_idZ target_idr‹r�r˜r¢rrr/rr£CsP .ÿÿÿÿÿÿÿÿÿr£csŠeZdZdZd‡fdd„ Z‡fdd„Zdd „Zd d „Zd d „Zdd„Z e edd�Z e edd�Z e edd�Z e e dd�Z‡fdd„Z‡ZS)ÚRDMCPStorageObjectzH An interface to configFS storage objects for rd_mcp backstore. NFcs`|durHtt|ƒ |d|¡z| |||¡Wq\| ¡‚Yq\0ntt|ƒ |d|¡dS)aO A RDMCPStorageObject can be instantiated in two ways: - B{Creation mode}: If I{size} is specified, the underlying configFS object will be created with that parameter. No RDMCPStorageObject with the same I{name} can pre-exist in the parent Backstore in that mode, or instantiation will fail. - B{Lookup mode}: If I{size} is not set, then the RDMCPStorageObject will be bound to the existing configFS object in the parent Backstore having the specified I{name}. The underlying configFS object must already exist in that mode, or instantiation will fail. @param name: The name of the RDMCPStorageObject. @type name: string @param size: The size of the ramdrive to create, in bytes. @type size: int @param wwn: T10 WWN Unit Serial, will generate if None @type wwn: string @param nullio: If rd should be created w/o backing page store. @type nullio: boolean @return: A RDMCPStorageObject object. Nr¤r¥)r#rµr$r3r,)rrÚsizer0Únullior.r/rrr$âs zRDMCPStorageObject.__init__cs`| ¡tt|ƒt ¡ƒ}|dkr(d}| d|¡|rD| d¡| ¡tt|ƒ  |¡dS)Nrrz rd_pages=%dz rd_nullio=1) rTÚroundÚfloatÚresourceZ getpagesizerjrgr#rµr3)rr¶r0r·r/rrr3s zRDMCPStorageObject._configurecCs | ¡t| d¡ d¡dƒS)NúPAGES/PAGE_SIZEÚ*r©rTrrar=rrrrÚ_get_page_sizesz!RDMCPStorageObject._get_page_sizecCs | ¡t| d¡ d¡dƒS)Nr»r¼rr½rrrrÚ _get_pagesszRDMCPStorageObject._get_pagescCs| ¡| ¡| ¡}|Sr4)rTr¾r¿)rr¶rrrÚ _get_sizeszRDMCPStorageObject._get_sizecCs6| ¡ztt| d¡ƒƒWSty0YdS0dS)Nr·F©rTr”rrarsrrrrÚ _get_nullios  zRDMCPStorageObject._get_nulliozGet the ramdisk page size.r•z Get the ramdisk number of pages.zGet the ramdisk size in bytes.zGet the nullio status.cs4tt|ƒ ¡}|j|d<|j|d<|jr0d|d<|S)Nr0r¶Tr·)r#rµr˜r0r¶r·r›r/rrr˜2s   zRDMCPStorageObject.dump)NNFN)rr�ržrŸr$r3r¾r¿rÀrÂr¡Z page_sizeZpagesr¶r·r˜r¢rrr/rrµÛs("  ÿÿÿÿrµcsŠeZdZdZd‡fdd„ Z‡fdd„Zdd „Zd d „Zd d „Zdd„Z e edd�Z e edd�Z e edd�Z e e dd�Z‡fdd„Z‡ZS)ÚFileIOStorageObjectzH An interface to configFS storage objects for fileio backstore. NFcsd|durLtt|ƒ |d|¡z| |||||¡Wq`| ¡‚Yq`0ntt|ƒ |d|¡dS)að A FileIOStorageObject can be instantiated in two ways: - B{Creation mode}: If I{dev} and I{size} are specified, the underlying configFS object will be created with those parameters. No FileIOStorageObject with the same I{name} can pre-exist in the parent Backstore in that mode, or instantiation will fail. - B{Lookup mode}: If I{dev} and I{size} are not set, then the FileIOStorageObject will be bound to the existing configFS object in the parent Backstore having the specified I{name}. The underlying configFS object must already exist in that mode, or instantiation will fail. @param name: The name of the FileIOStorageObject. @type name: string @param dev: The path to the backend file or block device to be used. - Examples: I{dev="/dev/sda"}, I{dev="/tmp/myfile"} - The only block device type that is accepted I{TYPE_DISK}, or partitions of a I{TYPE_DISK} device. For other device types, use pscsi. @type dev: string @param size: Size of the object, if not a block device @type size: int @param wwn: T10 WWN Unit Serial, will generate if None @type wwn: string @param write_back: Should we create the StorageObject with write caching enabled? Disabled by default @type write_back: bool @return: A FileIOStorageObject object. Nr¤r¥)r#rÃr$r3r,)rrr¦r¶r0Ú write_backÚaior.r/rrr$Cs  zFileIOStorageObject.__init__csä| ¡t|ƒ}|dur\tj |¡r8tj |¡s8tdƒ‚|durHtdƒ‚| d||f¡n2|dkrltdƒ‚t|ƒr€td|ƒ‚| d|¡|r¬|  dd ¡| d |¡|r¾| d |¡|  |¡|  ¡t t |ƒ |¡dS) Nz"Path not to a file or block devicezPath is to a file, size neededzfd_dev_name=%s,fd_dev_size=%drz&Device is not a TYPE_DISK block devicezDevice %s is already in usezfd_dev_name=%sÚemulate_write_cacherzfd_buffered_io=%dzfd_async_io=%d)rTrrGr)r}r“r rjr Z set_attributer^rgr#rÃr3)rr¦r¶r0rÄrÅZ block_typer/rrr3ms*   zFileIOStorageObject._configurecCs| ¡tt| d¡ƒƒS©NrÆ©rTr”rrrrrrÚ_get_wb_enabled’sz#FileIOStorageObject._get_wb_enabledcCs<| ¡|jr*t| d¡ƒt| d¡ƒSt| d¡ƒSdS)Nr`Ú SectorSizeÚSize)rTÚis_blockrrarrrrrrÀ–s   ÿzFileIOStorageObject._get_sizecCst|jƒduSr4)rr]rrrrÚ _is_blockŸszFileIOStorageObject._is_blockcCsF| ¡td|jƒ}t dd | ¡¡¡}|s4dStt|  d¡ƒƒS)Nrmz.*Async: ([^: ]+).*rFr) rTrr)rprqrAr=r”rrr)rrvÚrrrrÚ_aio¢s zFileIOStorageObject._aioúATrue if write-back, False if write-through (write cache disabled)r•z+Get the current FileIOStorage size in byteszCTrue if FileIoStorage is backed by a block device instead of a filez#True if asynchronous I/O is enabledcsDtt|ƒ ¡}|j|d<|j|d<|j|d<|j|d<|j|d<|S)NrÄr0r¦r¶rÅ)r#rÃr˜rÄr0r]r¶rÅr›r/rrr˜¶s     zFileIOStorageObject.dump)NNNFFN)rr�ržrŸr$r3rÉrÀrÍrÏr¡rÄr¶rÌrÅr˜r¢rrr/rrÃ<s,ÿ* %  ÿÿÿÿrÃcsžeZdZdZd‡fdd„ Z‡fdd„Zdd „Zd d „Zd d „Zdd„Z dd„Z e edd�Z e edd�Z e edd�Ze e dd�Ze e dd�Z‡fdd„Z‡ZS)ÚBlockStorageObjectzG An interface to configFS storage objects for block backstore. NFcs`|durHtt|ƒ |d|¡z| |||¡Wq\| ¡‚Yq\0ntt|ƒ |d|¡dS)aw A BlockIOStorageObject can be instantiated in two ways: - B{Creation mode}: If I{dev} is specified, the underlying configFS object will be created with that parameter. No BlockIOStorageObject with the same I{name} can pre-exist in the parent Backstore in that mode. - B{Lookup mode}: If I{dev} is not set, then the BlockIOStorageObject will be bound to the existing configFS object in the parent Backstore having the specified I{name}. The underlying configFS object must already exist in that mode, or instantiation will fail. @param name: The name of the BlockIOStorageObject. @type name: string @param dev: The path to the backend block device to be used. - Example: I{dev="/dev/sda"}. - The only device type that is accepted I{TYPE_DISK}. For other device types, use pscsi. @type dev: string @param wwn: T10 WWN Unit Serial, will generate if None @type wwn: string @return: A BlockIOStorageObject object. Nr¤r¥)r#rÑr$r3r,)rrr¦r0ÚreadonlyrÄr.r/rrr$Çs zBlockStorageObject.__init__csz| ¡t|ƒdkr td|ƒ‚t|ƒr8tdd|ƒ‚| |¡| d|¡| d|¡| ¡tt|ƒ  |¡dS)Nrz)Device %s is not a TYPE_DISK block devicer§zdevice %s is already in usez udev_path=%sz readonly=%d) rTrr r r^rjrgr#rÑr3)rr¦r0rÒr/rrr3ës  ÿ zBlockStorageObject._configurecCs| ¡t| d¡ƒS)NZMajorr¯rrrrÚ _get_majorùszBlockStorageObject._get_majorcCs| ¡t| d¡ƒS)NZMinorr¯rrrrÚ _get_minorýszBlockStorageObject._get_minorcCst| d¡ƒt| d¡ƒS)NZdevicerÊ)rrarrrrrrÀszBlockStorageObject._get_sizecCs| ¡tt| d¡ƒƒSrÇrÈrrrrrÉsz"BlockStorageObject._get_wb_enabledcCs6| ¡ztt| d¡ƒƒWSty0YdS0dS)NrÒFrÁrrrrÚ _get_readonly s  z BlockStorageObject._get_readonlyz!Get the block device major numberr•z!Get the block device minor numberzGet the block device sizerÐz4True if the device is read-only, False if read/writecs:tt|ƒ ¡}|j|d<|j|d<|j|d<|j|d<|S)NrÄrÒr0r¦)r#rÑr˜rÄrÒr0r]r›r/rrr˜s     zBlockStorageObject.dump)NNFFN)rr�ržrŸr$r3rÓrÔrÀrÉrÕr¡ÚmajorÚminorr¶rÄrÒr˜r¢rrr/rrÑÀs4ÿ$  ÿÿÿÿÿrÑcsžeZdZdZd‡fdd„ Z‡fdd„Zdd„Zd d „Zd d „Zd d„Z dd„Z e edd�Z e edd�Z e edd�Ze e dd�Ze e dd�Z‡fdd„Z‡ZS)ÚUserBackedStorageObjectzR An interface to configFS storage objects for userspace-backed backstore. Ncs„|durl|durtdƒ‚d|vr(tdƒ‚tt|ƒ |d|¡z| |||||¡Wq€| ¡‚Yq€0ntt|ƒ |d|¡dS)aÌ @param name: The name of the UserBackedStorageObject. @type name: string @param config: user-handler-specific config string. - e.g. "rbd/machine1@snap4" @type config: string @param size: The size of the device to create, in bytes. @type size: int @param wwn: T10 WWN Unit Serial, will generate if None @type wwn: string @hw_max_sectors: Max sectors per command limit to export to initiators. @type hw_max_sectors: int @control: String of control=value tuples separate by a ',' that will passed to the kernel control file. @type: string @return: A UserBackedStorageObject object. NzK'size' and 'config' must be set when creating a new UserBackedStorageObjectrzL'config' must contain a '/' separating subtype from its configuration stringr¤r¥)r r#rØr$r3r,)rrÚconfigr¶r0Úhw_max_sectorsÚcontrolr.r/rrr$,s z UserBackedStorageObject.__init__csx| ¡d|vrtdƒ‚| d|¡| d|¡|durJ| d|¡|dur\| |¡| ¡tt|ƒ |¡dS)NrRz ':' not allowed in config stringz dev_config=%sz dev_size=%dzhw_max_sectors=%s)rTr rjrgr#rØr3)rrÙr¶r0rÚrÛr/rrr3Ps z"UserBackedStorageObject._configurecCs| ¡t| d¡ƒS)NrËr¯rrrrrÀ_sz!UserBackedStorageObject._get_sizecCs| ¡t| d¡ƒS)NZ HwMaxSectorsr¯rrrrÚ_get_hw_max_sectorscsz+UserBackedStorageObject._get_hw_max_sectorscCsv| ¡g}| d¡}|dkr,| d|¡| d¡}|dkrL| d|¡| d¡}|dkrl| d|¡d |¡S) NZ MaxDataAreaMBÚNULLzmax_data_area_mb=%sZ hw_block_sizezhw_block_size=%sZDataPagesPerBlkzdata_pages_per_blk=%sr;)rTrar?rrA)rZtuplesr‰rrrÚ_get_control_tuplesgs   z+UserBackedStorageObject._get_control_tuplescCs"| ¡| d¡}|dkrdS|S)NZConfigrÝr­)rr‰rrrÚ _get_configys  z#UserBackedStorageObject._get_configcCs| ¡t|ƒSr4r´rrrrr�€sz+UserBackedStorageObject._get_alua_supportedz Get the max sectors per command.r•z?Get the comma separated string containing control=value tuples.zGet the size in bytes.zGet the TCMU config.r—csDtt|ƒ ¡}|j|d<|j|d<|j|d<|j|d<|j|d<|S)Nr0r¶rÙrÚrÛ)r#rØr˜r0r¶rÙrÚÚcontrol_tuplesr›r/rrr˜�s     zUserBackedStorageObject.dump)NNNNNN)rr�ržrŸr$r3rÀrÜrÞrßr�r¡rÚràr¶rÙr�r˜r¢rrr/rrØ's4ÿ$ ÿÿÿÿÿrØc@seZdZdZdd„ZdS)ÚStorageObjectFactoryzY Create a storage object based on a given path. Only works for file & block. cCsl| d¡ dd¡}tj |¡r\t |¡}t |j¡r@t||d�St  |j¡r\t |||j d�St d|ƒ‚dS)Nrú-)rr¦)rr¦r¶z(Can't create storageobject from path: %s) r@ÚreplacerGr)r}ÚstatÚS_ISBLKÚst_moderÑÚS_ISREGrÃÚst_sizer )rJr)rÚsrrrÚ__new__ s     zStorageObjectFactory.__new__N)rr�ržrŸrêrrrrrášsrá)ÚpscsiÚrd_mcpÚramdiskr_ÚiblockÚblockÚuserrë)rrírì)rÚ alt_dirprefixr_rïrîrðcs†eZdZdZd‡fdd„ Z‡fdd„Zdd„Zd d „Zd d „Zd d„Z dd„Z e e dd�Z e edd�Z e edd�Ze e dd�Z‡ZS)r&z¬ Backstore is needed as a level in the configfs hierarchy, but otherwise useless. 1:1 so:backstore. Created by storageobject ctor before SO configfs entry. Ncsôtt|ƒ ¡||_t|jd|_t|j d|j¡}|dur˜ts˜t  d|j ¡D]B}|  d¡}|d}|d  dd¡\} } d | |f} t | ƒt| <qTd ||f|_|durät |jd¡|_|jdkrî|d krîtd |j|fƒ‚n t |ƒ|_|jdk�rª|d k�rtd |j|fƒ‚n’tj d¡�s0t d¡ttdƒ} t | tj¡tt ¡ƒ} tdƒD](}|| v�r\||_|jt|j<�qœ�q\t | tj¡tdƒ‚t | tj¡d|j ||jf|_z|  |¡Wn"|jtv�rèt|j=‚Yn0dS)Nrrñz%s/core/*_*/*/rrLéýÿÿÿrMrr"r¤zStorage object %s/%s existsr¥zStorage object %s/%s not foundz/var/runzw+izNo available backstore indexz %s/core/%s_%d)!r#r&r$Z_so_clsÚ bs_paramsÚ_pluginÚgetÚbs_cacherEZiglobrFr=rOrÚ _lookup_keyÚ_indexr r rGr)r}ÚmakedirsÚopenÚ lock_fileÚfcntlZflockZLOCK_EXÚsetÚvaluesrZLOCK_UNr*r+)rrZstorage_object_clsr-r.ZdirpÚdirÚpartsZbs_nameZbs_dirpZbs_indexZ current_keyZlkfdZindexesr/rrr$Ês^   ÿ   ÿ       þ z_Backstore.__init__cs$tt|ƒ ¡|jtvr t|j=dSr4)r#r&r,r÷rörr/rrr,s z_Backstore.deletecCs|jSr4)rørrrrÚ _get_indexsz_Backstore._get_indexcCsR| ¡td|jƒ}z"t d|d | ¡¡¡ d¡WStyLYdS0dS)Nz %s/hba_infornrrrortrrrra sÿ ÿÿ z_Backstore._parse_infocCs| ¡| d¡S)Nrcr­rrrrrdsz_Backstore._get_versioncCs| ¡|jSr4)rTrôrrrrÚ _get_pluginsz_Backstore._get_plugincCs| ¡d|j|jfS)Nz%s%d)rTrr.rrrrresz_Backstore._get_namezGet the backstore plugin name.r•z"Get the backstore index as an int.z(Get the Backstore plugin version string.zGet the backstore name.)N)rr�ržrŸr$r,rrardrrer¡rr.rcrr¢rrr/rr&Ãs(9  ÿÿÿÿr&cCsddl}| ¡dS)Nr)ÚdoctestZtestmod)rrrrÚ_test*srÚ__main__)*rŸrGrärprErürºZ six.movesrZaluarZnoderZutilsrrrr r r r r rrrrûrrr£rµrÃrÑrØÚobjectrárPÚdictrórör&rrrrrrÚsZ   agsù     ûg