示例#1
0
def get_imds_values(is_lad):
    """
    Query imds to get required values for MetricsExtension config for this VM
    """
    retries = 1
    max_retries = 3
    sleep_time = 5
    imdsurl = ""
    is_arc = False

    if is_lad:
        imdsurl = "http://169.254.169.254/metadata/instance?api-version=2019-03-11"
    else:
        if metrics_utils.is_arc_installed():
            imdsurl = metrics_utils.get_arc_endpoint()
            imdsurl += "/metadata/instance?api-version=2019-11-01"
            is_arc = True
        else:
            imdsurl = "http://169.254.169.254/metadata/instance?api-version=2019-03-11"

    data = None
    while retries <= max_retries:

        #query imds to get the required information
        req = urllib.request.Request(imdsurl, headers={'Metadata': 'true'})
        res = urllib.request.urlopen(req)
        data = json.loads(res.read().decode('utf-8', 'ignore'))

        if "compute" not in data:
            retries += 1
        else:
            break

        time.sleep(sleep_time)

    if retries > max_retries:
        raise Exception(
            "Unable to find 'compute' key in imds query response. Reached max retry limit of - {0} times. Failed to setup ME."
            .format(max_retries))
        return False

    if "resourceId" not in data["compute"]:
        raise Exception(
            "Unable to find 'resourceId' key in imds query response. Failed to setup ME."
        )
        return False

    az_resource_id = data["compute"]["resourceId"]

    if "subscriptionId" not in data["compute"]:
        raise Exception(
            "Unable to find 'subscriptionId' key in imds query response. Failed to setup ME."
        )
        return False

    subscription_id = data["compute"]["subscriptionId"]

    if "location" not in data["compute"]:
        raise Exception(
            "Unable to find 'location' key in imds query response. Failed to setup ME."
        )
        return False

    location = data["compute"]["location"]

    return az_resource_id, subscription_id, location, data
def handle_config(config_data, me_url, mdsd_url, is_lad):
    """
    The main method to perfom the task of parsing the config , writing them to disk, setting up, stopping, removing and starting telegraf
    :param config_data: Parsed Metrics Configuration from which telegraf config is created
    :param me_url: The url to which telegraf will send metrics to for MetricsExtension
    :param mdsd_url: The url to which telegraf will send metrics to for MDSD
    :param is_lad: Boolean value for whether the extension is Lad or not (AMA)
    """

    # Making the imds call to get resource id, sub id, resource group and region for the dimensions for telegraf metrics
    retries = 1
    max_retries = 3
    sleep_time = 5
    imdsurl = ""
    is_arc = False

    if is_lad:
        imdsurl = "http://169.254.169.254/metadata/instance?api-version=2019-03-11"
    else:
        if metrics_utils.is_arc_installed():
            imdsurl = metrics_utils.get_arc_endpoint()
            imdsurl += "/metadata/instance?api-version=2019-11-01"
            is_arc = True
        else:
            imdsurl = "http://169.254.169.254/metadata/instance?api-version=2019-03-11"

    data = None
    while retries <= max_retries:

        req = urllib.request.Request(imdsurl, headers={'Metadata': 'true'})
        res = urllib.request.urlopen(req)
        data = json.loads(res.read().decode('utf-8', 'ignore'))

        if "compute" not in data:
            retries += 1
        else:
            break

        time.sleep(sleep_time)

    if retries > max_retries:
        raise Exception(
            "Unable to find 'compute' key in imds query response. Reached max retry limit of - {0} times. Failed to setup Telegraf."
            .format(max_retries))

    if "resourceId" not in data["compute"]:
        raise Exception(
            "Unable to find 'resourceId' key in imds query response. Failed to setup Telegraf."
        )

    az_resource_id = data["compute"]["resourceId"]

    # If the instance is VMSS then trim the last two values from the resource id ie - "/virtualMachines/0"
    # Since ME expects the resource id in a particular format. For egs -
    # IMDS returned ID - /subscriptions/<sub-id>/resourceGroups/<rg_name>/providers/Microsoft.Compute/virtualMachineScaleSets/<VMSSName>/virtualMachines/0
    # ME expected ID- /subscriptions/<sub-id>/resourceGroups/<rg_name>/providers/Microsoft.Compute/virtualMachineScaleSets/<VMSSName>
    if "virtualMachineScaleSets" in az_resource_id:
        az_resource_id = "/".join(az_resource_id.split("/")[:-2])

    if "subscriptionId" not in data["compute"]:
        raise Exception(
            "Unable to find 'subscriptionId' key in imds query response. Failed to setup Telegraf."
        )

    subscription_id = data["compute"]["subscriptionId"]

    if "resourceGroupName" not in data["compute"]:
        raise Exception(
            "Unable to find 'resourceGroupName' key in imds query response. Failed to setup Telegraf."
        )

    resource_group = data["compute"]["resourceGroupName"]

    if "location" not in data["compute"]:
        raise Exception(
            "Unable to find 'location' key in imds query response. Failed to setup Telegraf."
        )

    region = data["compute"]["location"]

    virtual_machine_name = ""
    if "vmScaleSetName" in data[
            "compute"] and data["compute"]["vmScaleSetName"] != "":
        virtual_machine_name = data["compute"]["name"]

    #call the method to first parse the configs
    output, namespaces = parse_config(config_data, me_url, mdsd_url, is_lad,
                                      az_resource_id, subscription_id,
                                      resource_group, region,
                                      virtual_machine_name)

    _, configFolder = get_handler_vars()
    if is_lad:
        telegraf_bin = metrics_constants.lad_telegraf_bin
    else:
        telegraf_bin = metrics_constants.ama_telegraf_bin

    telegraf_conf_dir = configFolder + "/telegraf_configs/"
    telegraf_agent_conf = telegraf_conf_dir + "telegraf.conf"
    telegraf_d_conf_dir = telegraf_conf_dir + "telegraf.d/"

    #call the method to write the configs
    write_configs(output, telegraf_conf_dir, telegraf_d_conf_dir)

    # Setup Telegraf service.
    # If the VM has systemd, then we will copy over the systemd unit file and use that to start/stop
    if metrics_utils.is_systemd():
        telegraf_service_setup = setup_telegraf_service(
            telegraf_bin, telegraf_d_conf_dir, telegraf_agent_conf)
        if not telegraf_service_setup:
            return False, []

    return True, namespaces
示例#3
0
def generate_MSI_token():
    """
    This method is used to query the metdadata service to get the MSI Auth token for the VM and write it to the ME config location
    This is called from the main extension code after config setup is complete
    """

    if metrics_utils.is_arc_installed():
        return generate_Arc_MSI_token()
    else:
        _, configFolder = get_handler_vars()
        me_config_dir = configFolder + "/metrics_configs/"
        me_auth_file_path = me_config_dir + "AuthToken-MSI.json"
        expiry_epoch_time = ""
        log_messages = ""
        retries = 1
        max_retries = 3
        sleep_time = 5

        if not os.path.exists(me_config_dir):
            log_messages += "Metrics extension config directory - {0} does not exist. Failed to generate MSI auth token fo ME.\n".format(
                me_config_dir)
            return False, expiry_epoch_time, log_messages
        try:
            data = None
            while retries <= max_retries:
                msiauthurl = "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://ingestion.monitor.azure.com/"
                req = urllib.request.Request(msiauthurl,
                                             headers={
                                                 'Metadata': 'true',
                                                 'Content-Type':
                                                 'application/json'
                                             })
                res = urllib.request.urlopen(req)
                data = json.loads(res.read().decode('utf-8', 'ignore'))

                if not data or "access_token" not in data:
                    retries += 1
                else:
                    break

                log_messages += "Failed to fetch MSI Auth url. Retrying in {2} seconds. Retry Count - {0} out of Mmax Retries - {1}\n".format(
                    retries, max_retries, sleep_time)
                time.sleep(sleep_time)

            if retries > max_retries:
                log_messages += "Unable to generate a valid MSI auth token at {0}.\n".format(
                    me_auth_file_path)
                return False, expiry_epoch_time, log_messages

            with open(me_auth_file_path, "w") as f:
                f.write(json.dumps(data))

            if "expires_on" in data:
                expiry_epoch_time = data["expires_on"]
            else:
                log_messages += "Error parsing the msi token at {0} for the token expiry time. Failed to generate the correct token\n".format(
                    me_auth_file_path)
                return False, expiry_epoch_time, log_messages

        except Exception as e:
            log_messages += "Failed to get msi auth token. Please check if VM's system assigned Identity is enabled Failed with error {0}\n".format(
                e)
            return False, expiry_epoch_time, log_messages

        return True, expiry_epoch_time, log_messages