usr/lib/python3/dist-packages/linuxmusterLinuxclient7/hooks.py
#
# This is used to run hooks
#
from enum import Enum
import os, subprocess
from linuxmusterLinuxclient7 import logging, constants, user, config, computer, environment, setup, shares
class Type(Enum):
"""
Enum containing all hook types
"""
Boot = 0
"""The onBoot hook
"""
Shutdown = 1
"""The on Shutdown hook
"""
LoginAsRoot = 2
"""The onLoginAsRoot hook
"""
Login = 3
"""The onLogin hook
"""
SessionStarted = 4
"""The onSession started hook
"""
LogoutAsRoot = 5
LoginLogoutAsRoot = 6
remoteScriptNames = {
Type.Boot: "sysstart.sh",
Type.Login: "logon.sh",
Type.SessionStarted: "sessionstart.sh",
Type.Shutdown: "sysstop.sh"
}
_remoteScriptInUserContext = {
Type.Boot: False,
Type.Login: True,
Type.SessionStarted: True,
Type.Shutdown: False
}
def runLocalHook(hookType):
"""
Run all scripts in a local hookdir
:param hookType: The type of hook to run
:type hookType: hooks.Type
"""
logging.info("=== Running local hook on{0} ===".format(hookType.name))
hookDir = _getLocalHookDir(hookType)
if os.path.exists(hookDir):
_prepareEnvironment()
for fileName in sorted(os.listdir(hookDir)):
filePath = hookDir + "/" + fileName
_runHookScript(filePath)
logging.info("===> Finished running local hook on{0} ===".format(hookType.name))
def runRemoteHook(hookType):
"""
Run hookscript from sysvol
:param hookType: The type of hook to run
:type hookType: hooks.Type
"""
logging.info("=== Running remote hook on{0} ===".format(hookType.name))
rc, hookScripts = _getRemoteHookScripts(hookType)
if rc:
_prepareEnvironment()
_runHookScript(hookScripts[0])
_runHookScript(hookScripts[1])
logging.info("===> Finished running remote hook on{0} ===".format(hookType.name))
def runHook(hookType):
"""
Executes hooks.runLocalHook() and hooks.runRemoteHook()
:param hookType: The type of hook to run
:type hookType: hooks.Type
"""
runLocalHook(hookType)
runRemoteHook(hookType)
def getLocalHookScript(hookType):
"""Get the path of a local hookscript
:param hookType: The type of hook script to get the path for
:type hookType: hooks.Type
:return: The path
:rtype: str
"""
return "{0}/on{1}".format(constants.scriptDir,hookType.name)
def shouldHooksBeExecuted(overrideUsername=None):
"""Check if hooks should be executed
:param overrideUsername: Override the username to check, defaults to None
:type overrideUsername: str, optional
:return: True if hooks should be executed, fale otherwise
:rtype: bool
"""
# check if linuxmuster-linuxclient7 is setup
if not setup.isSetup():
logging.info("==== Linuxmuster-linuxclient7 is not setup, exiting ====")
return False
# check if the computer is joined
if not computer.isInAD():
logging.info("==== This Client is not joined to any domain, exiting ====")
return False
# Check if the user is an AD user
if overrideUsername == None:
overrideUsername = user.username()
if not user.isUserInAD(overrideUsername):
logging.info("==== {0} is not an AD user, exiting ====".format(user.username()))
return False
return True
# --------------------
# - Helper functions -
# --------------------
def _prepareEnvironment():
dictsAndPrefixes = {}
rc, networkConfig = config.network()
if rc:
dictsAndPrefixes["Network"] = networkConfig
rc, userConfig = user.readAttributes()
if rc:
dictsAndPrefixes["User"] = userConfig
rc, computerConfig = computer.readAttributes()
if rc:
dictsAndPrefixes["Computer"] = computerConfig
environment = _dictsToEnv(dictsAndPrefixes)
_writeEnvironment(environment)
def _getLocalHookDir(hookType):
return "{0}/on{1}.d".format(constants.etcBaseDir,hookType.name)
def _getRemoteHookScripts(hookType):
if not hookType in remoteScriptNames:
return False, None
rc, networkConfig = config.network()
if not rc:
logging.error("Could not execute server hooks because the network config could not be read")
return False, None
if _remoteScriptInUserContext[hookType]:
rc, attributes = user.readAttributes()
if not rc:
logging.error("Could not execute server hooks because the user config could not be read")
return False, None
else:
rc, attributes = computer.readAttributes()
if not rc:
logging.error("Could not execute server hooks because the computer config could not be read")
return False, None
try:
domain = networkConfig["domain"]
school = attributes["sophomorixSchoolname"]
scriptName = remoteScriptNames[hookType]
except:
logging.error("Could not execute server hooks because the computer/user config is missing attributes")
return False, None
rc, sysvolPath = shares.getLocalSysvolPath()
if not rc:
logging.error("Could not execute server hook {} because the sysvol could not be mounted!\n")
return False, None
hookScriptPathTemplate = "{0}/{1}/scripts/{2}/{3}/linux/{4}".format(sysvolPath, domain, school, "{}", scriptName)
return True, [hookScriptPathTemplate.format("lmn"), hookScriptPathTemplate.format("custom")]
# parameter must be a dict of {"prefix": dict}
def _dictsToEnv(dictsAndPrefixes):
environmentDict = {}
for prefix in dictsAndPrefixes:
for key in dictsAndPrefixes[prefix]:
if type(dictsAndPrefixes[prefix][key]) is list:
environmentDict[prefix + "_" + key] = "\n".join(dictsAndPrefixes[prefix][key])
else:
environmentDict[prefix + "_" + key] = dictsAndPrefixes[prefix][key]
return environmentDict
def _runHookScript(filePath):
if not os.path.isfile(filePath):
logging.warning("* File {0} should be executed as hook but does not exist!".format(filePath))
return
if not os.access(filePath, os.X_OK):
logging.warning("* File {0} is in hook dir but not executable!".format(filePath))
return
logging.info("== Executing script {0} ==".format(filePath))
result = subprocess.call([filePath])
logging.info("==> Script {0} finished with exit code {1} ==".format(filePath, result))
def _writeEnvironment(environment):
for key in environment:
os.putenv(key, environment[key])