Пример #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_Arc_MSI_token():
    """
    This method is used to query the Hyrbid metdadata service of Arc 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
    """
    _, 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:
            arc_endpoint = metrics_utils.get_arc_endpoint()
            try:
                msiauthurl = arc_endpoint + "/metadata/identity/oauth2/token?api-version=2019-11-01&resource=https://ingestion.monitor.azure.com/"
                req = urllib.request.Request(msiauthurl,
                                             headers={'Metadata': 'true'})
                res = urllib.request.urlopen(req)
            except:
                # The above request is expected to fail and add a key to the path -
                authkey_dir = "/var/opt/azcmagent/tokens/"
                if not os.path.exists(authkey_dir):
                    log_messages += "Unable to find the auth key file at {0} returned from the arc msi auth request.".format(
                        authkey_dir)
                    return False, expiry_epoch_time, log_messages
                keys_dir = []
                for filename in os.listdir(authkey_dir):
                    keys_dir.append(filename)

                authkey_path = authkey_dir + keys_dir[-1]
                auth = "basic "
                with open(authkey_path, "r") as f:
                    key = f.read()
                auth += key
                req = urllib.request.Request(msiauthurl,
                                             headers={
                                                 'Metadata': 'true',
                                                 'authorization': auth
                                             })
                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