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 . fetch import load_pvs , load_vgs
from . request import RequestEntry
from . refresh import event_add
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 ) :
2016-08-25 02:31:15 +03:00
return dbus . String ( ' 1.0.0 ' )
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 (
MANAGER_INTERFACE , " PV Already exists! " )
rc , out , err = cmdhandler . pv_create ( create_options , [ device ] )
if rc == 0 :
2016-11-02 01:52:18 +03:00
cfg . load ( )
created_pv = cfg . om . get_object_path_by_lvm_id ( device )
2016-02-18 02:53:35 +03:00
else :
raise dbus . exceptions . DBusException (
MANAGER_INTERFACE ,
' Exit code %s , stderr = %s ' % ( str ( rc ) , err ) )
return created_pv
@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 )
if rc == 0 :
2016-11-02 01:52:18 +03:00
cfg . load ( )
return cfg . om . get_object_path_by_lvm_id ( name )
2016-02-18 02:53:35 +03:00
else :
raise dbus . exceptions . DBusException (
MANAGER_INTERFACE ,
' Exit code %s , stderr = %s ' % ( str ( rc ) , err ) )
@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 :
utils . log_debug ( ' Manager.Refresh - exit %d ' % ( rc ) ,
' bg_black ' , ' fg_light_red ' )
else :
utils . log_debug ( ' Manager.Refresh - exit %d ' % ( rc ) )
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 )
@dbus.service.method (
dbus_interface = MANAGER_INTERFACE ,
in_signature = ' s ' ,
out_signature = ' o ' )
def LookUpByLvmId ( self , key ) :
"""
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
: return : Return the object path . If object not found you will get ' / '
"""
2016-09-28 19:16:49 +03:00
p = cfg . om . get_object_path_by_uuid_lvm_id ( key , key )
2016-02-18 02:53:35 +03:00
if p :
return p
return ' / '
@dbus.service.method (
dbus_interface = MANAGER_INTERFACE ,
2016-08-29 22:26:16 +03:00
in_signature = ' b ' , out_signature = ' b ' )
2016-02-18 02:53:35 +03:00
def UseLvmShell ( self , yes_no ) :
"""
Allow the client to enable / disable lvm shell , used for testing
: param yes_no :
: return : Nothing
"""
2016-08-29 22:26:16 +03:00
return dbus . Boolean ( cmdhandler . set_execution ( yes_no ) )
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 ) :
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 ( ) :
utils . log_debug ( " ExternalEvent received, disabling "
" udev monitoring " )
# We are dependent on external events now to stay current!
cfg . ee = True
2016-02-18 02:53:35 +03:00
event_add ( ( command , ) )
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 )
if rc == 0 :
# This could potentially change the state quite a bit, so lets
# update everything to be safe
cfg . load ( )
return ' / '
else :
raise dbus . exceptions . DBusException (
MANAGER_INTERFACE ,
' Exit code %s , stderr = %s ' % ( str ( rc ) , err ) )
@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 ( )