219 lines
6.4 KiB
Python
219 lines
6.4 KiB
Python
#
|
|
# 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])
|