LCM/scripts/python3/RemoveModule.py (143 lines of code) (raw):
#!/usr/bin/env python3
import sys
import os
import subprocess
import shutil
import platform
import warnings
with warnings.catch_warnings():
warnings.filterwarnings("ignore",category=DeprecationWarning)
import imp
from imp import load_source
from os.path import dirname, join, realpath
from sys import argv
pathToCurrentScript = realpath(__file__)
pathToCommonScriptsFolder = dirname(pathToCurrentScript)
DSCLogPath = join(pathToCommonScriptsFolder, 'nxDSCLog.py')
nxDSCLog = load_source('nxDSCLog', DSCLogPath)
LG = nxDSCLog.DSCLog
helperLibPath = join(pathToCommonScriptsFolder, 'helperlib.py')
helperlib = imp.load_source('helperlib', helperLibPath)
fullPathDSCLogger = os.path.join(pathToCommonScriptsFolder, 'nxDSCLog.py')
nxDSCLog = imp.load_source('nxDSCLog', fullPathDSCLogger)
logger = nxDSCLog.ConsoleAndFileLogger()
sys.stdout = logger
def usage():
print("Usage:")
print(" RemoveModule.py NAME")
sys.exit(1)
def exitWithError(message, errorCode = 1):
if (isinstance(message, bytes)):
message = message.decode()
errorMessage = "ERROR from RemoveModule.py: " + message
print(errorMessage)
sys.exit(errorCode)
def printVerboseMessage(message):
if (isinstance(message, bytes)):
message = message.decode()
verboseMessage = "VERBOSE from RemoveModule.py: " + message
print(verboseMessage)
def getPlatformArchitectureFolderName():
platformArchitecture = platform.architecture()
if len(platformArchitecture) != 2:
exitWithError("The python function platform.architecture() failed to return a valid tuple. Cannot detect if this system has an x64 or an x86 architecture.")
if (platformArchitecture[0] == "64bit"):
platformArchitectureFolderName = "x64"
else:
platformArchitectureFolderName = "x86"
return platformArchitectureFolderName
def regenerateDscPythonScriptInitFiles():
regenerateInitFilesScriptPath = join(helperlib.DSC_SCRIPT_PATH, 'python3/RegenerateInitFiles.py')
regenerateInitFilesResult = subprocess.call(regenerateInitFilesScriptPath)
if regenerateInitFilesResult != 0:
exitWithError("Failed to regenerate the DSC __init__.py files with the result code " + regenerateInitFilesResult)
def main(args):
'''
Removes all the resources in the named module from DSC and OMI.
'''
# Parameter validation
if len(args) != 1:
usage()
moduleName = args[0]
modulePath = join(helperlib.DSC_MODULES_PATH, moduleName)
if os.path.isdir(modulePath):
printVerboseMessage("Found installed module " + moduleName + " at the path " + modulePath + ". Removing module.")
else:
exitWithError("Unable to find installed module " + moduleName + " at the path " + modulePath)
# TODO: Move this module-specifc section out of this generic script.
# Special section for nxOMSAutomationWorker module.
# The Linux Hybrid worker and manager needs to be killed before the module is removed.
# Also a good idea to remove the state and working directories.
if moduleName == "nxOMSAutomationWorker":
# Invoke deregister when it becomes available.
# Kill all processes running under the nxOMSAutomationWorker user.
# In some cases, there might be no processes to kill, and the return code of the following command might be non-zero.
# We make a best attempt to terminate the processes and don't care about its return code.
nxOMSAutomationWorkerUserName = "nxautomation"
subprocess.call(["sudo", "pkill", "-u", nxOMSAutomationWorkerUserName, ".*"])
# Remove the state directory for nxOMSAutomationWorker
nxOMSAutomationWorkerStateFolderPath = "/var/opt/microsoft/omsagent/state/automationworker"
shutil.rmtree(nxOMSAutomationWorkerStateFolderPath, ignore_errors=True)
# Remove the working directory for nxOMSAutomationWorker
nxOMSAutomationWorkerWorkingFolderPath = "/var/opt/microsoft/omsagent/run/automationworker"
shutil.rmtree(nxOMSAutomationWorkerWorkingFolderPath, ignore_errors=True)
# Populate common DSC paths
dscMainFolderPath = join(helperlib.CONFIG_SYSCONFDIR, helperlib.CONFIG_SYSCONFDIR_DSC)
dscConfigurationFolderPath = join (dscMainFolderPath, 'configuration')
dscConfigurationRegistrationFolderPath = join(dscConfigurationFolderPath, 'registration')
dscConfigurationSchemaFolderPath = join(dscConfigurationFolderPath, 'schema')
# Populate common OMI namespace path
omiNamespaceFolderName = helperlib.DSC_NAMESPACE.replace('/', '-')
omiRegistrationFolderPath = join(helperlib.CONFIG_SYSCONFDIR, 'omiregister')
omiNamespaceFolderPath = join(omiRegistrationFolderPath, omiNamespaceFolderName)
# Populate common platform architecture
resourceArchitectureFolderName = getPlatformArchitectureFolderName()
# Remove all the resources in the module from DSC and OMI
moduleResourcePath = join(modulePath, 'DSCResources')
moduleResources = os.listdir(moduleResourcePath)
for resource in moduleResources:
resourceFolderPath = join(moduleResourcePath, resource)
# Skip anything that is not a directory
if not os.path.isdir(resourceFolderPath):
continue
printVerboseMessage("Removing resource " + resource)
# Remove DSC schema for the resource
dscConfigurationSchemaFolderPath = join(dscConfigurationFolderPath, 'schema')
resourceDscSchemaFolderPath = join(dscConfigurationSchemaFolderPath, resource)
if os.path.isdir(resourceDscSchemaFolderPath):
shutil.rmtree(resourceDscSchemaFolderPath)
else:
printVerboseMessage("Unable to find DSC schema folder for resource " + resource + " at the path " + resourceDscSchemaFolderPath + ". Continuing with resource removal.")
# Remove DSC registration for the resource
resourceDscRegistrationFolderPath = join(dscConfigurationRegistrationFolderPath, resource)
if os.path.isdir(resourceDscRegistrationFolderPath):
shutil.rmtree(resourceDscRegistrationFolderPath)
else:
printVerboseMessage("Unable to find DSC registration folder for resource " + resource + " at the path " + resourceDscRegistrationFolderPath + ". Continuing with resource removal.")
# Remove the resource Python scripts from the DSC scripts directories
resourceLibraryFolderPath = join(resourceFolderPath, resourceArchitectureFolderName)
if not os.path.isdir(resourceLibraryFolderPath):
exitWithError("Unable to find the resource library folder for the " + resourceArchitectureFolderName + " architecture in the module at " + resourceLibraryFolderPath)
resourceScriptsFolderPath = join(resourceLibraryFolderPath, 'Scripts')
if not os.path.isdir(resourceLibraryFolderPath):
exitWithError("Unable to find the resource library scripts folder for the resource " + resource + " and platform architecture " + resourceArchitectureFolderName + " at the path " + resourceScriptsFolderPath + " in the extracted module.")
pythonVersionFileNames = ['2.4x-2.5x', '2.6x-2.7x', '3.x']
for pythonVersionFileName in pythonVersionFileNames:
resourceScriptsPythonVersionFolderPath = join(resourceScriptsFolderPath, pythonVersionFileName)
if not os.path.isdir(resourceScriptsPythonVersionFolderPath):
exitWithError("Unable to find the version-specific Python folder under the resource library scripts folder for the resource " + resource + " and platform architecture " + resourceArchitectureFolderName + " at the path " + resourceScriptsPythonVersionFolderPath + " in the extracted module.")
resourceScriptsPythonVersionScriptsFolderPath = join(resourceScriptsPythonVersionFolderPath, 'Scripts')
if not os.path.isdir(resourceScriptsPythonVersionScriptsFolderPath):
exitWithError("Unable to find the version-specific Python scripts folder under the resource library scripts folder for the resource " + resource + " and platform architecture " + resourceArchitectureFolderName + " at the path " + resourceScriptsPythonVersionScriptsFolderPath + " in the extracted module.")
resourceScriptFileNames = os.listdir(resourceScriptsPythonVersionScriptsFolderPath)
dscScriptsPythonVersionFolderPath = join(helperlib.DSC_SCRIPT_PATH, pythonVersionFileName)
dscScriptsPythonVersionScriptsFolderPath = join(dscScriptsPythonVersionFolderPath, 'Scripts')
for resourceScriptFileName in resourceScriptFileNames:
resourceScriptFilePath = join(dscScriptsPythonVersionScriptsFolderPath, resourceScriptFileName)
if os.path.isfile(resourceScriptFilePath):
os.remove(resourceScriptFilePath)
else:
printVerboseMessage("Unable to find resource script " + resourceScriptFileName + " under the DSC scripts folder at the path " + resourceScriptFilePath + ". Continuing with resource removal.")
# Remove OMI library file for the resource
resourceLibraryOriginalName = "lib" + resource + ".so"
if helperlib.DSC_NAMESPACE == "root/Microsoft/DesiredStateConfiguration":
resourceLibraryFileName = resourceLibraryOriginalName
else:
resourceLibraryFileName = resourceLibraryOriginalName.replace('.so', "_" + omiNamespaceFolderName + ".so")
resourceLibraryFilePath = join(helperlib.CONFIG_LIBDIR, resourceLibraryFileName)
if os.path.isfile(resourceLibraryFilePath):
os.remove(resourceLibraryFilePath)
else:
printVerboseMessage("Unable to find OMI library file for resource " + resource + " at the path " + resourceLibraryFilePath + ". Continuing with resource removal.")
# Remove OMSCONFIG library file for the resource
if "omsconfig" in helperlib.DSC_SCRIPT_PATH:
resourceSharedObjectDestinationPath = join("/opt/dsc/lib", resource)
if os.path.isdir(resourceSharedObjectDestinationPath):
shutil.rmtree(resourceSharedObjectDestinationPath)
# Remove OMI registration for the resource
resourceOmiRegistrationFileName = resource + ".reg"
resourceOmiRegistrationFilePath = join(omiNamespaceFolderPath, resourceOmiRegistrationFileName)
os.remove(resourceOmiRegistrationFilePath)
# Regenerate the DSC Python scripts init files
regenerateDscPythonScriptInitFiles()
# Remove the extracted module directory and everything in it
shutil.rmtree(modulePath)
if __name__ == "__main__":
LG().Log("DEBUG", "Starting Main method for " + argv[0] + " runing with python " + str(sys.version_info))
main(sys.argv[1:])
LG().Log("DEBUG", "End of Main method for " + argv[0] + " runing with python " + str(sys.version_info))