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])
 |