LCM/scripts/python3/StartDscConfiguration.py (162 lines of code) (raw):

#!/usr/bin/env python3 # Standard library imports import sys from subprocess import Popen, PIPE from sys import argv import warnings with warnings.catch_warnings(): warnings.filterwarnings("ignore",category=DeprecationWarning) from imp import load_source from os.path import dirname, isfile, join, realpath from fcntl import flock, LOCK_EX, LOCK_UN, LOCK_NB from OmsConfigHostHelpers import write_omsconfig_host_telemetry, write_omsconfig_host_switch_event, write_omsconfig_host_log, stop_old_host_instances from time import sleep import subprocess import codecs 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 = load_source('helperlib', helperLibPath) try: # Used by Python 2.7+ from argparse import ArgumentParser useArgParse = True except: # Used by Python 2.4-2.6 from optparse import OptionParser useArgParse = False def main(argv): """StartDscConfiguration""" # Define method arguments and description description = 'Starts the specified DSC configuration.' parameters = { 'configurationmof' : { 'shortForm' : 'c', 'helpText' : 'The path to the configuration mof to start.', 'required' : True, 'action' : 'store' }, 'force' : { 'shortForm' : 'f', 'helpText' : 'Specifies that any current pending configuration should be forcibly removed before starting the new configuration.', 'required' : False, 'action' : 'store_true' } } # Parse -configurationmof on its own for backwards compatibility configmofArgument = None if '-configurationmof' in argv: configmofIndex = argv.index('-configurationmof') try: configmofArgument = argv[configmofIndex + 1] except: print('StartDscConfiguration.py: error: Please provide a valid path argument for -configurationmof') exit(1) # Set the configuration mof parameter to no longer be required so it doesn't error in the arugment parser parameters['configurationmof']['required'] = False # Remove -configurationmof and its argument from the list so it doesn't error in the arugment parser argv.pop(configmofIndex) argv.pop(configmofIndex) # Parse arguments if (useArgParse): # Used by Python 2.7+ parser = ArgumentParser(description = description) for parameter in parameters.keys(): parameterInfo = parameters[parameter] parser.add_argument('-' + parameterInfo['shortForm'], '--' + parameter, required = parameterInfo['required'], help = parameterInfo['helpText'], action = parameterInfo['action']) parsedArguments = parser.parse_args(argv) else: # Used by Python 2.4-2.6 parser = OptionParser(description = description) for parameter in parameters.keys(): parameterInfo = parameters[parameter] parser.add_option('-' + parameterInfo['shortForm'], '--' + parameter, help = parameterInfo['helpText'], action = parameterInfo['action']) (parsedArguments, extraArguments) = parser.parse_args(argv) for parameter in parameters.keys(): if parameters[parameter]['required']: if not getattr(parsedArguments, parameter): print ('StartDscConfiguration.py: error: argument -', parameters[parameter]['shortForm'], '/--', parameter, ' is required.') exit(1) # Check that we don't have two configuration mofs defined if configmofArgument and parsedArguments.configurationmof: print('StartDscConfiguration.py: error: Two configuration mof arguments were found. Please provide only one.') exit(1) if configmofArgument: parsedArguments.configurationmof = configmofArgument # Read the configuration mof try: configurationFile = codecs.open(parsedArguments.configurationmof, 'r') except: configurationFile = codecs.open(parsedArguments.configurationmof, 'r', encoding = 'utf-16') try: configurationFileContent = configurationFile.read() finally: if (configurationFile): configurationFile.close() # Convert the file content to strings of integers representing unicode configurationData = [] for char in configurationFileContent: configurationData.append(str(ord(char))) # # OMI CLI location omicli_path = join(helperlib.CONFIG_BINDIR, 'omicli') dsc_host_base_path = helperlib.DSC_HOST_BASE_PATH dsc_host_path = join(dsc_host_base_path, 'bin/dsc_host') dsc_host_output_path = join(dsc_host_base_path, 'output') dsc_host_lock_path = join(dsc_host_base_path, 'dsc_host_lock') dsc_host_switch_path = join(dsc_host_base_path, 'dsc_host_ready') if ("omsconfig" in helperlib.DSC_SCRIPT_PATH): write_omsconfig_host_switch_event(pathToCurrentScript, isfile(dsc_host_switch_path)) if ("omsconfig" in helperlib.DSC_SCRIPT_PATH) and (isfile(dsc_host_switch_path)): use_omsconfig_host = True else: use_omsconfig_host = False # Assemble parameters to pass to OMI CLI host_parameters = [] if use_omsconfig_host: host_parameters.append(dsc_host_path) host_parameters.append(dsc_host_output_path) host_parameters.append("SendConfigurationApply") host_parameters.append(args[2]) # Insert force if specified if parsedArguments.force: host_parameters.append("force") else: host_parameters.append(omicli_path) host_parameters.append("iv") host_parameters.append("<DSC_NAMESPACE>") host_parameters.append("{") host_parameters.append("MSFT_DSCLocalConfigurationManager") host_parameters.append("}") host_parameters.append("SendConfigurationApply") host_parameters.append("{") host_parameters.append("ConfigurationData") host_parameters.append("[") # Insert configurationmof data here for token in configurationData: host_parameters.append(token) host_parameters.append("]") # Insert force if specified if parsedArguments.force: host_parameters.append("force") host_parameters.append("true") host_parameters.append("}") stdout = '' stderr = '' if use_omsconfig_host: try: stop_old_host_instances(dsc_host_lock_path) # Open the dsc host lock file. This also creates a file if it does not exist dschostlock_filehandle = open(dsc_host_lock_path, 'w') print("Opened the dsc host lock file at the path '" + dsc_host_lock_path + "'") dschostlock_acquired = False # Acquire dsc host file lock for retry in range(10): try: flock(dschostlock_filehandle, LOCK_EX | LOCK_NB) dschostlock_acquired = True break except IOError: write_omsconfig_host_log('dsc_host lock file not acquired. retry (#' + str(retry) + ') after 60 seconds...', pathToCurrentScript) sleep(60) if dschostlock_acquired: p = subprocess.Popen(parameters, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = p.communicate() stdout = stdout.decode() if isinstance(stdout, bytes) else stdout print(stdout) else: print("dsc host lock already acuired by a different process") finally: if (dschostlock_filehandle): # Release dsc host file lock flock(dschostlock_filehandle, LOCK_UN) # Close dsc host lock file handle dschostlock_filehandle.close() else: p = subprocess.Popen(host_parameters, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = p.communicate() stdout = stdout.decode() if isinstance(stdout, bytes) else stdout stderr = stderr.decode() if isinstance(stderr, bytes) else stderr print(stdout) print(stderr) LG().Log("DEBUG", "Starting Main method for " + argv[0] + " runing with python " + str(sys.version_info)) main(argv[1:]) LG().Log("DEBUG", "End of Main method for " + argv[0] + " runing with python " + str(sys.version_info))