mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
lvmdbusd: Use udev until ExternalEvent occurs
The normal mode of operation will be to monitor for udev events until an ExternalEvent occurs. In that case the service will disable monitoring for udev events and use ExternalEvent exclusively. Note: User specifies --udev the service will always monitor udev regardless if ExternalEvent is being called too.
This commit is contained in:
parent
2352ff24a5
commit
4902034c89
@ -24,14 +24,18 @@ om = None
|
|||||||
# This is the global bus connection
|
# This is the global bus connection
|
||||||
bus = None
|
bus = None
|
||||||
|
|
||||||
|
# Command line args
|
||||||
|
args = None
|
||||||
|
|
||||||
|
# Set to true if we are depending on external events for updates
|
||||||
|
ee = False
|
||||||
|
|
||||||
# Shared state variable across all processes
|
# Shared state variable across all processes
|
||||||
run = multiprocessing.Value('i', 1)
|
run = multiprocessing.Value('i', 1)
|
||||||
|
|
||||||
# Debug
|
# If this is set to true, the current setup support lvm shell and we are
|
||||||
DEBUG = True
|
# running in that mode of operation
|
||||||
|
SHELL_IN_USE = None
|
||||||
# Use lvm shell
|
|
||||||
USE_SHELL = False
|
|
||||||
|
|
||||||
# Lock used by pprint
|
# Lock used by pprint
|
||||||
stdout_lock = multiprocessing.Lock()
|
stdout_lock = multiprocessing.Lock()
|
||||||
|
@ -13,6 +13,7 @@ import threading
|
|||||||
from itertools import chain
|
from itertools import chain
|
||||||
import collections
|
import collections
|
||||||
import traceback
|
import traceback
|
||||||
|
import os
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from . import cfg
|
from . import cfg
|
||||||
@ -101,7 +102,8 @@ def call_lvm(command, debug=False):
|
|||||||
# in different locations on the same box
|
# in different locations on the same box
|
||||||
command.insert(0, cfg.LVM_CMD)
|
command.insert(0, cfg.LVM_CMD)
|
||||||
|
|
||||||
process = Popen(command, stdout=PIPE, stderr=PIPE, close_fds=True)
|
process = Popen(command, stdout=PIPE, stderr=PIPE, close_fds=True,
|
||||||
|
env=os.environ)
|
||||||
out = process.communicate()
|
out = process.communicate()
|
||||||
|
|
||||||
stdout_text = bytes(out[0]).decode("utf-8")
|
stdout_text = bytes(out[0]).decode("utf-8")
|
||||||
@ -111,7 +113,7 @@ def call_lvm(command, debug=False):
|
|||||||
_debug_c(command, process.returncode, (stdout_text, stderr_text))
|
_debug_c(command, process.returncode, (stdout_text, stderr_text))
|
||||||
|
|
||||||
if process.returncode == 0:
|
if process.returncode == 0:
|
||||||
if cfg.DEBUG and out[1] and len(out[1]) and 'help' not in command:
|
if cfg.args.debug and out[1] and len(out[1]) and 'help' not in command:
|
||||||
log_error('WARNING: lvm is out-putting text to STDERR on success!')
|
log_error('WARNING: lvm is out-putting text to STDERR on success!')
|
||||||
_debug_c(command, process.returncode, (stdout_text, stderr_text))
|
_debug_c(command, process.returncode, (stdout_text, stderr_text))
|
||||||
|
|
||||||
@ -123,9 +125,10 @@ def _shell_cfg():
|
|||||||
try:
|
try:
|
||||||
lvm_shell = LVMShellProxy()
|
lvm_shell = LVMShellProxy()
|
||||||
_t_call = lvm_shell.call_lvm
|
_t_call = lvm_shell.call_lvm
|
||||||
cfg.USE_SHELL = True
|
cfg.SHELL_IN_USE = lvm_shell
|
||||||
except Exception:
|
except Exception:
|
||||||
_t_call = call_lvm
|
_t_call = call_lvm
|
||||||
|
cfg.SHELL_IN_USE = None
|
||||||
log_error(traceback.format_exc())
|
log_error(traceback.format_exc())
|
||||||
log_error("Unable to utilize lvm shell, dropping back to fork & exec")
|
log_error("Unable to utilize lvm shell, dropping back to fork & exec")
|
||||||
|
|
||||||
@ -133,6 +136,15 @@ def _shell_cfg():
|
|||||||
def set_execution(shell):
|
def set_execution(shell):
|
||||||
global _t_call
|
global _t_call
|
||||||
with cmd_lock:
|
with cmd_lock:
|
||||||
|
# If the user requested lvm shell and we are currently setup that
|
||||||
|
# way, just return
|
||||||
|
if cfg.SHELL_IN_USE and shell:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
if not shell and cfg.SHELL_IN_USE:
|
||||||
|
cfg.SHELL_IN_USE.exit_shell()
|
||||||
|
cfg.SHELL_IN_USE = None
|
||||||
|
|
||||||
_t_call = call_lvm
|
_t_call = call_lvm
|
||||||
if shell:
|
if shell:
|
||||||
_shell_cfg()
|
_shell_cfg()
|
||||||
@ -217,7 +229,7 @@ def pv_remove(device, remove_options):
|
|||||||
|
|
||||||
def _qt(tag_name):
|
def _qt(tag_name):
|
||||||
# When running in lvm shell you need to quote the tags
|
# When running in lvm shell you need to quote the tags
|
||||||
if cfg.USE_SHELL:
|
if cfg.SHELL_IN_USE:
|
||||||
return '"%s"' % tag_name
|
return '"%s"' % tag_name
|
||||||
return tag_name
|
return tag_name
|
||||||
|
|
||||||
@ -440,7 +452,7 @@ def supports_json():
|
|||||||
cmd = ['help']
|
cmd = ['help']
|
||||||
rc, out, err = call(cmd)
|
rc, out, err = call(cmd)
|
||||||
if rc == 0:
|
if rc == 0:
|
||||||
if cfg.USE_SHELL:
|
if cfg.SHELL_IN_USE:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
if 'fullreport' in err:
|
if 'fullreport' in err:
|
||||||
@ -488,7 +500,7 @@ def lvm_full_report_json():
|
|||||||
# With the current implementation, if we are using the shell then we
|
# With the current implementation, if we are using the shell then we
|
||||||
# are using JSON and JSON is returned back to us as it was parsed to
|
# are using JSON and JSON is returned back to us as it was parsed to
|
||||||
# figure out if we completed OK or not
|
# figure out if we completed OK or not
|
||||||
if cfg.USE_SHELL:
|
if cfg.SHELL_IN_USE:
|
||||||
assert(type(out) == dict)
|
assert(type(out) == dict)
|
||||||
return out
|
return out
|
||||||
else:
|
else:
|
||||||
|
@ -203,6 +203,12 @@ class LVMShellProxy(object):
|
|||||||
|
|
||||||
return rc, json_result, error_msg
|
return rc, json_result, error_msg
|
||||||
|
|
||||||
|
def exit_shell(self):
|
||||||
|
try:
|
||||||
|
self._write_cmd('exit\n')
|
||||||
|
except Exception as e:
|
||||||
|
log_error(str(e))
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
try:
|
try:
|
||||||
self.lvm_shell.terminate()
|
self.lvm_shell.terminate()
|
||||||
|
@ -92,6 +92,7 @@ def process_request():
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
start = time.time()
|
||||||
# Add simple command line handling
|
# Add simple command line handling
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument("--udev", action='store_true',
|
parser.add_argument("--udev", action='store_true',
|
||||||
@ -112,16 +113,13 @@ def main():
|
|||||||
# Ensure that we get consistent output for parsing stdout/stderr
|
# Ensure that we get consistent output for parsing stdout/stderr
|
||||||
os.environ["LC_ALL"] = "C"
|
os.environ["LC_ALL"] = "C"
|
||||||
|
|
||||||
args = parser.parse_args()
|
cfg.args = parser.parse_args()
|
||||||
|
|
||||||
cfg.DEBUG = args.debug
|
cmdhandler.set_execution(cfg.args.use_lvm_shell)
|
||||||
cmdhandler.set_execution(args.use_lvm_shell)
|
|
||||||
|
|
||||||
# List of threads that we start up
|
# List of threads that we start up
|
||||||
thread_list = []
|
thread_list = []
|
||||||
|
|
||||||
start = time.time()
|
|
||||||
|
|
||||||
# Install signal handlers
|
# Install signal handlers
|
||||||
for s in [signal.SIGHUP, signal.SIGINT]:
|
for s in [signal.SIGHUP, signal.SIGINT]:
|
||||||
try:
|
try:
|
||||||
@ -144,7 +142,7 @@ def main():
|
|||||||
|
|
||||||
cfg.load = load
|
cfg.load = load
|
||||||
|
|
||||||
cfg.db = lvmdb.DataStore(args.use_json)
|
cfg.db = lvmdb.DataStore(cfg.args.use_json)
|
||||||
|
|
||||||
# Start up thread to monitor pv moves
|
# Start up thread to monitor pv moves
|
||||||
thread_list.append(
|
thread_list.append(
|
||||||
@ -160,23 +158,25 @@ def main():
|
|||||||
process.damon = True
|
process.damon = True
|
||||||
process.start()
|
process.start()
|
||||||
|
|
||||||
|
# Add udev watching
|
||||||
|
if cfg.args.use_udev:
|
||||||
|
log_debug('Utilizing udev to trigger updates')
|
||||||
|
|
||||||
|
# In all cases we are going to monitor for udev until we get an
|
||||||
|
# ExternalEvent. In the case where we get an external event and the user
|
||||||
|
# didn't specify --udev we will stop monitoring udev
|
||||||
|
udevwatch.add()
|
||||||
|
|
||||||
end = time.time()
|
end = time.time()
|
||||||
log_debug(
|
log_debug(
|
||||||
'Service ready! total time= %.4f, lvm time= %.4f count= %d' %
|
'Service ready! total time= %.4f, lvm time= %.4f count= %d' %
|
||||||
(end - start, cmdhandler.total_time, cmdhandler.total_count),
|
(end - start, cmdhandler.total_time, cmdhandler.total_count),
|
||||||
'bg_black', 'fg_light_green')
|
'bg_black', 'fg_light_green')
|
||||||
|
|
||||||
# Add udev watching
|
|
||||||
if args.use_udev:
|
|
||||||
log_debug('Utilizing udev to trigger updates')
|
|
||||||
udevwatch.add()
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if cfg.run.value != 0:
|
if cfg.run.value != 0:
|
||||||
cfg.loop.run()
|
cfg.loop.run()
|
||||||
|
udevwatch.remove()
|
||||||
if args.use_udev:
|
|
||||||
udevwatch.remove()
|
|
||||||
|
|
||||||
for process in thread_list:
|
for process in thread_list:
|
||||||
process.join()
|
process.join()
|
||||||
|
@ -17,7 +17,7 @@ from . import cmdhandler
|
|||||||
from .fetch import load_pvs, load_vgs
|
from .fetch import load_pvs, load_vgs
|
||||||
from .request import RequestEntry
|
from .request import RequestEntry
|
||||||
from .refresh import event_add
|
from .refresh import event_add
|
||||||
|
from . import udevwatch
|
||||||
|
|
||||||
# noinspection PyPep8Naming
|
# noinspection PyPep8Naming
|
||||||
class Manager(AutomatedProperties):
|
class Manager(AutomatedProperties):
|
||||||
@ -181,6 +181,13 @@ class Manager(AutomatedProperties):
|
|||||||
in_signature='s', out_signature='i')
|
in_signature='s', out_signature='i')
|
||||||
def ExternalEvent(self, command):
|
def ExternalEvent(self, command):
|
||||||
|
|
||||||
|
# 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
|
||||||
event_add((command,))
|
event_add((command,))
|
||||||
return dbus.Int32(0)
|
return dbus.Int32(0)
|
||||||
|
|
||||||
|
@ -8,10 +8,12 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import pyudev
|
import pyudev
|
||||||
|
import threading
|
||||||
from .refresh import event_add
|
from .refresh import event_add
|
||||||
from . import cfg
|
from . import cfg
|
||||||
|
|
||||||
observer = None
|
observer = None
|
||||||
|
observer_lock = threading.RLock()
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal
|
# noinspection PyUnusedLocal
|
||||||
@ -40,15 +42,20 @@ def filter_event(action, device):
|
|||||||
|
|
||||||
|
|
||||||
def add():
|
def add():
|
||||||
global observer
|
with observer_lock:
|
||||||
context = pyudev.Context()
|
global observer
|
||||||
monitor = pyudev.Monitor.from_netlink(context)
|
context = pyudev.Context()
|
||||||
monitor.filter_by('block')
|
monitor = pyudev.Monitor.from_netlink(context)
|
||||||
observer = pyudev.MonitorObserver(monitor, filter_event)
|
monitor.filter_by('block')
|
||||||
observer.start()
|
observer = pyudev.MonitorObserver(monitor, filter_event)
|
||||||
|
observer.start()
|
||||||
|
|
||||||
|
|
||||||
def remove():
|
def remove():
|
||||||
global observer
|
with observer_lock:
|
||||||
observer.stop()
|
global observer
|
||||||
observer = None
|
if observer:
|
||||||
|
observer.stop()
|
||||||
|
observer = None
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
@ -265,7 +265,7 @@ def _common_log(msg, *attributes):
|
|||||||
# @param msg Message to output to stdout
|
# @param msg Message to output to stdout
|
||||||
# @return None
|
# @return None
|
||||||
def log_debug(msg, *attributes):
|
def log_debug(msg, *attributes):
|
||||||
if cfg.DEBUG:
|
if cfg.args.debug:
|
||||||
_common_log(msg, *attributes)
|
_common_log(msg, *attributes)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user