Zhou Zheng Sheng has uploaded a new change for review. Change subject: vdsm-tool: add service management utilities ......................................................................
vdsm-tool: add service management utilities Change-Id: Idd1cbcf5fd00bb1ec73c5970be012e294b3b4c55 Signed-off-by: Zhou Zheng Sheng <[email protected]> --- M lib/vdsm/tool/Makefile.am A lib/vdsm/tool/service.py M vdsm.spec.in 3 files changed, 277 insertions(+), 0 deletions(-) git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/01/13701/1 diff --git a/lib/vdsm/tool/Makefile.am b/lib/vdsm/tool/Makefile.am index 49c067c..31704cc 100644 --- a/lib/vdsm/tool/Makefile.am +++ b/lib/vdsm/tool/Makefile.am @@ -33,4 +33,5 @@ __init__.py \ passwd.py \ seboolsetup.py \ + service.py $(NULL) diff --git a/lib/vdsm/tool/service.py b/lib/vdsm/tool/service.py new file mode 100644 index 0000000..c7d705c --- /dev/null +++ b/lib/vdsm/tool/service.py @@ -0,0 +1,275 @@ +# Copyright 2013 IBM, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# +# Refer to the README and COPYING files for full details of the license +# + +''' +System service management utlities. +''' + +import os +import subprocess +import functools +import re + +from vdsm.tool import expose +from vdsm.utils import CommandPath + + +def execCmd(argv): + p = subprocess.Popen(argv, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + out, err = p.communicate() + rc = p.returncode + return (rc, out, err) + + +_SYSTEMCTL = CommandPath("systemctl", + "/bin/systemctl", + "/usr/bin/systemctl", + ) + +_INITCTL = CommandPath("initctl", + "/sbin/initctl", + ) + +_SERVICE = CommandPath("service", + "/sbin/service", + "/usr/sbin/service", + ) + +_CHKCONFIG = CommandPath("chkconfig", + "/sbin/chkconfig", + ) + +_UPDATERC = CommandPath("update-rc.d", + "/usr/sbin/update-rc.d", + ) + +_srvStartAlts = [] +_srvStopAlts = [] +_srvStatusAlts = [] +_srvRestartAlts = [] +_srvDisableAlts = [] + +try: + _SYSTEMCTL.cmd +except OSError: + pass +else: + def _systemctlNative(systemctlFun): + @functools.wraps(systemctlFun) + def wrapper(srvName): + cmd = [_SYSTEMCTL.cmd, "--no-pager", "list-unit-files"] + rc, out, err = execCmd(cmd) + if rc != 0: + return (rc, out, err) + lines = out.splitlines() + for line in lines: + if srvName + ".service" == line.split(" ", 1): + return systemctlFun(srvName) + return (1, "", "%s is not native systemctl service") + return wrapper + + @_systemctlNative + def _systemctlStart(srvName): + cmd = [_SYSTEMCTL.cmd, "start", srvName] + return execCmd(cmd) + + @_systemctlNative + def _systemctlStop(srvName): + cmd = [_SYSTEMCTL.cmd, "stop", srvName] + return execCmd(cmd) + + @_systemctlNative + def _systemctlStatus(srvName): + cmd = [_SYSTEMCTL.cmd, "status", srvName] + return execCmd(cmd) + + @_systemctlNative + def _systemctlRestart(srvName): + cmd = [_SYSTEMCTL.cmd, "restart", srvName] + return execCmd(cmd) + + @_systemctlNative + def _systemctlDisable(srvName): + cmd = [_SYSTEMCTL.cmd, "disable", srvName] + return execCmd(cmd) + + _srvStartAlts.append(_systemctlStart) + _srvStopAlts.append(_systemctlStop) + _srvStatusAlts.append(_systemctlStatus) + _srvRestartAlts.append(_systemctlRestart) + _srvDisableAlts.append(_systemctlDisable) + + +def _isStopped(message): + stopRegex = r"\Wstopped\W|\Wstop\W|\Wwaiting\W|\Wnot running\W" + return re.search(stopRegex, message, re.MULTILINE) is not None + +try: + _INITCTL.cmd +except OSError: + pass +else: + def _initctlStart(srvName): + cmd = [_INITCTL.cmd, "start", srvName] + return execCmd(cmd) + + def _initctlStop(srvName): + cmd = [_INITCTL.cmd, "stop", srvName] + return execCmd(cmd) + + def _initctlStatus(srvName): + cmd = [_INITCTL.cmd, "status", srvName] + rc, out, err = execCmd(cmd) + if rc == 0: + # initctl rc is 0 even though the service is stopped + rc = _isStopped(out) + return (rc, out, err) + + def _initctlRestart(srvName): + cmd = [_INITCTL.cmd, "restart", srvName] + return execCmd(cmd) + + def _initctlDisable(srvName): + if not os.path.isfile("/etc/init/%s.conf" % srvName): + return 1, "", "" + with open("/etc/init/%s.override" % srvName, "a") as f: + f.write("manual\n") + return 0, "", "" + + _srvStartAlts.append(_initctlStart) + _srvStopAlts.append(_initctlStop) + _srvStatusAlts.append(_initctlStatus) + _srvRestartAlts.append(_initctlRestart) + _srvDisableAlts.append(_initctlDisable) + + +try: + _SERVICE.cmd +except OSError: + pass +else: + def _serviceStart(srvName): + cmd = [_SERVICE.cmd, srvName, "start"] + return execCmd(cmd) + + def _serviceStop(srvName): + cmd = [_SERVICE.cmd, srvName, "stop"] + return execCmd(cmd) + + def _serviceStatus(srvName): + cmd = [_SERVICE.cmd, srvName, "status"] + rc, out, err = execCmd(cmd) + if rc == 0: + # certain service rc is 0 even though the service is stopped + rc = _isStopped(out) + return (rc, out, err) + + def _serviceRestart(srvName): + cmd = [_SERVICE.cmd, srvName, "restart"] + return execCmd(cmd) + + _srvStartAlts.append(_serviceStart) + _srvStopAlts.append(_serviceStop) + _srvRestartAlts.append(_serviceRestart) + _srvStatusAlts.append(_serviceStatus) + + +try: + _CHKCONFIG.cmd +except OSError: + pass +else: + def _chkconfigDisable(srvName): + cmd = [_CHKCONFIG.cmd, srvName, "off"] + return execCmd(cmd) + + _srvDisableAlts.append(_chkconfigDisable) + + +try: + _UPDATERC.cmd +except OSError: + pass +else: + def _updatercDisable(srvName): + cmd = [_UPDATERC.cmd, srvName, "disable"] + return execCmd(cmd) + + _srvDisableAlts.append(_updatercDisable) + + +def _runAlts(alts, *args, **kwarg): + errors = {} + for alt in alts: + try: + rc, out, err = alt(*args, **kwarg) + except Exception as e: + errors[alt.func_name] = e + else: + if rc == 0: + return + else: + errors[alt.func_name] = (rc, out, err) + raise RuntimeError("Tried all alternatives but failed:\n%s" % errors) + + +@expose("service_start") +def service_start(srvName): + """ + Start a system service + """ + _runAlts(_srvStartAlts, srvName) + return 0 + + +@expose("service_stop") +def service_stop(srvName): + """ + Stop a system service + """ + _runAlts(_srvStopAlts, srvName) + return 0 + + +@expose("service_status") +def service_status(srvName): + """ + Get status of a system service + """ + _runAlts(_srvStatusAlts, srvName) + return 0 + + +@expose("service_restart") +def service_restart(srvName): + """ + Get status of a system service + """ + _runAlts(_srvRestartAlts, srvName) + return 0 + + +@expose("service_disable") +def service_disable(srvName): + """ + Disable a system service + """ + _runAlts(_srvDisableAlts, srvName) + return 0 diff --git a/vdsm.spec.in b/vdsm.spec.in index da2546f..4350140 100644 --- a/vdsm.spec.in +++ b/vdsm.spec.in @@ -900,6 +900,7 @@ %endif %{python_sitearch}/%{vdsm_name}/tool/passwd.py* %{python_sitearch}/%{vdsm_name}/tool/seboolsetup.py* +%{python_sitearch}/%{vdsm_name}/tool/service.py* %{python_sitearch}/%{vdsm_name}/tool/validate_ovirt_certs.py* %files tests -- To view, visit http://gerrit.ovirt.org/13701 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Idd1cbcf5fd00bb1ec73c5970be012e294b3b4c55 Gerrit-PatchSet: 1 Gerrit-Project: vdsm Gerrit-Branch: master Gerrit-Owner: Zhou Zheng Sheng <[email protected]> _______________________________________________ vdsm-patches mailing list [email protected] https://lists.fedorahosted.org/mailman/listinfo/vdsm-patches
