MOON
Server: Apache
System: Linux vps.erhabenn.com.br 3.10.0-1160.119.1.el7.tuxcare.els2.x86_64 #1 SMP Mon Jul 15 12:09:18 UTC 2024 x86_64
User: machen (1008)
PHP: 8.2.31
Disabled: NONE
Upload Files
File: //opt/microsoft/omsagent/tst/modules/errors_tsg.py
from error_codes          import *
from errors               import error_info, get_input, is_error
from connect.check_endpts import check_internet_connect

# urlopen() in different packages in Python 2 vs 3
try:
    from urllib.request import urlopen
except ImportError:
    from urllib2 import urlopen

TSG_URL = "https://raw.github.com/microsoft/OMS-Agent-for-Linux/master/docs/Troubleshooting.md"
TSG_DOC_PATH = "/opt/microsoft/omsagent/tst/files/Troubleshooting.md"

# TODO: grab these directly from https://docs.microsoft.com/en-us/azure/virtual-machines/extensions/oms-linux#error-codes-and-their-meanings
extension_err_codes_dict = {
    '0'  : "No errors found",
    '9'  : "Enable called prematurely, try updating the Azure Linux Agent to the latest available version",
    '10' : "VM is already connected to a Log Analytics workspace",
    '11' : "Invalid config provided to the extension",
    '17' : "Log Analytics package installation failure",
    '19' : "OMI package installation failure",
    '20' : "SCX package installation failure",
    '51' : "This extension is not supported on the VM's operation system",
    '55' : "Cannot connect to the Azure Monitor service, or required packages missing, or dpkg package manager is locked"
}



# parse through error codes to get dictionary
def parse_error_codes(ts_doc, section_name, source_url):
    try:
        err_codes = {0 : "No errors found"}
        section = None
        for line in ts_doc:
            if (source_url):
                line = line.decode('utf8')
            line = line.rstrip('\n')
            if (line == ''):
                continue
            if (line.startswith('##')):
                section = line[3:]
                continue
            if (section == section_name):
                parsed_line = list(map(lambda x : x.strip(' '), line.split('|')))[1:-1]
                if (parsed_line[0] in ['Error Code', '---']):
                    continue
                err_codes[parsed_line[0]] = parsed_line[1]
                continue
            if (section==section_name and line.startswith('#')):
                break
        # parsing error occurred
        if (err_codes == {0 : "No errors found"}):
            return (None, "Couldn't parse Troubleshooting.md")
        # everything worked correctly
        return (err_codes, None)

    # some other error occurred
    except Exception as e:
        return (None, "Issue parsing Troubleshooting.md: {0}".format(e))



# get error codes from Troubleshooting.md
def get_error_codes(err_type):
    # extension
    if (err_type == 'Extension'):
        return (extension_err_codes_dict, None)

    # shell bundle or onboarding
    section_name = "{0} Error Codes".format(err_type)

    # try getting it via file
    try:
        with open(TSG_DOC_PATH) as ts_doc:
            return parse_error_codes(ts_doc, section_name, False)

    except Exception as e:
        # try getting it via 'wget'
        try:
            ts_doc = urlopen(TSG_URL)
            return parse_error_codes(ts_doc.readlines(), section_name, True)

        except:
            # opening via file errored
            checked_urlopen = check_urlopen_errs(e)
            return (None, checked_urlopen)



# check errors involving urlopen function
def check_urlopen_errs(err_msg):
    # error in connection, check connection
    checked_internet = check_internet_connect()
    if (is_error(checked_internet)):
        return "Machine is not connected to the internet"

    # ssl package not installed
    if (err_msg == "<urlopen error unknown url type: https>"):
        try:
            import ssl
        except ImportError:
            return "This version of Python is missing the ssl package"

    # connection in general fine, connecting to current page not
    return "Can't connect to {0}: {1}".format(TSG_URL, err_msg)



# ask user if they encountered error code
def ask_error_codes(err_type, err_types):
    # ask if user has error code
    answer = get_input("Do you have an {0} error code? (y/n)".format(err_type.lower()),\
                       (lambda x : x.lower() in ['y','yes','n','no']),\
                       "Please type either 'y'/'yes' or 'n'/'no' to proceed.")
    if (answer.lower() in ['y','yes']):
        # get dict of all error codes
        (err_codes, tsg_error) = get_error_codes(err_type)
        if (err_codes == None):
            print("WARNING (INTERNAL): {0}\n Skipping this check...".format(tsg_error))
            print("--------------------------------------------------------------------------------")
            return NO_ERROR

        # ask user for error code
        poss_ans = lambda x : x.isdigit() or (x in ['NOT_DEFINED', 'none'])
        err_code = get_input("Please input the error code", poss_ans,\
                             "Please enter an error code ({0})\nto get the error message, or "\
                                "type 'none' to continue with the troubleshooter.".format(err_types))
        # did user give integer, but not valid error code
        while (err_code.isdigit() and (not err_code in list(err_codes.keys()))):
            print("{0} is not a valid {1} error code.".format(err_code, err_type.lower()))
            err_code = get_input("Please input the error code", poss_ans,\
                                 "Please enter an error code ({0})\nto get the error message, or type "\
                                    "'none' to continue with the troubleshooter.".format(err_types))
        # print out error, ask to exit
        if (err_code != 'none'):
            print("\nError {0}: {1}\n".format(err_code, err_codes[err_code]))
            answer1 = get_input("Would you like to continue with the troubleshooter? (y/n)",\
                                (lambda x : x.lower() in ['y','yes','n','no']),
                                "Please type either 'y'/'yes' or 'n'/'no' to proceed.")
            if (answer1.lower() in ['n','no']):
                print("Exiting troubleshooter...")
                print("================================================================================")
                return USER_EXIT
    print("Continuing on with troubleshooter...")
    print("--------------------------------------------------------------------------------")
    return NO_ERROR



# make specific for installation versus onboarding
def ask_install_error_codes():
    print("--------------------------------------------------------------------------------")
    print("Installation error codes can be found for either shell bundle or extension\n"\
          "installation, and can help give a quick idea of what went wrong (separate \n"\
          "from the troubleshooter's tests).")
    do_install_tests = get_input("Do you have an installation code from either installing via shell bundle (b) or\n"\
                                    "via extension (e)? (Type 's' to skip)",\
                                 (lambda x : x.lower() in ['b','bundle','e','extension','s','skip']),\
                                 "Please enter 'bundle'/'b' for a shell bundle code, 'extension'/'e' for an\n"\
                                    "extension code, or 's'/'skip' to skip.")
    
    # shell bundle error code
    if (do_install_tests.lower() in ['b','bundle']):
        print("--------------------------------------------------------------------------------")
        print("Shell bundle error codes can be found by going through the command output in \n"\
              "the terminal after running the `omsagent-*.universal.x64.sh` script to find \n"\
              "a line that matches:\n"\
              "\n    Shell bundle exiting with code <err>\n")
        return ask_error_codes('Installation', "either an integer or 'NOT_DEFINED'")

    # extension error code
    elif (do_install_tests.lower() in ['e','extension']):
        print("--------------------------------------------------------------------------------")
        print("Data about the state of extension deployments can be retrieved from the Azure \n"\
              "portal, and by using the Azure CLI.")
        return ask_error_codes('Extension', "an integer")

    # requested to skip
    else:
        print("Continuing on with troubleshooter...")
        print("--------------------------------------------------------------------------------")



def ask_onboarding_error_codes():
    print("--------------------------------------------------------------------------------")
    print("Onboarding error codes can help give a quick idea of what went wrong (separate \n"\
          "from the troubleshooter's tests).")
    print("Onboarding error codes can be found by running the command:\n"\
          "\n    echo $?\n\n"\
          "directly after running the `/opt/microsoft/omsagent/bin/omsadmin.sh` tool.")
    return ask_error_codes('Onboarding', "an integer")