helperLibPath = join(pathToCommonScriptsFolder, 'helperlib.py')
helperlib = load_source('helperlib', helperLibPath)

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

LG().Log(
    "DEBUG", "Starting script logic for " + argv[0] + " runing with python " +
    str(sys.version_info.major))

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

parameters = []

if use_omsconfig_host:
    parameters.append(dsc_host_path)
    parameters.append(dsc_host_output_path)
    parameters.append("GetConfiguration")
else:
    parameters.append(omicli_path)
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)
def run_perform_required_configuration_checks():

    dsc_sysconfdir = join(helperlib.CONFIG_SYSCONFDIR, helperlib.CONFIG_SYSCONFDIR_DSC)
    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

    parameters = []
    if use_omsconfig_host:
        parameters.append(dsc_host_path)
        parameters.append(dsc_host_output_path)
        parameters.append("PerformRequiredConfigurationChecks")
        parameters.append("1")
    else:
        parameters.append(omicli_path)
        parameters.append("iv")
        parameters.append(helperlib.DSC_NAMESPACE)
        parameters.append("{")
        parameters.append("MSFT_DSCLocalConfigurationManager")
        parameters.append("}")
        parameters.append("PerformRequiredConfigurationChecks")
        parameters.append("{")
        parameters.append("Flags")
        parameters.append("1")
        parameters.append("}")

    stdout = ''
    stderr = ''

    if use_omsconfig_host:
        try:
            # Open the dsc host lock file. This also creates a file if it does not exist
            dschostlock_filehandle = None
            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(60):
                try:
                    flock(dschostlock_filehandle, LOCK_EX | LOCK_NB)
                    write_omsconfig_host_log('dsc_host lock file is acquired by : PerformRequiredConfigurationChecks', pathToCurrentScript)
                    dschostlock_acquired = True
                    break
                except IOError:
                    write_omsconfig_host_log('dsc_host lock file not acquired. retry (#' + str(retry) + ') after 60 seconds...', pathToCurrentScript)
                    sleep(15)
                    stop_old_host_instances(dsc_host_lock_path)
                
            if dschostlock_acquired:
                p = Popen(parameters, stdout=PIPE, stderr=PIPE)
                stdout, stderr = p.communicate()
                stdout = stdout.decode() if isinstance(stdout, bytes) else stdout
                print(stdout)
            else:
                print("dsc host lock already acquired 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 = Popen(parameters, stdout=PIPE, stderr=PIPE)
        stdout, stderr = p.communicate()
    stdout = stdout.decode() if isinstance(stdout, bytes) else stdout
    print(stdout)
def perform_inventory(args):
    Variables = dict()

    # Parse command line arguments
    optlist = []

    command_line_length = len(args)
    argIndex = 0
    inArgument = False
    currentArgument = ""
    arg = ""

    while argIndex < command_line_length:
        arg = args[argIndex]
        if argIndex == 0:
            # skip the program name
            argIndex += 1
            continue

        if inArgument:
            Variables[currentArgument] = arg
            inArgument = False
        else:
            if arg[0:2] == "--":
                inArgument = True
                currentArgument = arg[2:].lower()
            else:
                # The rest are not options
                args = args[argIndex:]
                break
        argIndex += 1

    if inArgument:
        Variables[currentArgument] = arg

    AcceptableOptions = ["inmof", "outxml", "help"]

    if "help" in Variables:
        usage()
        exit(0)

    optionsValid = True
    for arg in Variables.keys():
        if arg.lower() not in AcceptableOptions:
            optionsValid = False
            exitWithError("Error: %s is not a valid option" % arg)

    if optionsValid == False:
        usage()
        exit(1)

    dsc_sysconfdir = join(helperlib.CONFIG_SYSCONFDIR, helperlib.CONFIG_SYSCONFDIR_DSC)
    dsc_reportdir = join(dsc_sysconfdir, 'InventoryReports')
    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')
    dsc_configuration_path = join(dsc_sysconfdir, 'configuration')
    temp_report_path = join(dsc_configuration_path, 'Inventory.xml.temp')
    report_path = join(dsc_configuration_path, 'Inventory.xml')
    inventorylock_path = join(dsc_sysconfdir, 'inventory_lock')

    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

    if "outxml" in Variables:
        report_path = Variables["outxml"]

    parameters = []

    if use_omsconfig_host:
        parameters.append(dsc_host_path)
        parameters.append(dsc_host_output_path)

        if "inmof" in Variables:
            parameters.append("PerformInventoryOOB")
            parameters.append(Variables["inmof"])
        else:
            parameters.append("PerformInventory")
    else:
        parameters.append(omicli_path)
        parameters.append("iv")
        parameters.append(helperlib.DSC_NAMESPACE)
        parameters.append("{")
        parameters.append("MSFT_DSCLocalConfigurationManager")
        parameters.append("}")

        if "inmof" in Variables:
            parameters.append("PerformInventoryOOB")
            parameters.append("{")
            parameters.append("InventoryMOFPath")
            parameters.append(Variables["inmof"])
            parameters.append("}")
        else:
            parameters.append("PerformInventory")

    # Ensure inventory lock file permission is set correctly before opening
    operationStatusUtility.ensure_file_permissions(inventorylock_path, '644')

    # Open the inventory lock file. This also creates a file if it does not exist.
    inventorylock_filehandle = open(inventorylock_path, 'w')
    printVerboseMessage("Opened the inventory lock file at the path '" + inventorylock_path + "'")
    retval = 0
    inventorylock_acquired = True

    try:
        # Acquire inventory file lock
        try:
            flock(inventorylock_filehandle, LOCK_EX | LOCK_NB)
        except IOError:
            inventorylock_acquired = False
            write_omsconfig_host_log('Failed to acquire inventory lock.', pathToCurrentScript, 'WARNING')

        if inventorylock_acquired:
            dschostlock_acquired = False
            
            if use_omsconfig_host:
                if isfile(dsc_host_lock_path):
                    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')
                    printVerboseMessage("Opened the dsc host lock file at the path '" + dsc_host_lock_path + "'")

                    # 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)
                else:
                    write_omsconfig_host_log('dsc_host lock file does not exist. Skipping this operation until next consistency hits.', pathToCurrentScript, 'WARNING')

            if dschostlock_acquired or (not use_omsconfig_host):
                try:
                    system("rm -f " + dsc_reportdir + "/*")

                    process = Popen(parameters, stdout = PIPE, stderr = PIPE)
                    stdout, stderr = process.communicate()
                    retval = process.returncode

                    printVerboseMessage(stdout)

                    if (retval > 0):
                        write_omsconfig_host_log('dsc_host failed with code = ' + str(retval), pathToCurrentScript)
                        exit(retval)

                    # Combine reports together
                    reportFiles = listdir(dsc_reportdir)

                    final_xml_report = '<INSTANCE CLASSNAME="Inventory"><PROPERTY.ARRAY NAME="Instances" TYPE="string" EmbeddedObject="object"><VALUE.ARRAY>'
                    values = []
                    for reportFileName in reportFiles:
                        reportFilePath = join(dsc_reportdir, reportFileName)

                        if not isfile(reportFilePath):
                            continue
                        report = parse(reportFilePath)
                        for valueNode in report.getElementsByTagName('VALUE'):
                            values.append(valueNode.toxml())

                    final_xml_report = final_xml_report + "".join(values) + "</VALUE.ARRAY></PROPERTY.ARRAY></INSTANCE>"

                    # Ensure temporary inventory report file permission is set correctly before opening
                    operationStatusUtility.ensure_file_permissions(temp_report_path, '644')

                    tempReportFileHandle = open(temp_report_path, 'w')
                    try:
                        tempReportFileHandle.write(final_xml_report)
                    finally:
                        tempReportFileHandle.close()

                    # Ensure temporary inventory report file permission is set correctly after opening
                    operationStatusUtility.ensure_file_permissions(temp_report_path, '644')

                    system("rm -f " + dsc_reportdir + "/*")
                    move(temp_report_path, report_path)

                    # Ensure inventory report file permission is set correctly
                    operationStatusUtility.ensure_file_permissions(report_path, '644')
                finally:
                    # Release inventory file lock
                    flock(inventorylock_filehandle, LOCK_UN)

                    # Release dsc host file lock
                    if isfile(dsc_host_lock_path) and use_omsconfig_host:
                        try:
                            flock(dschostlock_filehandle, LOCK_UN)
                        except:
                            pass
    finally:
        # Close inventory lock file handle
        inventorylock_filehandle.close()
        
        # Close dsc host lock file handle
        if use_omsconfig_host:
            try:
                dschostlock_filehandle.close()
            except:
                pass

    # Ensure inventory lock file permission is set correctly after opening
    operationStatusUtility.ensure_file_permissions(inventorylock_path, '644')

    # Ensure dsc host lock file permission is set correctly after opening
    if use_omsconfig_host:
        operationStatusUtility.ensure_file_permissions(dsc_host_lock_path, '644')

    exit(retval)
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 = open(parsedArguments.configurationmof, 'r')
    except:
        configurationFile = open(parsedArguments.configurationmof, 'r', encoding = 'utf-16')

    try:
        configurationFileContent = configurationFile.read()
    finally:
        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
    omiBinDir = "<CONFIG_BINDIR>"
    omiCliPath = omiBinDir + "/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(omiCliPath)
        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:
            # 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()
                print(stdout)
            else:
                print("dsc host lock already acuired by a different process")
        finally:
            # Release dsc host file lock
            flock(dschostlock_filehandle, LOCK_UN)

            # Close dsc host lock file handle
            dschostlock_filehandle.close()
    else:
        p = subprocess.Popen(parameters, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        stdout, stderr = p.communicate()

    print(stdout)
    print(stderr)
pathToCurrentScript = realpath(__file__)
pathToCommonScriptsFolder = dirname(pathToCurrentScript)

helperLibPath = join(pathToCommonScriptsFolder, 'helperlib.py')
helperlib = load_source('helperlib', helperLibPath)

omi_bindir = "<CONFIG_BINDIR>"
omicli_path = omi_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

parameters = []

if use_omsconfig_host:
    parameters.append(dsc_host_path)
    parameters.append(dsc_host_output_path)
    parameters.append("GetMetaConfiguration")
else:
    parameters.append(omicli_path)
    parameters.append("iv")
def apply_meta_config(args):
    if len(args) != 3:
        usage()

    if args[1].lower() != '-configurationmof':
        usage()

    if (not isfile(args[2])):
        errorMessage = 'The provided configurationmof file does not exist: ' + str(args[2])
        print(errorMessage)
        write_omsconfig_host_log('Incorrect parameters to SetDscLocalConfigurationManager.py: ' + errorMessage, pathToCurrentScript, 'ERROR')
        exit(1)

    fileHandle = open(args[2], 'r')
    global proc
    try:
        fileContent = fileHandle.read()
        outtokens = []
        for char in fileContent:
            outtokens.append(str(ord(char)))

        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

        parameters = []

        if use_omsconfig_host:
            parameters.append(dsc_host_path)
            parameters.append(dsc_host_output_path)
            parameters.append("SendMetaConfigurationApply")
            parameters.append(args[2])
        else:
            parameters.append(omicli_path)
            parameters.append("iv")
            parameters.append(helperlib.DSC_NAMESPACE)
            parameters.append("{")
            parameters.append("MSFT_DSCLocalConfigurationManager")
            parameters.append("}")
            parameters.append("SendMetaConfigurationApply")
            parameters.append("{")
            parameters.append("ConfigurationData")
            parameters.append("[")
            # Insert configurationmof data here
            for token in outtokens:
                parameters.append(token)
            parameters.append("]")
            parameters.append("}")

        exit_code = 0
        stdout = ''
        stderr = ''

        # Apply the metaconfig
        if use_omsconfig_host:
            try:
                dschostlock_filehandle = None
                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)
                        write_omsconfig_host_log('dsc_host lock file is acquired by : SendMetaConfigurationApply', pathToCurrentScript)
                        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:
                    proc = Popen(parameters, stdout=PIPE, stderr=PIPE)
                    exit_code = proc.wait()
                    stdout, stderr = proc.communicate()
                    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:
            proc = Popen(parameters, stdout=PIPE, stderr=PIPE)
            exit_code = proc.wait()
            stdout, stderr = proc.communicate()

        print(stdout)

        if ((exit_code != 0) or (stderr)):
            exit(1)

    finally:
        fileHandle.close()
Beispiel #8
0
def run_perform_required_configuration_checks():

    dsc_sysconfdir = join(helperlib.CONFIG_SYSCONFDIR,
                          helperlib.CONFIG_SYSCONFDIR_DSC)
    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

    parameters = []
    if use_omsconfig_host:
        parameters.append(dsc_host_path)
        parameters.append(dsc_host_output_path)
        parameters.append("PerformRequiredConfigurationChecks")
        parameters.append("1")
    else:
        parameters.append(omicli_path)
        parameters.append("iv")
        parameters.append(helperlib.DSC_NAMESPACE)
        parameters.append("{")
        parameters.append("MSFT_DSCLocalConfigurationManager")
        parameters.append("}")
        parameters.append("PerformRequiredConfigurationChecks")
        parameters.append("{")
        parameters.append("Flags")
        parameters.append("1")
        parameters.append("}")

    # Save the starting timestamp without milliseconds
    startDateTime = operationStatusUtility.get_current_time_no_ms()

    stdout = ''
    stderr = ''

    if use_omsconfig_host:
        try:
            # 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(60):
                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(15)

            if dschostlock_acquired:
                p = Popen(parameters, stdout=PIPE, stderr=PIPE)
                stdout, stderr = p.communicate()
                print(stdout)
            else:
                print("dsc host lock already acuired by a different process")
        finally:
            # Release dsc host file lock
            flock(dschostlock_filehandle, LOCK_UN)

            # Close dsc host lock file handle
            dschostlock_filehandle.close()
    else:
        p = Popen(parameters, stdout=PIPE, stderr=PIPE)
        stdout, stderr = p.communicate()

    print(stdout)

    # Python 3 returns an empty byte array into stderr on success
    if stderr == '' or (version_info >=
                        (3, 0) and stderr.decode(encoding='UTF-8') == ''):
        operationStatusUtility.write_success_to_status_file(operation)
    else:
        operationStatusUtility.write_failure_to_status_file(
            operation, startDateTime, stderr)
        print(stderr)
def perform_inventory(args):
    Variables = dict()

    # Parse command line arguments
    optlist = []

    command_line_length = len(args)
    argIndex = 0
    inArgument = False
    currentArgument = ""
    arg = ""

    while argIndex < command_line_length:
        arg = args[argIndex]
        if argIndex == 0:
            # skip the program name
            argIndex += 1
            continue

        if inArgument:
            Variables[currentArgument] = arg
            inArgument = False
        else:
            if arg[0:2] == "--":
                inArgument = True
                currentArgument = arg[2:].lower()
            else:
                # The rest are not options
                args = args[argIndex:]
                break
        argIndex += 1

    if inArgument:
        Variables[currentArgument] = arg

    AcceptableOptions = ["inmof", "outxml", "help"]

    if "help" in Variables:
        usage()
        exit(0)

    optionsValid = True
    for arg in Variables.keys():
        if arg.lower() not in AcceptableOptions:
            optionsValid = False
            exitWithError("Error: %s is not a valid option" % arg)

    if optionsValid == False:
        usage()
        exit(1)

    dsc_sysconfdir = join(helperlib.CONFIG_SYSCONFDIR, helperlib.CONFIG_SYSCONFDIR_DSC)
    dsc_reportdir = join(dsc_sysconfdir, 'InventoryReports')
    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')
    dsc_configuration_path = join(dsc_sysconfdir, 'configuration')
    temp_report_path = join(dsc_configuration_path, 'Inventory.xml.temp')
    report_path = join(dsc_configuration_path, 'Inventory.xml')
    inventorylock_path = join(dsc_sysconfdir, 'inventory_lock')

    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

    if "outxml" in Variables:
        report_path = Variables["outxml"]

    parameters = []

    if use_omsconfig_host:
        parameters.append(dsc_host_path)
        parameters.append(dsc_host_output_path)

        if "inmof" in Variables:
            parameters.append("PerformInventoryOOB")
            parameters.append(Variables["inmof"])
        else:
            parameters.append("PerformInventory")
    else:
        parameters.append(omicli_path)
        parameters.append("iv")
        parameters.append(helperlib.DSC_NAMESPACE)
        parameters.append("{")
        parameters.append("MSFT_DSCLocalConfigurationManager")
        parameters.append("}")

        if "inmof" in Variables:
            parameters.append("PerformInventoryOOB")
            parameters.append("{")
            parameters.append("InventoryMOFPath")
            parameters.append(Variables["inmof"])
            parameters.append("}")
        else:
            parameters.append("PerformInventory")

    # Ensure inventory lock file permission is set correctly before opening
    operationStatusUtility.ensure_file_permissions(inventorylock_path, '644')

    # Open the inventory lock file. This also creates a file if it does not exist.
    inventorylock_filehandle = open(inventorylock_path, 'w')
    printVerboseMessage("Opened the inventory lock file at the path '" + inventorylock_path + "'")
    retval = 0
    inventorylock_acquired = True

    try:
        # Acquire inventory file lock
        try:
            flock(inventorylock_filehandle, LOCK_EX | LOCK_NB)
        except IOError:
            inventorylock_acquired = False

        if inventorylock_acquired:
            dschostlock_acquired = False
            
            if use_omsconfig_host:
                if isfile(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')
                    printVerboseMessage("Opened the dsc host lock file at the path '" + dsc_host_lock_path + "'")

                    # 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)
                else:
                    write_omsconfig_host_log('dsc_host lock file does not exist. Skipping this operation until next consistency hits.', pathToCurrentScript, 'WARNING')

            if dschostlock_acquired or (not use_omsconfig_host):
                try:
                    system("rm -f " + dsc_reportdir + "/*")

                    # Save the starting timestamp without milliseconds
                    startDateTime = operationStatusUtility.get_current_time_no_ms()

                    process = Popen(parameters, stdout = PIPE, stderr = PIPE)
                    stdout, stderr = process.communicate()
                    retval = process.returncode

                    printVerboseMessage(stdout)

                    if (retval > 0):
                        write_omsconfig_host_log('dsc_host failed with code = ' + str(retval), pathToCurrentScript)
                        exit(retval)

                    # Python 3 returns an empty byte array into stderr on success
                    if stderr == '' or (version_info >= (3, 0) and stderr.decode(encoding = 'UTF-8') == ''):
                        operationStatusUtility.write_success_to_status_file(operation)
                    else:
                        operationStatusUtility.write_failure_to_status_file(operation, startDateTime, stderr)
                        printVerboseMessage(stderr)

                    # Combine reports together
                    reportFiles = listdir(dsc_reportdir)

                    final_xml_report = '<INSTANCE CLASSNAME="Inventory"><PROPERTY.ARRAY NAME="Instances" TYPE="string" EmbeddedObject="object"><VALUE.ARRAY>'
                    values = []
                    for reportFileName in reportFiles:
                        reportFilePath = join(dsc_reportdir, reportFileName)

                        if not isfile(reportFilePath):
                            continue
                        report = parse(reportFilePath)
                        for valueNode in report.getElementsByTagName('VALUE'):
                            values.append(valueNode.toxml())

                    final_xml_report = final_xml_report + "".join(values) + "</VALUE.ARRAY></PROPERTY.ARRAY></INSTANCE>"

                    # Ensure temporary inventory report file permission is set correctly before opening
                    operationStatusUtility.ensure_file_permissions(temp_report_path, '644')

                    tempReportFileHandle = open(temp_report_path, 'w')
                    try:
                        tempReportFileHandle.write(final_xml_report)
                    finally:
                        tempReportFileHandle.close()

                    # Ensure temporary inventory report file permission is set correctly after opening
                    operationStatusUtility.ensure_file_permissions(temp_report_path, '644')

                    system("rm -f " + dsc_reportdir + "/*")
                    move(temp_report_path, report_path)

                    # Ensure inventory report file permission is set correctly
                    operationStatusUtility.ensure_file_permissions(report_path, '644')
                finally:
                    # Release inventory file lock
                    flock(inventorylock_filehandle, LOCK_UN)

                    # Release dsc host file lock
                    if isfile(dsc_host_lock_path) and use_omsconfig_host:
                        try:
                            flock(dschostlock_filehandle, LOCK_UN)
                        except:
                            pass
    finally:
        # Close inventory lock file handle
        inventorylock_filehandle.close()
        
        # Close dsc host lock file handle
        if use_omsconfig_host:
            try:
                dschostlock_filehandle.close()
            except:
                pass

    # Ensure inventory lock file permission is set correctly after opening
    operationStatusUtility.ensure_file_permissions(inventorylock_path, '644')

    # Ensure dsc host lock file permission is set correctly after opening
    if use_omsconfig_host:
        operationStatusUtility.ensure_file_permissions(dsc_host_lock_path, '644')

    exit(retval)
def run_perform_required_configuration_checks():

    dsc_sysconfdir = join(helperlib.CONFIG_SYSCONFDIR, helperlib.CONFIG_SYSCONFDIR_DSC)
    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

    parameters = []
    if use_omsconfig_host:
        parameters.append(dsc_host_path)
        parameters.append(dsc_host_output_path)
        parameters.append("PerformRequiredConfigurationChecks")
        parameters.append("1")
    else:
        parameters.append(omicli_path)
        parameters.append("iv")
        parameters.append(helperlib.DSC_NAMESPACE)
        parameters.append("{")
        parameters.append("MSFT_DSCLocalConfigurationManager")
        parameters.append("}")
        parameters.append("PerformRequiredConfigurationChecks")
        parameters.append("{")
        parameters.append("Flags")
        parameters.append("1")
        parameters.append("}")

    # Save the starting timestamp without milliseconds
    startDateTime = operationStatusUtility.get_current_time_no_ms()

    stdout = ''
    stderr = ''

    if use_omsconfig_host:
        try:
            # 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(60):
                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(15)
                
            if dschostlock_acquired:
                p = Popen(parameters, stdout=PIPE, stderr=PIPE)
                stdout, stderr = p.communicate()
                print(stdout)
            else:
                print("dsc host lock already acuired by a different process")
        finally:
            # Release dsc host file lock
            flock(dschostlock_filehandle, LOCK_UN)

            # Close dsc host lock file handle
            dschostlock_filehandle.close()
    else:
        p = Popen(parameters, stdout=PIPE, stderr=PIPE)
        stdout, stderr = p.communicate()

    print(stdout)

    # Python 3 returns an empty byte array into stderr on success
    if stderr == '' or (version_info >= (3, 0) and stderr.decode(encoding = 'UTF-8') == ''):
        operationStatusUtility.write_success_to_status_file(operation)
    else:
        operationStatusUtility.write_failure_to_status_file(operation, startDateTime, stderr)
        print(stderr)
def apply_meta_config(args):
    if len(args) != 3:
        usage()

    if args[1].lower() != '-configurationmof':
        usage()

    if (not isfile(args[2])):
        errorMessage = 'The provided configurationmof file does not exist: ' + str(args[2])
        print(errorMessage)
        operationStatusUtility.write_failure_to_status_file_no_log(operation, 'Incorrect parameters to SetDscLocalConfigurationManager.py: ' + errorMessage)
        exit(1)

    fileHandle = open(args[2], 'r')
    try:
        fileContent = fileHandle.read()
        outtokens = []
        for char in fileContent:
            outtokens.append(str(ord(char)))

        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

        parameters = []

        if use_omsconfig_host:
            parameters.append(dsc_host_path)
            parameters.append(dsc_host_output_path)
            parameters.append("SendMetaConfigurationApply")
            parameters.append(args[2])
        else:
            parameters.append(omicli_path)
            parameters.append("iv")
            parameters.append(helperlib.DSC_NAMESPACE)
            parameters.append("{")
            parameters.append("MSFT_DSCLocalConfigurationManager")
            parameters.append("}")
            parameters.append("SendMetaConfigurationApply")
            parameters.append("{")
            parameters.append("ConfigurationData")
            parameters.append("[")
            # Insert configurationmof data here
            for token in outtokens:
                parameters.append(token)
            parameters.append("]")
            parameters.append("}")

        exit_code = 0

        # Save the starting timestamp without milliseconds
        startDateTime = operationStatusUtility.get_current_time_no_ms()

        stdout = ''
        stderr = ''

        # Apply the metaconfig
        if use_omsconfig_host:
            try:
                # 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 = Popen(parameters, stdout=PIPE, stderr=PIPE)
                    exit_code = p.wait()
                    stdout, stderr = p.communicate()
                    print(stdout)
                else:
                    print("dsc host lock already acuired by a different process")
            finally:
                # Release dsc host file lock
                flock(dschostlock_filehandle, LOCK_UN)

                # Close dsc host lock file handle
                dschostlock_filehandle.close()
        else:
            p = Popen(parameters, stdout=PIPE, stderr=PIPE)
            exit_code = p.wait()
            stdout, stderr = p.communicate()

        print(stdout)

        if ((exit_code != 0) or (stderr)):
            exit(1)

        # Python 3 returns an empty byte array into stderr on success
        if stderr == '' or (version_info >= (3, 0) and stderr.decode(encoding = 'UTF-8') == ''):
            operationStatusUtility.write_success_to_status_file(operation)
            print("Successfully applied metaconfig.")
        else:
            operationStatusUtility.write_failure_to_status_file(operation, startDateTime, stderr)
            print(stderr)
    finally:
        fileHandle.close()