1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

lvmdbusd: VDO Pool LV representation

VDO pool LVs are represented by a new dbus interface VgVdo.  Currently
the interface only has additional VDO properties, but when the
ability to support additional LV creation is added we can add a method
to the interface.
This commit is contained in:
Tony Asleson 2019-10-09 07:49:58 -05:00
parent 455498f206
commit 5971da2c72
8 changed files with 197 additions and 29 deletions

View File

@ -51,6 +51,7 @@ VG_VDO_INTERFACE = BASE_INTERFACE + '.VgVdo'
LV_INTERFACE = BASE_INTERFACE + '.Lv'
LV_COMMON_INTERFACE = BASE_INTERFACE + '.LvCommon'
THIN_POOL_INTERFACE = BASE_INTERFACE + '.ThinPool'
VDO_POOL_INTERFACE = BASE_INTERFACE + '.VdoPool'
CACHE_POOL_INTERFACE = BASE_INTERFACE + '.CachePool'
LV_CACHED = BASE_INTERFACE + '.CachedLv'
SNAPSHOT_INTERFACE = BASE_INTERFACE + '.Snapshot'
@ -62,6 +63,7 @@ PV_OBJ_PATH = BASE_OBJ_PATH + '/Pv'
VG_OBJ_PATH = BASE_OBJ_PATH + '/Vg'
LV_OBJ_PATH = BASE_OBJ_PATH + '/Lv'
THIN_POOL_PATH = BASE_OBJ_PATH + "/ThinPool"
VDO_POOL_PATH = BASE_OBJ_PATH + "/VdoPool"
CACHE_POOL_PATH = BASE_OBJ_PATH + "/CachePool"
HIDDEN_LV_PATH = BASE_OBJ_PATH + "/HiddenLv"
MANAGER_OBJ_PATH = BASE_OBJ_PATH + '/Manager'
@ -72,6 +74,7 @@ pv_id = itertools.count()
vg_id = itertools.count()
lv_id = itertools.count()
thin_id = itertools.count()
vdo_id = itertools.count()
cache_pool_id = itertools.count()
job_id = itertools.count()
hidden_lv = itertools.count()

View File

@ -509,6 +509,22 @@ def lvm_full_report_json():
lv_seg_columns = ['seg_pe_ranges', 'segtype', 'lv_uuid']
if cfg.vdo_support:
lv_columns.extend(
['vdo_operating_mode', 'vdo_compression_state', 'vdo_index_state',
'vdo_used_size', 'vdo_saving_percent']
)
lv_seg_columns.extend(
['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'])
cmd = _dc('fullreport', [
'-a', # Need hidden too
'--configreport', 'pv', '-o', ','.join(pv_columns),

View File

@ -15,9 +15,9 @@ import dbus
from . import cmdhandler
from . import cfg
from .cfg import LV_INTERFACE, THIN_POOL_INTERFACE, SNAPSHOT_INTERFACE, \
LV_COMMON_INTERFACE, CACHE_POOL_INTERFACE, LV_CACHED
LV_COMMON_INTERFACE, CACHE_POOL_INTERFACE, LV_CACHED, VDO_POOL_INTERFACE
from .request import RequestEntry
from .utils import n, n32
from .utils import n, n32, d
from .loader import common
from .state import State
from . import background
@ -74,6 +74,49 @@ def lvs_state_retrieve(selection, cache_refresh=True):
lvs = sorted(cfg.db.fetch_lvs(selection), key=get_key)
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']),
@ -194,6 +237,8 @@ class LvState(State):
def _object_type_create(self):
if self.Attr[0] == 't':
return LvThinPool
elif self.Attr[0] == 'd':
return LvVdoPool
elif self.Attr[0] == 'C':
if 'pool' in self.layout:
return LvCachePool
@ -220,6 +265,34 @@ class LvState(State):
return (klass, path_method)
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,
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):
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)
# noinspection PyPep8Naming
@utils.dbus_property(LV_COMMON_INTERFACE, 'Uuid', 's')
@utils.dbus_property(LV_COMMON_INTERFACE, 'Name', 's')
@ -670,6 +743,43 @@ class Lv(LvCommon):
cb, cbe, return_tuple=False)
cfg.worker_q.put(r)
# 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)
# noinspection PyPep8Naming
class LvThinPool(Lv):

View File

@ -20,7 +20,7 @@ from lvmdbusd.utils import log_debug, log_error
class DataStore(object):
def __init__(self, usejson=True):
def __init__(self, usejson=True, vdo_support=False):
self.pvs = {}
self.vgs = {}
self.lvs = {}
@ -43,6 +43,8 @@ class DataStore(object):
else:
self.json = usejson
self.vdo_support = vdo_support
@staticmethod
def _insert_record(table, key, record, allowed_multiple):
if key in table:
@ -241,8 +243,7 @@ class DataStore(object):
return DataStore._parse_lvs_common(c_lvs, c_lv_full_lookup)
@staticmethod
def _parse_lvs_json(_all):
def _parse_lvs_json(self, _all):
c_lvs = OrderedDict()
c_lv_full_lookup = {}
@ -262,8 +263,13 @@ class DataStore(object):
if 'seg' in r:
for s in r['seg']:
r = c_lvs[s['lv_uuid']]
r.setdefault('seg_pe_ranges', []).append(s['seg_pe_ranges'])
r.setdefault('seg_pe_ranges', []).\
append(s['seg_pe_ranges'])
r.setdefault('segtype', []).append(s['segtype'])
if self.vdo_support:
for seg_key, seg_val in s.items():
if seg_key.startswith("vdo_"):
r[seg_key] = seg_val
return DataStore._parse_lvs_common(c_lvs, c_lv_full_lookup)

View File

@ -155,7 +155,7 @@ def main():
cfg.om = Lvm(BASE_OBJ_PATH)
cfg.om.register_object(Manager(MANAGER_OBJ_PATH))
cfg.db = lvmdb.DataStore(cfg.args.use_json)
cfg.db = lvmdb.DataStore(cfg.args.use_json, cfg.vdo_support)
# Using a thread to process requests, we cannot hang the dbus library
# thread that is handling the dbus interface

View File

@ -66,8 +66,20 @@ def n32(v):
return int(float(v))
@rtype(dbus.Double)
def d(v):
if not v:
return 0.0
return float(v)
def _snake_to_pascal(s):
return ''.join(x.title() for x in s.split('_'))
# noinspection PyProtectedMember
def init_class_from_arguments(obj_instance):
def init_class_from_arguments(
obj_instance, begin_suffix=None, snake_to_pascal=False):
for k, v in list(sys._getframe(1).f_locals.items()):
if k != 'self':
nt = k
@ -78,7 +90,16 @@ def init_class_from_arguments(obj_instance):
cur = getattr(obj_instance, nt, v)
# print 'Init class %s = %s' % (nt, str(v))
if not (cur and len(str(cur)) and (v is None or len(str(v))) == 0):
if not (cur and len(str(cur)) and (v is None or len(str(v))) == 0)\
and (begin_suffix is None or nt.startswith(begin_suffix)):
if begin_suffix and nt.startswith(begin_suffix):
name = nt[len(begin_suffix):]
if snake_to_pascal:
name = _snake_to_pascal(name)
setattr(obj_instance, name, v)
else:
setattr(obj_instance, nt, v)
@ -347,6 +368,8 @@ def lv_object_path_method(name, meta):
return _hidden_lv_obj_path_generate
elif meta[0][0] == 't':
return _thin_pool_obj_path_generate
elif meta[0][0] == 'd':
return _vdo_pool_object_path_generate
elif meta[0][0] == 'C' and 'pool' in meta[1]:
return _cache_pool_obj_path_generate
@ -364,6 +387,10 @@ def _thin_pool_obj_path_generate():
return cfg.THIN_POOL_PATH + "/%d" % next(cfg.thin_id)
def _vdo_pool_object_path_generate():
return cfg.VDO_POOL_PATH + "/%d" % next(cfg.vdo_id)
def _cache_pool_obj_path_generate():
return cfg.CACHE_POOL_PATH + "/%d" % next(cfg.cache_pool_id)

View File

@ -71,7 +71,8 @@ def lv_n(suffix=None):
def _is_testsuite_pv(pv_name):
return g_prefix != "" and pv_name[-1].isdigit() and pv_name[:-1].endswith(g_prefix + "pv")
return g_prefix != "" and pv_name[-1].isdigit() and \
pv_name[:-1].endswith(g_prefix + "pv")
def is_nested_pv(pv_name):
@ -114,7 +115,7 @@ def get_objects():
rc = {
MANAGER_INT: [], PV_INT: [], VG_INT: [], LV_INT: [],
THINPOOL_INT: [], JOB_INT: [], SNAPSHOT_INT: [], LV_COMMON_INT: [],
CACHE_POOL_INT: [], CACHE_LV_INT: [], VG_VDO_INT: []}
CACHE_POOL_INT: [], CACHE_LV_INT: [], VG_VDO_INT: [], VDOPOOL_INT: []}
object_manager_object = bus.get_object(
BUS_NAME, "/com/redhat/lvmdbus1", introspect=False)

View File

@ -27,6 +27,7 @@ VG_INT = BASE_INTERFACE + ".Vg"
VG_VDO_INT = BASE_INTERFACE + ".VgVdo"
LV_INT = BASE_INTERFACE + ".Lv"
THINPOOL_INT = BASE_INTERFACE + ".ThinPool"
VDOPOOL_INT = BASE_INTERFACE + ".VdoPool"
SNAPSHOT_INT = BASE_INTERFACE + ".Snapshot"
LV_COMMON_INT = BASE_INTERFACE + ".LvCommon"
JOB_INT = BASE_INTERFACE + ".Job"
@ -240,6 +241,10 @@ class RemoteInterface(object):
class ClientProxy(object):
Pv = None
Lv = None
Vg = None
@staticmethod
def _intf_short_name(nm):
return nm.split('.')[-1:][0]