2016-02-18 02:53:35 +03:00
# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from . automatedproperties import AutomatedProperties
from . import utils
2022-08-31 19:20:49 +03:00
from . utils import vg_obj_path_generate , log_error , _handle_execute , LvmBug
2016-02-18 02:53:35 +03:00
import dbus
from . import cmdhandler
from . import cfg
from . cfg import LV_INTERFACE , THIN_POOL_INTERFACE , SNAPSHOT_INTERFACE , \
2019-10-09 15:49:58 +03:00
LV_COMMON_INTERFACE , CACHE_POOL_INTERFACE , LV_CACHED , VDO_POOL_INTERFACE
2016-02-18 02:53:35 +03:00
from . request import RequestEntry
2019-10-09 15:49:58 +03:00
from . utils import n , n32 , d
2016-02-18 02:53:35 +03:00
from . loader import common
from . state import State
from . import background
2022-09-08 23:38:31 +03:00
from . utils import round_size , mt_remove_dbus_objects , lvm_column_key
2016-06-28 20:07:21 +03:00
from . job import JobState
2016-02-18 02:53:35 +03:00
2023-02-16 19:24:06 +03:00
# Try and build a key for a LV, so that we sort the LVs with the least dependencies
# first. This may be error-prone because of the flexibility LVM
2016-06-10 19:58:55 +03:00
# provides and what you can stack.
def get_key ( i ) :
name = i [ ' lv_name ' ]
parent = i [ ' lv_parent ' ]
pool = i [ ' pool_lv ' ]
a1 = " "
a2 = " "
if name [ 0 ] == ' [ ' :
a1 = ' # '
# We have a parent
if parent :
# Check if parent is hidden
if parent [ 0 ] == ' [ ' :
a2 = ' ## '
else :
a2 = ' # '
# If a LV has a pool, then it should be sorted/loaded after the pool
# lv, unless it's a hidden too, then after other hidden, but before visible
if pool :
if pool [ 0 ] != ' [ ' :
a2 + = ' ~ '
else :
a1 = ' $ ' + a1
return " %s %s %s " % ( a1 , a2 , name )
2016-02-18 02:53:35 +03:00
# noinspection PyUnusedLocal
def lvs_state_retrieve ( selection , cache_refresh = True ) :
rc = [ ]
if cache_refresh :
cfg . db . refresh ( )
2022-08-31 19:20:49 +03:00
try :
lvmdbusd: Handle missing key in get_key
When we sort the LVs, we can stumble on a missing key, protect against
this as well.
Seen in error injection testing:
Traceback (most recent call last):
File "/home/tasleson/projects/lvm2/daemons/lvmdbusd/fetch.py", line 198, in update_thread
num_changes = load(*_load_args(queued_requests))
File "/home/tasleson/projects/lvm2/daemons/lvmdbusd/fetch.py", line 83, in load
rc = MThreadRunner(_main_thread_load, refresh, emit_signal).done()
File "/home/tasleson/projects/lvm2/daemons/lvmdbusd/utils.py", line 726, in done
raise self.exception
File "/home/tasleson/projects/lvm2/daemons/lvmdbusd/utils.py", line 732, in _run
self.rc = self.f(*self.args)
File "/home/tasleson/projects/lvm2/daemons/lvmdbusd/fetch.py", line 40, in _main_thread_load
(lv_changes, remove) = load_lvs(
File "/home/tasleson/projects/lvm2/daemons/lvmdbusd/lv.py", line 148, in load_lvs
return common(
File "/home/tasleson/projects/lvm2/daemons/lvmdbusd/loader.py", line 37, in common
objects = retrieve(search_keys, cache_refresh=False)
File "/home/tasleson/projects/lvm2/daemons/lvmdbusd/lv.py", line 72, in lvs_state_retrieve
lvs = sorted(cfg.db.fetch_lvs(selection), key=get_key)
File "/home/tasleson/projects/lvm2/daemons/lvmdbusd/lv.py", line 35, in get_key
pool = i['pool_lv']
KeyError: 'pool_lv'
2023-03-09 20:21:27 +03:00
# When building up the model, it's best to process LVs with the least
# dependencies to those that are dependant upon other LVs. Otherwise, when
# we are trying to gather information we could be in a position where we
# don't have information available yet.
lvs = sorted ( cfg . db . fetch_lvs ( selection ) , key = get_key )
2022-08-31 19:20:49 +03:00
for l in lvs :
if cfg . vdo_support :
rc . append ( LvStateVdo (
l [ ' lv_uuid ' ] , l [ ' lv_name ' ] ,
l [ ' lv_path ' ] , n ( l [ ' lv_size ' ] ) ,
l [ ' vg_name ' ] ,
l [ ' vg_uuid ' ] , l [ ' pool_lv_uuid ' ] ,
l [ ' pool_lv ' ] , l [ ' origin_uuid ' ] , l [ ' origin ' ] ,
n32 ( l [ ' data_percent ' ] ) , l [ ' lv_attr ' ] ,
l [ ' lv_tags ' ] , l [ ' lv_active ' ] , l [ ' data_lv ' ] ,
l [ ' metadata_lv ' ] , l [ ' segtype ' ] , l [ ' lv_role ' ] ,
l [ ' lv_layout ' ] ,
n32 ( l [ ' snap_percent ' ] ) ,
n32 ( l [ ' metadata_percent ' ] ) ,
n32 ( l [ ' copy_percent ' ] ) ,
n32 ( l [ ' sync_percent ' ] ) ,
n ( l [ ' lv_metadata_size ' ] ) ,
l [ ' move_pv ' ] ,
l [ ' move_pv_uuid ' ] ,
l [ ' vdo_operating_mode ' ] ,
l [ ' vdo_compression_state ' ] ,
l [ ' vdo_index_state ' ] ,
n ( l [ ' vdo_used_size ' ] ) ,
d ( l [ ' vdo_saving_percent ' ] ) ,
l [ ' vdo_compression ' ] ,
l [ ' vdo_deduplication ' ] ,
l [ ' vdo_use_metadata_hints ' ] ,
n32 ( l [ ' vdo_minimum_io_size ' ] ) ,
n ( l [ ' vdo_block_map_cache_size ' ] ) ,
n32 ( l [ ' vdo_block_map_era_length ' ] ) ,
l [ ' vdo_use_sparse_index ' ] ,
n ( l [ ' vdo_index_memory_size ' ] ) ,
n ( l [ ' vdo_slab_size ' ] ) ,
n32 ( l [ ' vdo_ack_threads ' ] ) ,
n32 ( l [ ' vdo_bio_threads ' ] ) ,
n32 ( l [ ' vdo_bio_rotation ' ] ) ,
n32 ( l [ ' vdo_cpu_threads ' ] ) ,
n32 ( l [ ' vdo_hash_zone_threads ' ] ) ,
n32 ( l [ ' vdo_logical_threads ' ] ) ,
n32 ( l [ ' vdo_physical_threads ' ] ) ,
n32 ( l [ ' vdo_max_discard ' ] ) ,
l [ ' vdo_write_policy ' ] ,
n32 ( l [ ' vdo_header_size ' ] ) ) )
else :
rc . append ( LvState (
l [ ' lv_uuid ' ] , l [ ' lv_name ' ] ,
l [ ' lv_path ' ] , n ( l [ ' lv_size ' ] ) ,
l [ ' vg_name ' ] ,
l [ ' vg_uuid ' ] , l [ ' pool_lv_uuid ' ] ,
l [ ' pool_lv ' ] , l [ ' origin_uuid ' ] , l [ ' origin ' ] ,
n32 ( l [ ' data_percent ' ] ) , l [ ' lv_attr ' ] ,
l [ ' lv_tags ' ] , l [ ' lv_active ' ] , l [ ' data_lv ' ] ,
l [ ' metadata_lv ' ] , l [ ' segtype ' ] , l [ ' lv_role ' ] ,
l [ ' lv_layout ' ] ,
n32 ( l [ ' snap_percent ' ] ) ,
n32 ( l [ ' metadata_percent ' ] ) ,
n32 ( l [ ' copy_percent ' ] ) ,
n32 ( l [ ' sync_percent ' ] ) ,
n ( l [ ' lv_metadata_size ' ] ) ,
l [ ' move_pv ' ] ,
l [ ' move_pv_uuid ' ] ) )
except KeyError as ke :
# Sometimes lvm omits returning one of the keys we requested.
key = ke . args [ 0 ]
2022-09-08 23:38:31 +03:00
if lvm_column_key ( key ) :
2022-08-31 19:20:49 +03:00
raise LvmBug ( " missing JSON key: ' %s ' " % key )
raise ke
2016-02-18 02:53:35 +03:00
return rc
def load_lvs ( lv_name = None , object_path = None , refresh = False , emit_signal = False ,
cache_refresh = True ) :
# noinspection PyUnresolvedReferences
return common (
lvs_state_retrieve ,
( LvCommon , Lv , LvThinPool , LvSnapShot ) ,
lv_name , object_path , refresh , emit_signal , cache_refresh )
# noinspection PyPep8Naming,PyUnresolvedReferences,PyUnusedLocal
class LvState ( State ) :
@staticmethod
def _pv_devices ( uuid ) :
rc = [ ]
for pv in sorted ( cfg . db . lv_contained_pv ( uuid ) ) :
( pv_uuid , pv_name , pv_segs ) = pv
2016-09-28 19:16:49 +03:00
pv_obj = cfg . om . get_object_path_by_uuid_lvm_id ( pv_uuid , pv_name )
2016-08-29 20:32:20 +03:00
segs_decorate = [ ]
for i in pv_segs :
segs_decorate . append ( ( dbus . UInt64 ( i [ 0 ] ) ,
dbus . UInt64 ( i [ 1 ] ) ,
dbus . String ( i [ 2 ] ) ) )
rc . append ( ( dbus . ObjectPath ( pv_obj ) , segs_decorate ) )
2016-02-18 02:53:35 +03:00
return dbus . Array ( rc , signature = " (oa(tts)) " )
def vg_name_lookup ( self ) :
return cfg . om . get_object_by_path ( self . Vg ) . Name
@property
def lvm_id ( self ) :
return " %s / %s " % ( self . vg_name_lookup ( ) , self . Name )
def identifiers ( self ) :
return ( self . Uuid , self . lvm_id )
def _get_hidden_lv ( self ) :
rc = dbus . Array ( [ ] , " o " )
vg_name = self . vg_name_lookup ( )
for l in cfg . db . hidden_lvs ( self . Uuid ) :
full_name = " %s / %s " % ( vg_name , l [ 1 ] )
2016-09-28 19:16:49 +03:00
op = cfg . om . get_object_path_by_uuid_lvm_id ( l [ 0 ] , full_name )
2016-02-18 02:53:35 +03:00
assert op
2016-08-29 20:32:20 +03:00
rc . append ( dbus . ObjectPath ( op ) )
2016-02-18 02:53:35 +03:00
return rc
def __init__ ( self , Uuid , Name , Path , SizeBytes ,
vg_name , vg_uuid , pool_lv_uuid , PoolLv ,
origin_uuid , OriginLv , DataPercent , Attr , Tags , active ,
2016-10-05 21:59:38 +03:00
data_lv , metadata_lv , segtypes , role , layout , SnapPercent ,
2016-10-05 23:28:42 +03:00
MetaDataPercent , CopyPercent , SyncPercent , MetaDataSizeBytes ,
move_pv , move_pv_uuid ) :
2016-02-18 02:53:35 +03:00
utils . init_class_from_arguments ( self )
# The segtypes is possibly an array with potentially dupes or a single
# value
self . _segs = dbus . Array ( [ ] , signature = ' s ' )
if not isinstance ( segtypes , list ) :
2016-08-29 20:32:20 +03:00
self . _segs . append ( dbus . String ( segtypes ) )
2016-02-18 02:53:35 +03:00
else :
2016-08-29 20:32:20 +03:00
self . _segs . extend ( [ dbus . String ( x ) for x in set ( segtypes ) ] )
2016-02-18 02:53:35 +03:00
2016-06-10 20:03:04 +03:00
self . Vg = cfg . om . get_object_path_by_uuid_lvm_id (
2016-02-18 02:53:35 +03:00
vg_uuid , vg_name , vg_obj_path_generate )
self . Devices = LvState . _pv_devices ( self . Uuid )
if PoolLv :
gen = utils . lv_object_path_method ( Name , ( Attr , layout , role ) )
2016-06-10 20:03:04 +03:00
self . PoolLv = cfg . om . get_object_path_by_uuid_lvm_id (
2016-09-28 19:16:49 +03:00
pool_lv_uuid , ' %s / %s ' % ( vg_name , PoolLv ) , gen )
2016-02-18 02:53:35 +03:00
else :
self . PoolLv = ' / '
if OriginLv :
self . OriginLv = \
2016-06-10 20:03:04 +03:00
cfg . om . get_object_path_by_uuid_lvm_id (
2016-02-18 02:53:35 +03:00
origin_uuid , ' %s / %s ' % ( vg_name , OriginLv ) ,
vg_obj_path_generate )
else :
self . OriginLv = ' / '
self . HiddenLvs = self . _get_hidden_lv ( )
@property
def SegType ( self ) :
return self . _segs
def _object_path_create ( self ) :
return utils . lv_object_path_method (
self . Name , ( self . Attr , self . layout , self . role ) )
def _object_type_create ( self ) :
if self . Attr [ 0 ] == ' t ' :
return LvThinPool
2019-10-09 15:49:58 +03:00
elif self . Attr [ 0 ] == ' d ' :
return LvVdoPool
2016-02-18 02:53:35 +03:00
elif self . Attr [ 0 ] == ' C ' :
if ' pool ' in self . layout :
return LvCachePool
else :
return LvCacheLv
2016-06-10 20:11:17 +03:00
elif self . Name [ 0 ] == ' [ ' :
return LvCommon
2016-02-18 02:53:35 +03:00
elif self . OriginLv != ' / ' :
return LvSnapShot
else :
return Lv
def create_dbus_object ( self , path ) :
if not path :
2016-06-10 20:03:04 +03:00
path = cfg . om . get_object_path_by_uuid_lvm_id (
2016-02-18 02:53:35 +03:00
self . Uuid , self . lvm_id , self . _object_path_create ( ) )
obj_ctor = self . _object_type_create ( )
return obj_ctor ( path , self )
def creation_signature ( self ) :
klass = self . _object_type_create ( )
path_method = self . _object_path_create ( )
return ( klass , path_method )
2019-10-09 15:49:58 +03:00
class LvStateVdo ( LvState ) :
def __init__ ( self , Uuid , Name , Path , SizeBytes ,
vg_name , vg_uuid , pool_lv_uuid , PoolLv ,
origin_uuid , OriginLv , DataPercent , Attr , Tags , active ,
data_lv , metadata_lv , segtypes , role , layout , SnapPercent ,
MetaDataPercent , CopyPercent , SyncPercent ,
MetaDataSizeBytes , move_pv , move_pv_uuid ,
vdo_operating_mode , vdo_compression_state , vdo_index_state ,
2022-08-25 16:33:50 +03:00
vdo_used_size , vdo_saving_percent , vdo_compression ,
vdo_deduplication , vdo_use_metadata_hints ,
vdo_minimum_io_size , vdo_block_map_cache_size ,
vdo_block_map_era_length , vdo_use_sparse_index ,
vdo_index_memory_size , vdo_slab_size , vdo_ack_threads ,
vdo_bio_threads , vdo_bio_rotation , vdo_cpu_threads ,
vdo_hash_zone_threads , vdo_logical_threads ,
vdo_physical_threads , vdo_max_discard ,
vdo_write_policy , vdo_header_size ) :
2019-10-09 15:49:58 +03:00
super ( LvStateVdo , self ) . __init__ ( Uuid , Name , Path , SizeBytes ,
vg_name , vg_uuid , pool_lv_uuid , PoolLv ,
origin_uuid , OriginLv , DataPercent , Attr , Tags , active ,
data_lv , metadata_lv , segtypes , role , layout , SnapPercent ,
MetaDataPercent , CopyPercent , SyncPercent ,
MetaDataSizeBytes , move_pv , move_pv_uuid )
utils . init_class_from_arguments ( self , " vdo_ " , snake_to_pascal = True )
2016-02-18 02:53:35 +03:00
# noinspection PyPep8Naming
@utils.dbus_property ( LV_COMMON_INTERFACE , ' Uuid ' , ' s ' )
@utils.dbus_property ( LV_COMMON_INTERFACE , ' Name ' , ' s ' )
@utils.dbus_property ( LV_COMMON_INTERFACE , ' Path ' , ' s ' )
@utils.dbus_property ( LV_COMMON_INTERFACE , ' SizeBytes ' , ' t ' )
@utils.dbus_property ( LV_COMMON_INTERFACE , ' SegType ' , ' as ' )
@utils.dbus_property ( LV_COMMON_INTERFACE , ' Vg ' , ' o ' )
@utils.dbus_property ( LV_COMMON_INTERFACE , ' OriginLv ' , ' o ' )
@utils.dbus_property ( LV_COMMON_INTERFACE , ' PoolLv ' , ' o ' )
@utils.dbus_property ( LV_COMMON_INTERFACE , ' Devices ' , " a(oa(tts)) " )
@utils.dbus_property ( LV_COMMON_INTERFACE , ' HiddenLvs ' , " ao " )
2016-10-05 21:59:38 +03:00
@utils.dbus_property ( LV_COMMON_INTERFACE , ' Attr ' , ' s ' )
@utils.dbus_property ( LV_COMMON_INTERFACE , ' DataPercent ' , ' u ' )
@utils.dbus_property ( LV_COMMON_INTERFACE , ' SnapPercent ' , ' u ' )
@utils.dbus_property ( LV_COMMON_INTERFACE , ' MetaDataPercent ' , ' u ' )
@utils.dbus_property ( LV_COMMON_INTERFACE , ' CopyPercent ' , ' u ' )
@utils.dbus_property ( LV_COMMON_INTERFACE , ' SyncPercent ' , ' u ' )
@utils.dbus_property ( LV_COMMON_INTERFACE , ' MetaDataSizeBytes ' , ' t ' )
2016-02-18 02:53:35 +03:00
class LvCommon ( AutomatedProperties ) :
_Tags_meta = ( " as " , LV_COMMON_INTERFACE )
2016-06-04 01:07:37 +03:00
_Roles_meta = ( " as " , LV_COMMON_INTERFACE )
2016-02-18 02:53:35 +03:00
_IsThinVolume_meta = ( " b " , LV_COMMON_INTERFACE )
_IsThinPool_meta = ( " b " , LV_COMMON_INTERFACE )
_Active_meta = ( " b " , LV_COMMON_INTERFACE )
_VolumeType_meta = ( " (ss) " , LV_COMMON_INTERFACE )
_Permissions_meta = ( " (ss) " , LV_COMMON_INTERFACE )
_AllocationPolicy_meta = ( " (ss) " , LV_COMMON_INTERFACE )
_State_meta = ( " (ss) " , LV_COMMON_INTERFACE )
_TargetType_meta = ( " (ss) " , LV_COMMON_INTERFACE )
_Health_meta = ( " (ss) " , LV_COMMON_INTERFACE )
_FixedMinor_meta = ( ' b ' , LV_COMMON_INTERFACE )
_ZeroBlocks_meta = ( ' b ' , LV_COMMON_INTERFACE )
_SkipActivation_meta = ( ' b ' , LV_COMMON_INTERFACE )
2016-10-05 23:28:42 +03:00
_MovePv_meta = ( ' o ' , LV_COMMON_INTERFACE )
def _get_move_pv ( self ) :
path = None
# It's likely that the move_pv is empty
if self . state . move_pv_uuid and self . state . move_pv :
path = cfg . om . get_object_path_by_uuid_lvm_id (
self . state . move_pv_uuid , self . state . move_pv )
if not path :
path = ' / '
return path
2016-02-18 02:53:35 +03:00
# noinspection PyUnusedLocal,PyPep8Naming
def __init__ ( self , object_path , object_state ) :
super ( LvCommon , self ) . __init__ ( object_path , lvs_state_retrieve )
self . set_interface ( LV_COMMON_INTERFACE )
self . state = object_state
2016-10-05 23:28:42 +03:00
self . _move_pv = self . _get_move_pv ( )
2016-02-18 02:53:35 +03:00
2017-02-02 00:38:55 +03:00
@staticmethod
def handle_execute ( rc , out , err ) :
2019-10-01 23:17:30 +03:00
_handle_execute ( rc , out , err , LV_INTERFACE )
2017-02-02 00:38:55 +03:00
@staticmethod
def validate_dbus_object ( lv_uuid , lv_name ) :
dbo = cfg . om . get_object_by_uuid_lvm_id ( lv_uuid , lv_name )
if not dbo :
raise dbus . exceptions . DBusException (
LV_INTERFACE ,
' LV with uuid %s and name %s not present! ' %
( lv_uuid , lv_name ) )
return dbo
2018-12-11 20:21:50 +03:00
def attr_struct ( self , index , type_map , default = ' undisclosed ' ) :
try :
if self . state . Attr [ index ] not in type_map :
log_error ( " LV %s %s with lv_attr %s , lv_attr[ %d ] = "
" ' %s ' is not known " %
( self . Uuid , self . Name , self . Attr , index ,
self . state . Attr [ index ] ) )
return dbus . Struct ( ( self . state . Attr [ index ] ,
type_map . get ( self . state . Attr [ index ] , default ) ) ,
signature = " (ss) " )
2022-08-31 19:18:55 +03:00
except BaseException as b :
st = utils . extract_stack_trace ( b )
2018-12-11 20:21:50 +03:00
log_error ( " attr_struct: \n %s " % st )
return dbus . Struct ( ( ' ? ' , ' Unavailable ' ) , signature = " (ss) " )
2016-02-18 02:53:35 +03:00
@property
def VolumeType ( self ) :
type_map = { ' C ' : ' Cache ' , ' m ' : ' mirrored ' ,
' M ' : ' Mirrored without initial sync ' , ' o ' : ' origin ' ,
' O ' : ' Origin with merging snapshot ' , ' r ' : ' raid ' ,
' R ' : ' Raid without initial sync ' , ' s ' : ' snapshot ' ,
' S ' : ' merging Snapshot ' , ' p ' : ' pvmove ' ,
' v ' : ' virtual ' , ' i ' : ' mirror or raid image ' ,
' I ' : ' mirror or raid Image out-of-sync ' ,
' l ' : ' mirror log device ' , ' c ' : ' under conversion ' ,
' V ' : ' thin Volume ' , ' t ' : ' thin pool ' , ' T ' : ' Thin pool data ' ,
' e ' : ' raid or pool metadata or pool metadata spare ' ,
2020-07-15 18:07:28 +03:00
' d ' : ' vdo pool ' , ' D ' : ' vdo pool data ' , ' g ' : ' integrity ' ,
2016-02-18 02:53:35 +03:00
' - ' : ' Unspecified ' }
2018-12-11 20:21:50 +03:00
return self . attr_struct ( 0 , type_map )
2016-02-18 02:53:35 +03:00
@property
def Permissions ( self ) :
type_map = { ' w ' : ' writable ' , ' r ' : ' read-only ' ,
' R ' : ' Read-only activation of non-read-only volume ' ,
' - ' : ' Unspecified ' }
2018-12-11 20:21:50 +03:00
return self . attr_struct ( 1 , type_map )
2016-02-18 02:53:35 +03:00
@property
def AllocationPolicy ( self ) :
type_map = { ' a ' : ' anywhere ' , ' A ' : ' anywhere locked ' ,
' c ' : ' contiguous ' , ' C ' : ' contiguous locked ' ,
' i ' : ' inherited ' , ' I ' : ' inherited locked ' ,
' l ' : ' cling ' , ' L ' : ' cling locked ' ,
' n ' : ' normal ' , ' N ' : ' normal locked ' , ' - ' : ' Unspecified ' }
2018-12-11 20:21:50 +03:00
return self . attr_struct ( 2 , type_map )
2016-02-18 02:53:35 +03:00
@property
def FixedMinor ( self ) :
2016-08-25 02:31:15 +03:00
return dbus . Boolean ( self . state . Attr [ 3 ] == ' m ' )
2016-02-18 02:53:35 +03:00
@property
def State ( self ) :
2018-12-11 20:24:51 +03:00
type_map = { ' a ' : ' active ' ,
' s ' : ' suspended ' ,
' I ' : ' Invalid snapshot ' ,
2016-02-18 02:53:35 +03:00
' S ' : ' invalid Suspended snapshot ' ,
' m ' : ' snapshot merge failed ' ,
' M ' : ' suspended snapshot (M)erge failed ' ,
' d ' : ' mapped device present without tables ' ,
' i ' : ' mapped device present with inactive table ' ,
2018-12-11 20:24:51 +03:00
' h ' : ' historical ' ,
' c ' : ' check needed suspended thin-pool ' ,
' C ' : ' check needed ' ,
' X ' : ' unknown ' ,
' - ' : ' Unspecified ' }
2018-12-11 20:21:50 +03:00
return self . attr_struct ( 4 , type_map )
2016-02-18 02:53:35 +03:00
@property
def TargetType ( self ) :
type_map = { ' C ' : ' Cache ' , ' m ' : ' mirror ' , ' r ' : ' raid ' ,
' s ' : ' snapshot ' , ' t ' : ' thin ' , ' u ' : ' unknown ' ,
' v ' : ' virtual ' , ' - ' : ' Unspecified ' }
2016-08-25 02:31:15 +03:00
return dbus . Struct ( ( self . state . Attr [ 6 ] , type_map [ self . state . Attr [ 6 ] ] ) ,
2016-08-29 23:07:55 +03:00
signature = " (ss) " )
2016-02-18 02:53:35 +03:00
@property
def ZeroBlocks ( self ) :
2016-08-25 02:31:15 +03:00
return dbus . Boolean ( self . state . Attr [ 7 ] == ' z ' )
2016-02-18 02:53:35 +03:00
@property
def Health ( self ) :
2018-12-11 20:23:56 +03:00
type_map = { ' p ' : ' partial ' ,
' r ' : ' refresh needed ' ,
' m ' : ' mismatches ' ,
' w ' : ' writemostly ' ,
' X ' : ' unknown ' ,
' - ' : ' unspecified ' ,
' s ' : ' reshaping ' ,
' F ' : ' failed ' ,
' D ' : ' Data space ' ,
' R ' : ' Remove ' ,
' M ' : ' Metadata ' }
2018-12-11 20:21:50 +03:00
return self . attr_struct ( 8 , type_map )
2016-02-18 02:53:35 +03:00
@property
def SkipActivation ( self ) :
2016-08-25 02:31:15 +03:00
return dbus . Boolean ( self . state . Attr [ 9 ] == ' k ' )
2016-02-18 02:53:35 +03:00
def vg_name_lookup ( self ) :
return self . state . vg_name_lookup ( )
def lv_full_name ( self ) :
return " %s / %s " % ( self . state . vg_name_lookup ( ) , self . state . Name )
@property
def identifiers ( self ) :
return self . state . identifiers
@property
def Tags ( self ) :
return utils . parse_tags ( self . state . Tags )
2016-06-04 01:07:37 +03:00
@property
def Roles ( self ) :
return utils . parse_tags ( self . state . role )
2016-02-18 02:53:35 +03:00
@property
def lvm_id ( self ) :
return self . state . lvm_id
@property
def IsThinVolume ( self ) :
2016-08-25 02:31:15 +03:00
return dbus . Boolean ( self . state . Attr [ 0 ] == ' V ' )
2016-02-18 02:53:35 +03:00
@property
def IsThinPool ( self ) :
2016-08-25 02:31:15 +03:00
return dbus . Boolean ( self . state . Attr [ 0 ] == ' t ' )
2016-02-18 02:53:35 +03:00
@property
def Active ( self ) :
2016-08-25 02:31:15 +03:00
return dbus . Boolean ( self . state . active == " active " )
2016-02-18 02:53:35 +03:00
2016-10-05 23:28:42 +03:00
@property
def MovePv ( self ) :
return dbus . ObjectPath ( self . _move_pv )
2016-02-18 02:53:35 +03:00
# noinspection PyPep8Naming
class Lv ( LvCommon ) :
2016-06-06 23:03:02 +03:00
def _fetch_hidden ( self , name ) :
# The name is vg/name
full_name = " %s / %s " % ( self . vg_name_lookup ( ) , name )
2016-06-10 20:05:52 +03:00
return cfg . om . get_object_path_by_lvm_id ( full_name )
2016-06-06 23:03:02 +03:00
def _get_data_meta ( self ) :
# Get the data
return ( self . _fetch_hidden ( self . state . data_lv ) ,
self . _fetch_hidden ( self . state . metadata_lv ) )
2016-02-18 02:53:35 +03:00
# noinspection PyUnusedLocal,PyPep8Naming
def __init__ ( self , object_path , object_state ) :
super ( Lv , self ) . __init__ ( object_path , object_state )
self . set_interface ( LV_INTERFACE )
self . state = object_state
@staticmethod
def _remove ( lv_uuid , lv_name , remove_options ) :
# Make sure we have a dbus object representing it
2017-02-02 00:38:55 +03:00
LvCommon . validate_dbus_object ( lv_uuid , lv_name )
# Remove the LV, if successful then remove from the model
2019-10-01 23:18:46 +03:00
LvCommon . handle_execute ( * cmdhandler . lv_remove ( lv_name , remove_options ) )
2016-02-18 02:53:35 +03:00
return ' / '
@dbus.service.method (
dbus_interface = LV_INTERFACE ,
in_signature = ' ia {sv} ' ,
out_signature = ' o ' ,
async_callbacks = ( ' cb ' , ' cbe ' ) )
def Remove ( self , tmo , remove_options , cb , cbe ) :
r = RequestEntry (
tmo , Lv . _remove ,
( self . Uuid , self . lvm_id , remove_options ) ,
cb , cbe , False )
cfg . worker_q . put ( r )
@staticmethod
def _rename ( lv_uuid , lv_name , new_name , rename_options ) :
# Make sure we have a dbus object representing it
2017-02-02 00:38:55 +03:00
LvCommon . validate_dbus_object ( lv_uuid , lv_name )
# Rename the logical volume
2019-10-01 23:18:46 +03:00
LvCommon . handle_execute ( * cmdhandler . lv_rename ( lv_name , new_name ,
rename_options ) )
2016-02-18 02:53:35 +03:00
return ' / '
@dbus.service.method (
dbus_interface = LV_INTERFACE ,
in_signature = ' sia {sv} ' ,
out_signature = ' o ' ,
async_callbacks = ( ' cb ' , ' cbe ' ) )
def Rename ( self , name , tmo , rename_options , cb , cbe ) :
2016-02-18 03:27:57 +03:00
utils . validate_lv_name ( LV_INTERFACE , self . vg_name_lookup ( ) , name )
2016-02-18 02:53:35 +03:00
r = RequestEntry (
tmo , Lv . _rename ,
( self . Uuid , self . lvm_id , name , rename_options ) ,
cb , cbe , False )
cfg . worker_q . put ( r )
@dbus.service.method (
dbus_interface = LV_INTERFACE ,
in_signature = ' o(tt)a(ott)ia {sv} ' ,
2016-06-28 20:07:21 +03:00
out_signature = ' o ' ,
async_callbacks = ( ' cb ' , ' cbe ' ) )
2016-02-18 02:53:35 +03:00
def Move ( self , pv_src_obj , pv_source_range ,
pv_dests_and_ranges ,
2016-06-28 20:07:21 +03:00
tmo , move_options , cb , cbe ) :
job_state = JobState ( )
r = RequestEntry (
tmo , background . move ,
( LV_INTERFACE , self . lvm_id , pv_src_obj , pv_source_range ,
pv_dests_and_ranges , move_options , job_state ) , cb , cbe , False ,
job_state )
2016-11-11 18:46:12 +03:00
background . cmd_runner ( r )
2016-02-18 02:53:35 +03:00
@staticmethod
def _snap_shot ( lv_uuid , lv_name , name , optional_size ,
snapshot_options ) :
# Make sure we have a dbus object representing it
2017-02-02 00:38:55 +03:00
dbo = LvCommon . validate_dbus_object ( lv_uuid , lv_name )
# If you specify a size you get a 'thick' snapshot even if
# it is a thin lv
if not dbo . IsThinVolume :
if optional_size == 0 :
2018-05-18 17:23:10 +03:00
space = dbo . SizeBytes / / 80
2017-02-02 00:38:55 +03:00
remainder = space % 512
optional_size = space + 512 - remainder
2019-10-01 23:18:46 +03:00
LvCommon . handle_execute ( * cmdhandler . vg_lv_snapshot (
2022-08-25 16:33:50 +03:00
lv_name , snapshot_options , name , optional_size ) )
2017-02-02 00:38:55 +03:00
full_name = " %s / %s " % ( dbo . vg_name_lookup ( ) , name )
return cfg . om . get_object_path_by_lvm_id ( full_name )
2016-02-18 02:53:35 +03:00
@dbus.service.method (
dbus_interface = LV_INTERFACE ,
in_signature = ' stia {sv} ' ,
out_signature = ' (oo) ' ,
async_callbacks = ( ' cb ' , ' cbe ' ) )
def Snapshot ( self , name , optional_size , tmo ,
snapshot_options , cb , cbe ) :
2016-02-18 03:27:57 +03:00
utils . validate_lv_name ( LV_INTERFACE , self . vg_name_lookup ( ) , name )
2016-02-18 02:53:35 +03:00
r = RequestEntry (
tmo , Lv . _snap_shot ,
( self . Uuid , self . lvm_id , name ,
optional_size , snapshot_options ) , cb , cbe )
cfg . worker_q . put ( r )
@staticmethod
def _resize ( lv_uuid , lv_name , new_size_bytes , pv_dests_and_ranges ,
resize_options ) :
# Make sure we have a dbus object representing it
pv_dests = [ ]
2017-02-02 00:38:55 +03:00
dbo = LvCommon . validate_dbus_object ( lv_uuid , lv_name )
2016-02-18 02:53:35 +03:00
2017-02-02 00:38:55 +03:00
# If we have PVs, verify them
if len ( pv_dests_and_ranges ) :
for pr in pv_dests_and_ranges :
pv_dbus_obj = cfg . om . get_object_by_path ( pr [ 0 ] )
if not pv_dbus_obj :
raise dbus . exceptions . DBusException (
LV_INTERFACE ,
' PV Destination ( %s ) not found ' % pr [ 0 ] )
2016-02-18 02:53:35 +03:00
2017-02-02 00:38:55 +03:00
pv_dests . append ( ( pv_dbus_obj . lvm_id , pr [ 1 ] , pr [ 2 ] ) )
2016-02-18 02:53:35 +03:00
2017-02-02 00:38:55 +03:00
size_change = new_size_bytes - dbo . SizeBytes
2019-10-01 23:18:46 +03:00
LvCommon . handle_execute ( * cmdhandler . lv_resize (
2022-08-25 16:33:50 +03:00
dbo . lvm_id , size_change , pv_dests , resize_options ) )
2017-02-02 00:38:55 +03:00
return " / "
2016-02-18 02:53:35 +03:00
@dbus.service.method (
dbus_interface = LV_INTERFACE ,
in_signature = ' ta(ott)ia {sv} ' ,
out_signature = ' o ' ,
async_callbacks = ( ' cb ' , ' cbe ' ) )
def Resize ( self , new_size_bytes , pv_dests_and_ranges , tmo ,
resize_options , cb , cbe ) :
"""
Resize a LV
: param new_size_bytes : The requested final size in bytes
: param pv_dests_and_ranges : An array of pv object paths and src &
dst . segment ranges
: param tmo : - 1 to wait forever , 0 to return job immediately , else
number of seconds to wait for operation to complete
before getting a job
: param resize_options : key / value hash of options
: param cb : Used by framework not client facing API
: param cbe : Used by framework not client facing API
: return : ' / ' if complete , else job object path
"""
r = RequestEntry (
tmo , Lv . _resize ,
( self . Uuid , self . lvm_id , round_size ( new_size_bytes ) ,
pv_dests_and_ranges ,
resize_options ) , cb , cbe , return_tuple = False )
cfg . worker_q . put ( r )
@staticmethod
def _lv_activate_deactivate ( uuid , lv_name , activate , control_flags ,
options ) :
# Make sure we have a dbus object representing it
2017-02-02 00:38:55 +03:00
LvCommon . validate_dbus_object ( uuid , lv_name )
2019-10-01 23:18:46 +03:00
LvCommon . handle_execute ( * cmdhandler . activate_deactivate (
' lvchange ' , lv_name , activate , control_flags , options ) )
2017-02-02 00:38:55 +03:00
return ' / '
2016-02-18 02:53:35 +03:00
@dbus.service.method (
dbus_interface = LV_INTERFACE ,
in_signature = ' tia {sv} ' ,
out_signature = ' o ' ,
async_callbacks = ( ' cb ' , ' cbe ' ) )
def Activate ( self , control_flags , tmo , activate_options , cb , cbe ) :
r = RequestEntry (
tmo , Lv . _lv_activate_deactivate ,
( self . state . Uuid , self . state . lvm_id , True ,
control_flags , activate_options ) ,
cb , cbe , return_tuple = False )
cfg . worker_q . put ( r )
# noinspection PyProtectedMember
@dbus.service.method (
dbus_interface = LV_INTERFACE ,
in_signature = ' tia {sv} ' ,
out_signature = ' o ' ,
async_callbacks = ( ' cb ' , ' cbe ' ) )
def Deactivate ( self , control_flags , tmo , activate_options , cb , cbe ) :
r = RequestEntry (
tmo , Lv . _lv_activate_deactivate ,
( self . state . Uuid , self . state . lvm_id , False ,
control_flags , activate_options ) ,
cb , cbe , return_tuple = False )
cfg . worker_q . put ( r )
@staticmethod
def _add_rm_tags ( uuid , lv_name , tags_add , tags_del , tag_options ) :
# Make sure we have a dbus object representing it
2017-02-02 00:38:55 +03:00
LvCommon . validate_dbus_object ( uuid , lv_name )
2019-10-01 23:18:46 +03:00
LvCommon . handle_execute ( * cmdhandler . lv_tag (
lv_name , tags_add , tags_del , tag_options ) )
2017-02-02 00:38:55 +03:00
return ' / '
2016-02-18 02:53:35 +03:00
@dbus.service.method (
dbus_interface = LV_INTERFACE ,
in_signature = ' asia {sv} ' ,
out_signature = ' o ' ,
async_callbacks = ( ' cb ' , ' cbe ' ) )
def TagsAdd ( self , tags , tmo , tag_options , cb , cbe ) :
2016-02-18 03:27:57 +03:00
for t in tags :
utils . validate_tag ( LV_INTERFACE , t )
2016-02-18 02:53:35 +03:00
r = RequestEntry (
tmo , Lv . _add_rm_tags ,
( self . state . Uuid , self . state . lvm_id ,
tags , None , tag_options ) ,
cb , cbe , return_tuple = False )
cfg . worker_q . put ( r )
@dbus.service.method (
dbus_interface = LV_INTERFACE ,
in_signature = ' asia {sv} ' ,
out_signature = ' o ' ,
async_callbacks = ( ' cb ' , ' cbe ' ) )
def TagsDel ( self , tags , tmo , tag_options , cb , cbe ) :
2016-02-18 03:27:57 +03:00
for t in tags :
utils . validate_tag ( LV_INTERFACE , t )
2016-02-18 02:53:35 +03:00
r = RequestEntry (
tmo , Lv . _add_rm_tags ,
( self . state . Uuid , self . state . lvm_id ,
None , tags , tag_options ) ,
cb , cbe , return_tuple = False )
cfg . worker_q . put ( r )
2020-07-01 14:27:46 +03:00
@staticmethod
2022-08-31 23:42:48 +03:00
def _caching_common ( method , lv_uuid , lv_name , lv_object_path , cache_options ) :
2020-07-01 14:27:46 +03:00
# Make sure we have a dbus object representing it
dbo = LvCommon . validate_dbus_object ( lv_uuid , lv_name )
# Make sure we have dbus object representing lv to cache
lv_to_cache = cfg . om . get_object_by_path ( lv_object_path )
if lv_to_cache :
fcn = lv_to_cache . lv_full_name ( )
2022-08-31 23:42:48 +03:00
rc , out , err = method (
2020-07-01 14:27:46 +03:00
dbo . lv_full_name ( ) , fcn , cache_options )
if rc == 0 :
# When we cache an LV, the cache pool and the lv that is getting
# cached need to be removed from the object manager and
# re-created as their interfaces have changed!
mt_remove_dbus_objects ( ( dbo , lv_to_cache ) )
cfg . load ( )
lv_converted = cfg . om . get_object_path_by_lvm_id ( fcn )
else :
raise dbus . exceptions . DBusException (
LV_INTERFACE ,
' Exit code %s , stderr = %s ' % ( str ( rc ) , err ) )
else :
raise dbus . exceptions . DBusException (
LV_INTERFACE , ' LV to cache with object path %s not present! ' %
2022-08-31 23:42:48 +03:00
lv_object_path )
2020-07-01 14:27:46 +03:00
return lv_converted
2022-08-31 23:42:48 +03:00
@staticmethod
def _writecache_lv ( lv_uuid , lv_name , lv_object_path , cache_options ) :
return Lv . _caching_common ( cmdhandler . lv_writecache_lv , lv_uuid ,
lv_name , lv_object_path , cache_options )
2020-07-01 14:27:46 +03:00
@dbus.service.method (
dbus_interface = LV_INTERFACE ,
in_signature = ' oia {sv} ' ,
out_signature = ' (oo) ' ,
async_callbacks = ( ' cb ' , ' cbe ' ) )
def WriteCacheLv ( self , lv_object , tmo , cache_options , cb , cbe ) :
r = RequestEntry (
tmo , Lv . _writecache_lv ,
( self . Uuid , self . lvm_id , lv_object ,
cache_options ) , cb , cbe )
cfg . worker_q . put ( r )
2019-10-09 15:49:58 +03:00
# noinspection PyPep8Naming
@utils.dbus_property ( VDO_POOL_INTERFACE , ' OperatingMode ' , ' s ' )
@utils.dbus_property ( VDO_POOL_INTERFACE , ' CompressionState ' , ' s ' )
@utils.dbus_property ( VDO_POOL_INTERFACE , ' IndexState ' , ' s ' )
@utils.dbus_property ( VDO_POOL_INTERFACE , ' UsedSize ' , ' t ' )
@utils.dbus_property ( VDO_POOL_INTERFACE , ' SavingPercent ' , ' d ' )
@utils.dbus_property ( VDO_POOL_INTERFACE , ' Compression ' , ' s ' )
@utils.dbus_property ( VDO_POOL_INTERFACE , ' Deduplication ' , ' s ' )
@utils.dbus_property ( VDO_POOL_INTERFACE , ' UseMetadataHints ' , ' s ' )
@utils.dbus_property ( VDO_POOL_INTERFACE , ' MinimumIoSize ' , ' u ' )
@utils.dbus_property ( VDO_POOL_INTERFACE , ' BlockMapCacheSize ' , " t " )
@utils.dbus_property ( VDO_POOL_INTERFACE , ' BlockMapEraLength ' , ' u ' )
@utils.dbus_property ( VDO_POOL_INTERFACE , ' UseSparseIndex ' , ' s ' )
@utils.dbus_property ( VDO_POOL_INTERFACE , ' IndexMemorySize ' , ' t ' )
@utils.dbus_property ( VDO_POOL_INTERFACE , ' SlabSize ' , ' t ' )
@utils.dbus_property ( VDO_POOL_INTERFACE , ' AckThreads ' , ' u ' )
@utils.dbus_property ( VDO_POOL_INTERFACE , ' BioThreads ' , ' u ' )
@utils.dbus_property ( VDO_POOL_INTERFACE , ' BioRotation ' , ' u ' )
@utils.dbus_property ( VDO_POOL_INTERFACE , ' CpuThreads ' , ' u ' )
@utils.dbus_property ( VDO_POOL_INTERFACE , ' HashZoneThreads ' , ' u ' )
@utils.dbus_property ( VDO_POOL_INTERFACE , ' LogicalThreads ' , ' u ' )
@utils.dbus_property ( VDO_POOL_INTERFACE , ' PhysicalThreads ' , ' u ' )
@utils.dbus_property ( VDO_POOL_INTERFACE , ' MaxDiscard ' , ' u ' )
@utils.dbus_property ( VDO_POOL_INTERFACE , ' WritePolicy ' , ' s ' )
@utils.dbus_property ( VDO_POOL_INTERFACE , ' HeaderSize ' , ' u ' )
class LvVdoPool ( Lv ) :
_DataLv_meta = ( " o " , VDO_POOL_INTERFACE )
def __init__ ( self , object_path , object_state ) :
super ( LvVdoPool , self ) . __init__ ( object_path , object_state )
self . set_interface ( VDO_POOL_INTERFACE )
self . _data_lv , _ = self . _get_data_meta ( )
@property
def DataLv ( self ) :
return dbus . ObjectPath ( self . _data_lv )
2019-12-27 17:29:15 +03:00
@staticmethod
def _enable_disable_compression ( pool_uuid , pool_name , enable , comp_options ) :
# Make sure we have a dbus object representing it
LvCommon . validate_dbus_object ( pool_uuid , pool_name )
# Rename the logical volume
LvCommon . handle_execute ( * cmdhandler . lv_vdo_compression (
pool_name , enable , comp_options ) )
return ' / '
@dbus.service.method (
dbus_interface = VDO_POOL_INTERFACE ,
in_signature = ' ia {sv} ' ,
out_signature = ' o ' ,
async_callbacks = ( ' cb ' , ' cbe ' ) )
def EnableCompression ( self , tmo , comp_options , cb , cbe ) :
r = RequestEntry (
tmo , LvVdoPool . _enable_disable_compression ,
( self . Uuid , self . lvm_id , True , comp_options ) ,
cb , cbe , False )
cfg . worker_q . put ( r )
@dbus.service.method (
2022-08-25 16:33:50 +03:00
dbus_interface = VDO_POOL_INTERFACE ,
in_signature = ' ia {sv} ' ,
out_signature = ' o ' ,
async_callbacks = ( ' cb ' , ' cbe ' ) )
2019-12-27 17:29:15 +03:00
def DisableCompression ( self , tmo , comp_options , cb , cbe ) :
r = RequestEntry (
tmo , LvVdoPool . _enable_disable_compression ,
( self . Uuid , self . lvm_id , False , comp_options ) ,
cb , cbe , False )
cfg . worker_q . put ( r )
@staticmethod
def _enable_disable_deduplication ( pool_uuid , pool_name , enable , dedup_options ) :
# Make sure we have a dbus object representing it
LvCommon . validate_dbus_object ( pool_uuid , pool_name )
# Rename the logical volume
LvCommon . handle_execute ( * cmdhandler . lv_vdo_deduplication (
pool_name , enable , dedup_options ) )
return ' / '
@dbus.service.method (
dbus_interface = VDO_POOL_INTERFACE ,
in_signature = ' ia {sv} ' ,
out_signature = ' o ' ,
async_callbacks = ( ' cb ' , ' cbe ' ) )
def EnableDeduplication ( self , tmo , dedup_options , cb , cbe ) :
r = RequestEntry (
tmo , LvVdoPool . _enable_disable_deduplication ,
( self . Uuid , self . lvm_id , True , dedup_options ) ,
cb , cbe , False )
cfg . worker_q . put ( r )
@dbus.service.method (
2022-08-25 16:33:50 +03:00
dbus_interface = VDO_POOL_INTERFACE ,
in_signature = ' ia {sv} ' ,
out_signature = ' o ' ,
async_callbacks = ( ' cb ' , ' cbe ' ) )
2019-12-27 17:29:15 +03:00
def DisableDeduplication ( self , tmo , dedup_options , cb , cbe ) :
r = RequestEntry (
tmo , LvVdoPool . _enable_disable_deduplication ,
( self . Uuid , self . lvm_id , False , dedup_options ) ,
cb , cbe , False )
cfg . worker_q . put ( r )
2016-02-18 02:53:35 +03:00
# noinspection PyPep8Naming
class LvThinPool ( Lv ) :
_DataLv_meta = ( " o " , THIN_POOL_INTERFACE )
_MetaDataLv_meta = ( " o " , THIN_POOL_INTERFACE )
def __init__ ( self , object_path , object_state ) :
super ( LvThinPool , self ) . __init__ ( object_path , object_state )
self . set_interface ( THIN_POOL_INTERFACE )
self . _data_lv , self . _metadata_lv = self . _get_data_meta ( )
@property
def DataLv ( self ) :
2016-08-25 02:31:15 +03:00
return dbus . ObjectPath ( self . _data_lv )
2016-02-18 02:53:35 +03:00
@property
def MetaDataLv ( self ) :
2016-08-25 02:31:15 +03:00
return dbus . ObjectPath ( self . _metadata_lv )
2016-02-18 02:53:35 +03:00
@staticmethod
def _lv_create ( lv_uuid , lv_name , name , size_bytes , create_options ) :
# Make sure we have a dbus object representing it
2017-02-02 00:38:55 +03:00
dbo = LvCommon . validate_dbus_object ( lv_uuid , lv_name )
2019-10-01 23:18:46 +03:00
LvCommon . handle_execute ( * cmdhandler . lv_lv_create (
lv_name , create_options , name , size_bytes ) )
2017-02-02 00:38:55 +03:00
full_name = " %s / %s " % ( dbo . vg_name_lookup ( ) , name )
return cfg . om . get_object_path_by_lvm_id ( full_name )
2016-02-18 02:53:35 +03:00
@dbus.service.method (
dbus_interface = THIN_POOL_INTERFACE ,
in_signature = ' stia {sv} ' ,
out_signature = ' (oo) ' ,
async_callbacks = ( ' cb ' , ' cbe ' ) )
def LvCreate ( self , name , size_bytes , tmo , create_options , cb , cbe ) :
2016-02-18 03:27:57 +03:00
utils . validate_lv_name ( THIN_POOL_INTERFACE , self . vg_name_lookup ( ) , name )
2016-02-18 02:53:35 +03:00
r = RequestEntry (
tmo , LvThinPool . _lv_create ,
( self . Uuid , self . lvm_id , name ,
round_size ( size_bytes ) , create_options ) , cb , cbe )
cfg . worker_q . put ( r )
# noinspection PyPep8Naming
class LvCachePool ( Lv ) :
2016-06-06 23:03:02 +03:00
_DataLv_meta = ( " o " , CACHE_POOL_INTERFACE )
_MetaDataLv_meta = ( " o " , CACHE_POOL_INTERFACE )
2016-02-18 02:53:35 +03:00
def __init__ ( self , object_path , object_state ) :
super ( LvCachePool , self ) . __init__ ( object_path , object_state )
self . set_interface ( CACHE_POOL_INTERFACE )
2016-06-06 23:03:02 +03:00
self . _data_lv , self . _metadata_lv = self . _get_data_meta ( )
@property
def DataLv ( self ) :
2016-08-25 02:31:15 +03:00
return dbus . ObjectPath ( self . _data_lv )
2016-06-06 23:03:02 +03:00
@property
def MetaDataLv ( self ) :
2016-08-25 02:31:15 +03:00
return dbus . ObjectPath ( self . _metadata_lv )
2016-02-18 02:53:35 +03:00
@staticmethod
def _cache_lv ( lv_uuid , lv_name , lv_object_path , cache_options ) :
2022-08-31 23:42:48 +03:00
return Lv . _caching_common ( cmdhandler . lv_cache_lv , lv_uuid , lv_name ,
lv_object_path , cache_options )
2016-02-18 02:53:35 +03:00
@dbus.service.method (
dbus_interface = CACHE_POOL_INTERFACE ,
in_signature = ' oia {sv} ' ,
out_signature = ' (oo) ' ,
async_callbacks = ( ' cb ' , ' cbe ' ) )
def CacheLv ( self , lv_object , tmo , cache_options , cb , cbe ) :
r = RequestEntry (
tmo , LvCachePool . _cache_lv ,
( self . Uuid , self . lvm_id , lv_object ,
cache_options ) , cb , cbe )
cfg . worker_q . put ( r )
# noinspection PyPep8Naming
class LvCacheLv ( Lv ) :
_CachePool_meta = ( " o " , LV_CACHED )
def __init__ ( self , object_path , object_state ) :
super ( LvCacheLv , self ) . __init__ ( object_path , object_state )
self . set_interface ( LV_CACHED )
@property
def CachePool ( self ) :
2016-08-25 02:31:15 +03:00
return dbus . ObjectPath ( self . state . PoolLv )
2016-02-18 02:53:35 +03:00
@staticmethod
def _detach_lv ( lv_uuid , lv_name , detach_options , destroy_cache ) :
# Make sure we have a dbus object representing cache pool
2017-02-02 00:38:55 +03:00
dbo = LvCommon . validate_dbus_object ( lv_uuid , lv_name )
2016-02-18 02:53:35 +03:00
2017-02-02 00:38:55 +03:00
# Get current cache name
cache_pool = cfg . om . get_object_by_path ( dbo . CachePool )
2016-02-18 02:53:35 +03:00
2017-02-02 00:38:55 +03:00
rc , out , err = cmdhandler . lv_detach_cache (
dbo . lv_full_name ( ) , detach_options , destroy_cache )
if rc == 0 :
# The cache pool gets removed as hidden and put back to
# visible, so lets delete
mt_remove_dbus_objects ( ( cache_pool , dbo ) )
cfg . load ( )
2016-02-18 02:53:35 +03:00
2017-02-02 00:38:55 +03:00
uncached_lv_path = cfg . om . get_object_path_by_lvm_id ( lv_name )
2016-02-18 02:53:35 +03:00
else :
raise dbus . exceptions . DBusException (
LV_INTERFACE ,
2017-02-02 00:38:55 +03:00
' Exit code %s , stderr = %s ' % ( str ( rc ) , err ) )
2016-02-18 02:53:35 +03:00
return uncached_lv_path
@dbus.service.method (
dbus_interface = LV_CACHED ,
in_signature = ' bia {sv} ' ,
out_signature = ' (oo) ' ,
async_callbacks = ( ' cb ' , ' cbe ' ) )
def DetachCachePool ( self , destroy_cache , tmo , detach_options , cb , cbe ) :
r = RequestEntry (
tmo , LvCacheLv . _detach_lv ,
( self . Uuid , self . lvm_id , detach_options ,
destroy_cache ) , cb , cbe )
cfg . worker_q . put ( r )
# noinspection PyPep8Naming
class LvSnapShot ( Lv ) :
def __init__ ( self , object_path , object_state ) :
super ( LvSnapShot , self ) . __init__ ( object_path , object_state )
self . set_interface ( SNAPSHOT_INTERFACE )
@dbus.service.method (
dbus_interface = SNAPSHOT_INTERFACE ,
in_signature = ' ia {sv} ' ,
2016-06-28 20:07:21 +03:00
out_signature = ' o ' ,
async_callbacks = ( ' cb ' , ' cbe ' ) )
def Merge ( self , tmo , merge_options , cb , cbe ) :
job_state = JobState ( )
r = RequestEntry ( tmo , background . merge ,
( SNAPSHOT_INTERFACE , self . Uuid , self . lvm_id ,
merge_options , job_state ) , cb , cbe , False ,
job_state )
2016-11-11 18:46:12 +03:00
background . cmd_runner ( r )