Refactor common parts from cmd to wrapper

This is needed to allow daemon reuse these parts and be plugged in
clearly.

Change-Id: I01e020ae6f185faa446c715cf9a6b0c082260e13
This commit is contained in:
Yuriy Taraday 2014-07-15 18:27:54 +04:00
parent 196bdc0fa2
commit e6c39e8370
3 changed files with 50 additions and 41 deletions

View File

@ -33,10 +33,6 @@
from __future__ import print_function from __future__ import print_function
import logging import logging
import os
import pwd
import signal
import subprocess
import sys import sys
from six import moves from six import moves
@ -49,12 +45,6 @@ RC_BADCONFIG = 97
RC_NOEXECFOUND = 96 RC_NOEXECFOUND = 96
def _subprocess_setup():
# Python installs a SIGPIPE handler by default. This is usually not what
# non-Python subprocesses expect.
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
def _exit_error(execname, message, errorcode, log=True): def _exit_error(execname, message, errorcode, log=True):
print("%s: %s" % (execname, message), file=sys.stderr) print("%s: %s" % (execname, message), file=sys.stderr)
if log: if log:
@ -62,15 +52,6 @@ def _exit_error(execname, message, errorcode, log=True):
sys.exit(errorcode) sys.exit(errorcode)
def _getlogin():
try:
return os.getlogin()
except OSError:
return (os.getenv('USER') or
os.getenv('USERNAME') or
os.getenv('LOGNAME'))
def main(): def main():
# Split arguments, require at least a command # Split arguments, require at least a command
execname = sys.argv.pop(0) execname = sys.argv.pop(0)
@ -97,25 +78,20 @@ def main():
config.syslog_log_facility, config.syslog_log_facility,
config.syslog_log_level) config.syslog_log_level)
# Execute command if it matches any of the loaded filters
filters = wrapper.load_filters(config.filters_path) filters = wrapper.load_filters(config.filters_path)
try: run_one_command(execname, config, filters, userargs)
filtermatch = wrapper.match_filter(filters, userargs,
exec_dirs=config.exec_dirs)
if filtermatch:
command = filtermatch.get_command(userargs,
exec_dirs=config.exec_dirs)
if config.use_syslog:
logging.info("(%s > %s) Executing %s (filter match = %s)" % (
_getlogin(), pwd.getpwuid(os.getuid())[0],
command, filtermatch.name))
obj = subprocess.Popen(command,
def run_one_command(execname, config, filters, userargs):
# Execute command if it matches any of the loaded filters
try:
obj = wrapper.start_subprocess(
filters, userargs,
exec_dirs=config.exec_dirs,
log=config.use_syslog,
stdin=sys.stdin, stdin=sys.stdin,
stdout=sys.stdout, stdout=sys.stdout,
stderr=sys.stderr, stderr=sys.stderr)
preexec_fn=_subprocess_setup,
env=filtermatch.get_environment(userargs))
obj.wait() obj.wait()
sys.exit(obj.returncode) sys.exit(obj.returncode)

View File

@ -16,6 +16,9 @@
import logging import logging
import logging.handlers import logging.handlers
import os import os
import pwd
import signal
import subprocess
from six import moves from six import moves
@ -170,3 +173,34 @@ def match_filter(filter_list, userargs, exec_dirs=None):
# No filter matched # No filter matched
raise NoFilterMatched() raise NoFilterMatched()
def _subprocess_setup():
# Python installs a SIGPIPE handler by default. This is usually not what
# non-Python subprocesses expect.
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
def _getlogin():
try:
return os.getlogin()
except OSError:
return (os.getenv('USER') or
os.getenv('USERNAME') or
os.getenv('LOGNAME'))
def start_subprocess(filter_list, userargs, exec_dirs=[], log=False, **kwargs):
filtermatch = match_filter(filter_list, userargs, exec_dirs)
command = filtermatch.get_command(userargs, exec_dirs)
if log:
logging.info("(%s > %s) Executing %s (filter match = %s)" % (
_getlogin(), pwd.getpwuid(os.getuid())[0],
command, filtermatch.name))
obj = subprocess.Popen(command,
preexec_fn=_subprocess_setup,
env=filtermatch.get_environment(userargs),
**kwargs)
return obj

View File

@ -23,7 +23,6 @@ import mock
from six import moves from six import moves
import testtools import testtools
from oslo.rootwrap import cmd
from oslo.rootwrap import filters from oslo.rootwrap import filters
from oslo.rootwrap import wrapper from oslo.rootwrap import wrapper
@ -437,7 +436,7 @@ class RootwrapTestCase(testtools.TestCase):
def test_getlogin(self): def test_getlogin(self):
with mock.patch('os.getlogin') as os_getlogin: with mock.patch('os.getlogin') as os_getlogin:
os_getlogin.return_value = 'foo' os_getlogin.return_value = 'foo'
self.assertEqual(cmd._getlogin(), 'foo') self.assertEqual(wrapper._getlogin(), 'foo')
def test_getlogin_bad(self): def test_getlogin_bad(self):
with mock.patch('os.getenv') as os_getenv: with mock.patch('os.getenv') as os_getenv:
@ -445,7 +444,7 @@ class RootwrapTestCase(testtools.TestCase):
os_getenv.side_effect = [None, None, 'bar'] os_getenv.side_effect = [None, None, 'bar']
os_getlogin.side_effect = OSError( os_getlogin.side_effect = OSError(
'[Errno 22] Invalid argument') '[Errno 22] Invalid argument')
self.assertEqual(cmd._getlogin(), 'bar') self.assertEqual(wrapper._getlogin(), 'bar')
os_getlogin.assert_called_once_with() os_getlogin.assert_called_once_with()
self.assertEqual(os_getenv.call_count, 3) self.assertEqual(os_getenv.call_count, 3)