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
from . cfg import MANAGER_INTERFACE
import dbus
from . import cfg
from . import cmdhandler
from . request import RequestEntry
2016-08-25 02:29:35 +03:00
from . import udevwatch
2016-02-18 02:53:35 +03:00
2016-08-29 23:07:55 +03:00
2016-02-18 02:53:35 +03:00
# noinspection PyPep8Naming
class Manager ( AutomatedProperties ) :
2016-08-25 02:31:15 +03:00
_Version_meta = ( " s " , MANAGER_INTERFACE )
2016-02-18 02:53:35 +03:00
def __init__ ( self , object_path ) :
super ( Manager , self ) . __init__ ( object_path )
self . set_interface ( MANAGER_INTERFACE )
@property
def Version ( self ) :
2020-07-01 14:27:47 +03:00
return dbus . String ( ' 1.1.0 ' )
2016-02-18 02:53:35 +03:00
2017-02-02 03:57:01 +03:00
@staticmethod
def handle_execute ( rc , out , err ) :
if rc == 0 :
cfg . load ( )
else :
# Need to work on error handling, need consistent
raise dbus . exceptions . DBusException (
MANAGER_INTERFACE ,
' Exit code %s , stderr = %s ' % ( str ( rc ) , err ) )
2016-02-18 02:53:35 +03:00
@staticmethod
def _pv_create ( device , create_options ) :
# Check to see if we are already trying to create a PV for an existing
# PV
2016-09-28 19:16:49 +03:00
pv = cfg . om . get_object_path_by_uuid_lvm_id ( device , device )
2016-02-18 02:53:35 +03:00
if pv :
raise dbus . exceptions . DBusException (
2017-04-22 08:07:52 +03:00
MANAGER_INTERFACE , " PV %s Already exists! " % device )
2016-02-18 02:53:35 +03:00
rc , out , err = cmdhandler . pv_create ( create_options , [ device ] )
2017-02-02 03:57:01 +03:00
Manager . handle_execute ( rc , out , err )
return cfg . om . get_object_path_by_lvm_id ( device )
2016-02-18 02:53:35 +03:00
@dbus.service.method (
dbus_interface = MANAGER_INTERFACE ,
in_signature = ' sia {sv} ' ,
out_signature = ' (oo) ' ,
async_callbacks = ( ' cb ' , ' cbe ' ) )
def PvCreate ( self , device , tmo , create_options , cb , cbe ) :
2016-02-18 03:27:57 +03:00
utils . validate_device_path ( MANAGER_INTERFACE , device )
2016-02-18 02:53:35 +03:00
r = RequestEntry (
tmo , Manager . _pv_create ,
( device , create_options ) , cb , cbe )
cfg . worker_q . put ( r )
@staticmethod
def _create_vg ( name , pv_object_paths , create_options ) :
pv_devices = [ ]
for p in pv_object_paths :
pv = cfg . om . get_object_by_path ( p )
if pv :
pv_devices . append ( pv . Name )
else :
raise dbus . exceptions . DBusException (
MANAGER_INTERFACE , ' object path = %s not found ' % p )
rc , out , err = cmdhandler . vg_create ( create_options , pv_devices , name )
2017-02-02 03:57:01 +03:00
Manager . handle_execute ( rc , out , err )
return cfg . om . get_object_path_by_lvm_id ( name )
2016-02-18 02:53:35 +03:00
@dbus.service.method (
dbus_interface = MANAGER_INTERFACE ,
in_signature = ' saoia {sv} ' ,
out_signature = ' (oo) ' ,
async_callbacks = ( ' cb ' , ' cbe ' ) )
def VgCreate ( self , name , pv_object_paths , tmo , create_options , cb , cbe ) :
2016-02-18 03:27:57 +03:00
utils . validate_vg_name ( MANAGER_INTERFACE , name )
2016-02-18 02:53:35 +03:00
r = RequestEntry (
tmo , Manager . _create_vg ,
( name , pv_object_paths , create_options , ) ,
cb , cbe )
cfg . worker_q . put ( r )
@staticmethod
def _refresh ( ) :
utils . log_debug ( ' Manager.Refresh - entry ' )
# This is a diagnostic and should not be run in normal operation, so
# lets remove the log entries for refresh as it's implied.
2016-09-27 18:08:23 +03:00
# Run an internal diagnostic on the object manager look up tables
lc = cfg . om . validate_lookups ( )
2016-02-18 02:53:35 +03:00
rc = cfg . load ( log = False )
if rc != 0 :
2019-10-11 18:46:22 +03:00
utils . log_debug ( ' Manager.Refresh - exit %d %d ' % ( rc , lc ) ,
2016-02-18 02:53:35 +03:00
' bg_black ' , ' fg_light_red ' )
else :
2019-10-11 18:46:22 +03:00
utils . log_debug ( ' Manager.Refresh - exit %d %d ' % ( rc , lc ) )
2016-09-27 18:08:23 +03:00
return rc + lc
2016-02-18 02:53:35 +03:00
@dbus.service.method (
dbus_interface = MANAGER_INTERFACE ,
out_signature = ' t ' ,
async_callbacks = ( ' cb ' , ' cbe ' ) )
def Refresh ( self , cb , cbe ) :
"""
Take all the objects we know about and go out and grab the latest
more of a test method at the moment to make sure we are handling object
paths correctly .
: param cb Callback for result
: param cbe Callback for errors
Returns the number of changes , object add / remove / properties changed
"""
r = RequestEntry ( - 1 , Manager . _refresh , ( ) , cb , cbe , False )
cfg . worker_q . put ( r )
2017-03-08 22:32:20 +03:00
@dbus.service.method (
dbus_interface = MANAGER_INTERFACE )
def FlightRecorderDump ( self ) :
"""
Dump the flight recorder to syslog
"""
2022-08-10 01:55:27 +03:00
cfg . flightrecorder . dump ( )
2017-03-09 00:31:45 +03:00
@staticmethod
def _lookup_by_lvm_id ( key ) :
p = cfg . om . get_object_path_by_uuid_lvm_id ( key , key )
2017-03-10 01:03:20 +03:00
if not p :
p = ' / '
2017-04-27 19:12:20 +03:00
utils . log_debug ( ' LookUpByLvmId: key = %s , result = %s ' % ( key , p ) )
2017-03-10 01:03:20 +03:00
return p
2017-03-09 00:31:45 +03:00
2016-02-18 02:53:35 +03:00
@dbus.service.method (
dbus_interface = MANAGER_INTERFACE ,
in_signature = ' s ' ,
2017-03-09 00:31:45 +03:00
out_signature = ' o ' ,
async_callbacks = ( ' cb ' , ' cbe ' ) )
def LookUpByLvmId ( self , key , cb , cbe ) :
2016-02-18 02:53:35 +03:00
"""
Given a lvm id in one of the forms :
/ dev / sda
some_vg
some_vg / some_lv
Oe1rPX - Pf0W - 15E5 - n41N - ZmtF - jXS0 - Osg8fn
return the object path in O ( 1 ) time .
: param key : The lookup value
2019-01-14 18:10:24 +03:00
: param cb : dbus python call back parameter , not client visible
: param cbe : dbus python error call back parameter , not client visible
2016-02-18 02:53:35 +03:00
: return : Return the object path . If object not found you will get ' / '
"""
2017-03-09 00:31:45 +03:00
r = RequestEntry ( - 1 , Manager . _lookup_by_lvm_id , ( key , ) , cb , cbe , False )
cfg . worker_q . put ( r )
2016-02-18 02:53:35 +03:00
2016-11-17 02:29:23 +03:00
@staticmethod
def _use_lvm_shell ( yes_no ) :
return dbus . Boolean ( cmdhandler . set_execution ( yes_no ) )
2016-02-18 02:53:35 +03:00
@dbus.service.method (
dbus_interface = MANAGER_INTERFACE ,
2016-11-17 02:29:23 +03:00
in_signature = ' b ' , out_signature = ' b ' ,
async_callbacks = ( ' cb ' , ' cbe ' ) )
def UseLvmShell ( self , yes_no , cb , cbe ) :
2016-02-18 02:53:35 +03:00
"""
Allow the client to enable / disable lvm shell , used for testing
: param yes_no :
2016-11-17 22:58:17 +03:00
: param cb : dbus python call back parameter , not client visible
: param cbe : dbus python error call back parameter , not client visible
2017-03-09 00:37:08 +03:00
: return : Boolean
2016-02-18 02:53:35 +03:00
"""
2016-11-17 02:29:23 +03:00
r = RequestEntry ( - 1 , Manager . _use_lvm_shell , ( yes_no , ) , cb , cbe , False )
cfg . worker_q . put ( r )
2016-02-18 02:53:35 +03:00
2017-03-09 00:31:45 +03:00
@staticmethod
def _external_event ( command ) :
utils . log_debug ( " Processing _external_event= %s " % command ,
' bg_black ' , ' fg_orange ' )
2022-08-17 20:08:16 +03:00
cfg . got_external_event = True
2017-03-09 00:31:45 +03:00
cfg . load ( )
2016-02-18 02:53:35 +03:00
@dbus.service.method (
dbus_interface = MANAGER_INTERFACE ,
in_signature = ' s ' , out_signature = ' i ' )
def ExternalEvent ( self , command ) :
2017-03-09 00:31:45 +03:00
utils . log_debug ( " ExternalEvent %s " % command )
2016-08-25 02:29:35 +03:00
# If a user didn't explicitly specify udev, we will turn it off now.
if not cfg . args . use_udev :
if udevwatch . remove ( ) :
2022-08-17 20:08:16 +03:00
utils . log_msg ( " ExternalEvent received, disabling "
2016-08-25 02:29:35 +03:00
" udev monitoring " )
# We are dependent on external events now to stay current!
2017-03-09 00:31:45 +03:00
r = RequestEntry (
- 1 , Manager . _external_event , ( command , ) , None , None , False )
cfg . worker_q . put ( r )
2016-02-18 02:53:35 +03:00
return dbus . Int32 ( 0 )
@staticmethod
def _pv_scan ( activate , cache , device_path , major_minor , scan_options ) :
rc , out , err = cmdhandler . pv_scan (
activate , cache , device_path ,
major_minor , scan_options )
2017-02-02 03:57:01 +03:00
Manager . handle_execute ( rc , out , err )
return ' / '
2016-02-18 02:53:35 +03:00
@dbus.service.method (
dbus_interface = MANAGER_INTERFACE ,
in_signature = ' bbasa(ii)ia {sv} ' ,
out_signature = ' o ' ,
async_callbacks = ( ' cb ' , ' cbe ' ) )
def PvScan ( self , activate , cache , device_paths , major_minors ,
tmo , scan_options , cb , cbe ) :
"""
Scan all supported LVM block devices in the system for physical volumes
NOTE : major_minors & device_paths only usable when cache == True
: param activate : If True , activate any newly found LVs
: param cache : If True , update lvmetad
: param device_paths : Array of device paths or empty
: param major_minors : Array of structures ( major , minor )
: param tmo : Timeout for operation
: param scan_options : Additional options to pvscan
: param cb : Not visible in API ( used for async . callback )
: param cbe : Not visible in API ( used for async . error callback )
: return : ' / ' if operation done , else job path
"""
2016-02-18 03:27:57 +03:00
for d in device_paths :
utils . validate_device_path ( MANAGER_INTERFACE , d )
2016-02-18 02:53:35 +03:00
r = RequestEntry (
tmo , Manager . _pv_scan ,
( activate , cache , device_paths , major_minors ,
scan_options ) , cb , cbe , False )
cfg . worker_q . put ( r )
@property
def lvm_id ( self ) :
"""
Intended to be overridden by classes that inherit
"""
return str ( id ( self ) )
@property
def Uuid ( self ) :
"""
Intended to be overridden by classes that inherit
"""
import uuid
return uuid . uuid1 ( )