skip to Main Content

I’m trying to make an update using Azure Device Update on ubuntu 22.04. When my update is of type apt (microsoft/apt:1) it works fine.

But when I try to run a script (microsoft/script:1) i’m getting error from ADU: 810549253 (0x30500005).

ADUC_ERC_SCRIPT_HANDLER_MISSING_SCRIPTFILENAME_PROPERTY MAKE_ADUC_EXTENDEDRESULTCODE_FOR_COMPONENT_ADUC_CONTENT_HANDLER_SCRIPT(5)

List of errors: result.h

Here the script that I want to run:

script_test.sh:


#!/bin/bash

# Create a directory
mkdir -p /home/azureuser/this_was_create_by_adu

# Create a text file with specified content inside the directory
echo "this file was generated by adu" > /home/azureuser/this_was_create_by_adu/generated_file.txt

# Confirmation message
echo "Directory and file have been created successfully."

The import manifest:

script_test.importmanifest.json:

{
  "updateId": {
    "name": "script",
    "provider": "me",
    "version": "7.0.0"
  },
  "compatibility": [
    {
      "manufacturer": "hp",
      "model": "elite"
    }
  ],
  "createdDateTime": "2024-10-23T09:33:11Z",
  "files": [
    {
      "filename": "script_test.sh",
      "hashes": {
        "sha256": "lHKs3UsbWJAE3Svz3KwPCWibEofSPisKfB2rsbyIM4E="
      },
      "sizeInBytes": 328
    }
  ],
  "instructions": {
    "steps": [
      {
        "files": [
          "script_test.sh"
        ],
        "handler": "microsoft/script:1",
        "handlerProperties": {
        "installedCriteria": "1.0",
        },
        "type": "inline"
      }
    ]
  },
  "manifestVersion": "5.0"
}

The log error:

2024-11-05T15:39:52.8793Z 5742[7981] [I] Try to load a handler for current update manifest version 5 (handler: ‘microsoft/update-manifest:5’) [GetUpdateManifestHandler:114] 2024-11-05T15:39:52.8793Z 5742[7981] [I] Loading handler for ‘microsoft/update-manifest:5’. [LoadUpdateContentHandlerExtension:208] 2024-11-05T15:39:52.8794Z 5742[7981] [I] Loading extension ‘microsoft/update-manifest:5’. Reg file : /var/lib/adu/extensions/update_content_handlers/microsoft_update-manifest_5/content_handler.json [LoadExtensionLibrary:85] 2024-11-05T15:39:52.8794Z 5742[7981] [D] Determining contract version for ‘microsoft/update-manifest:5’. [LoadUpdateContentHandlerExtension:303] 2024-11-05T15:39:52.8794Z 5742[7981] [D] Got 1.0 contract version for ‘microsoft/update-manifest:5’ handler [LoadUpdateContentHandlerExtension:331] 2024-11-05T15:39:52.8794Z 5742[7981] [D] Caching new handler for ‘microsoft/update-manifest:5’. [LoadUpdateContentHandlerExtension:340] 2024-11-05T15:39:52.8797Z 5742[7981] [I] Action ‘Download’ complete. Result: 0 (failed), 810549253 (0x30500005) [ADUC_Workflow_WorkCompletionCallback:890] 2024-11-05T15:39:52.8797Z 5742[7981] [I] WorkCompletionCallback: Download failed. Going to state Failed [ADUC_Workflow_WorkCompletionCallback:1016] 2024-11-05T15:39:52.8797Z 5742[7981] [I] Setting UpdateState to Failed [ADUC_Workflow_SetUpdateStateHelper:1088]

2024-11-05T15:39:52.8797Z 5742[7981] [D] [ADUC_D2C_Message_SendAsync:526] ==== MULTI-LINE LOG BEGIN ====
Queueing message (t:0, c:0x64006e50, m:{"deviceUpdate":{"__t":"c","agent":{"lastInstallResult":{"stepResults":{"step_0":{"resultCode":0,"extendedResultCodes":"00000000","resultDetails":null}},"resultCode":0,"extendedResultCodes":"30500005,A0000FFF","resultDetails":""},"state":255,"workflow":{"action":3,"id":"aebe0066-67ba-4d78-a247-2656d91dd7c8"}}}})2024-11-05T15:39:52.8797Z 5742[7981] [D] [ADUC_D2C_Message_SendAsync:526] ==== MULTI-LINE LOG END ====

2024-11-05T15:39:52.8815Z 5742[7981] [I] Workflow is Complete. [ADUC_Workflow_AutoTransitionWorkflow:758] 2024-11-05T15:39:53.2803Z 5742[5742] [D] context:0xb6b015a0 [DefaultIoTHubSendReportedStateCompletedCallback:205] 2024-11-05T15:39:53.2803Z 5742[5742] [D] D2C message processed successfully (t:0, r:0, content:0xb8465da0 ) [DefaultIoTHubSendReportedStateCompletedCallback:233] 2024-11-05T15:39:53.2803Z 5742[5742] [D] Send message completed (status:3) [OnUpdateResultD2CMessageCompleted:64] 2024-11-05T15:39:53.2804Z 5742[5742] [D] context:0xb6b01640 [DefaultIoTHubSendReportedStateCompletedCallback:205] 2024-11-05T15:39:53.2804Z 5742[5742] [D] D2C message processed successfully (t:1, r:0, content:0xb843b8c0 ) [DefaultIoTHubSendReportedStateCompletedCallback:233] 2024-11-05T15:39:53.2804Z 5742[5742] [D] Send message completed (status:3) [OnUpdateResultD2CMessageCompleted:64] 2024-11-05T15:39:53.2804Z 5742[5742] [D] Sending D2C message (t:0, retries:0). [ProcessMessage:390]

2024-11-05T15:39:53.2804Z 5742[5742] [D] [ADUC_D2C_Default_Message_Transport_Function:580] ==== MULTI-LINE LOG BEGIN ====
Sending D2C message:
{"deviceUpdate":{"__t":"c","agent":{"lastInstallResult":{"stepResults":{"step_0":{"resultCode":0,"extendedResultCodes":"00000000","resultDetails":null}},"resultCode":0,"extendedResultCodes":"30500005,A0000FFF","resultDetails":""},"state":255,"workflow":{"action":3,"id":"aebe0066-67ba-4d78-a247-2656d91dd7c8"}}}}2024-11-05T15:39:53.2804Z 5742[5742] [D] [ADUC_D2C_Default_Message_Transport_Function:580] ==== MULTI-LINE LOG END ====

2

Answers


  1. Chosen as BEST ANSWER

    After restarting the Virtual Machine that I was using for testing, I encountered a different error:

    "The install script doesn't create a result file '/var/lib/adu/downloads/aebe0066-67ba-4d78-a247-2656d91dd7c8/action_download_aduc_result.json'."

    According to the responses on the issue I opened on GitHub, I noticed that I wasn't writing the result to the result file, which is mandatory

    https://github.com/Azure/iot-hub-device-update/issues/667.

    Following the documentation and the example script I rewrote the script and the import manifest and it worked properly:

    script_test.importmanifest.json:

    {
      "compatibility": [
        {
          "manufacturer": "hp",
          "model": "elite"
        }
      ],
      "createdDateTime": "2024-11-15T14:30:05Z",
      "files": [
        {
          "filename": "script_test.sh",
          "hashes": {
            "sha256": "WRgOrX+fgPECHrmEX1i6XmnghiYwe+4PGPv0Tjm2vpQ="
          },
          "sizeInBytes": 5902
        }
      ],
      "instructions": {
        "steps": [
          {
            "files": [
              "script_test.sh"
            ],
            "handler": "microsoft/script:1",
            "handlerProperties": {
              "arguments": "",
              "scriptFileName": "script_test.sh",
                        "installedCriteria": "1.0"
            },
            "type": "inline"
          }
        ]
      },
      "manifestVersion": "5.0",
      "updateId": {
        "name": "scriptupdate",
        "provider": "me",
        "version": "51.0.0"
      }
    }
    

    script_test.sh

    #!/bin/bash
    
    # Copyright (c) Microsoft Corporation.
    # Licensed under the MIT License.
    
    # Ensure that getopt starts from first option if ". <script.sh>" was used.
    OPTIND=1
    
    # Ensure we don't end the user's terminal session if invoked from source (".").
    if [[ $0 != "${BASH_SOURCE[0]}" ]]; then
        ret='return'
    else
        ret='exit'
    fi
    
    # Output formatting.
    
    # Log level: 0=debug, 1=info, 2=warning, 3=error, 4=none
    log_level=1
    
    warn() { echo -e "33[1;33mWarning:33[0m $*" >&2; }
    
    error() { echo -e "33[1;31mError:33[0m $*" >&2; }
    
    header() { echo -e "e[4me[1me[1;32m$*e[0m"; }
    
    bullet() { echo -e "e[1;34m*e[0m $*"; }
    
    # Log debug prefix - blue
    log_debug_pref="33[1;30m[D]33[0m"
    
    # Log info prefix - blue
    log_info_pref="33[1;34m[I]33[0m"
    
    # Log warning prefix - yellow
    log_warn_pref="33[1;33m[W]33[0m"
    
    # Log error prefix - red
    log_error_pref="33[1;31m[E]33[0m"
    
    #
    # Install poicy
    #
    #install_error_policy="abort"
    #install_reboot_policy="none"
    
    # component_props will contain a map of property.
    declare -A component_props
    
    #
    # Files and Folders information
    #
    workfolder=
    output_file=
    log_file=
    result_file=
    
    #
    # Device Update specific arguments
    #
    do_install_action=
    
    #
    # Remaining aguments and parameters
    #
    PARAMS=
    
    #
    # Output, Logs, and Result helper functions.
    #
    _timestamp=
    
    update_timestamp() {
        # See https://man7.org/linux/man-pages/man1/date.1.html
        _timestamp="$(date +'%Y/%m/%d:%H%M%S')"
    }
    
    log_debug() {
        if [ $log_level -gt 0 ]; then
            return
        fi
        log "$log_debug_pref" "$@"
    }
    
    log_info() {
        if [ $log_level -gt 1 ]; then
            return
        fi
        log "$log_info_pref" "$@"
    }
    
    log_warn() {
        if [ $log_level -gt 2 ]; then
            return
        fi
        log "$log_warn_pref" "$@"
    }
    
    log_error() {
        if [ $log_level -gt 3 ]; then
            return
        fi
        log "$log_error_pref" "$@"
    }
    
    log() {
        update_timestamp
        if [ -z "$log_file" ]; then
            echo -e "[$_timestamp]" "$@" >&1
        else
            echo "[$_timestamp]" "$@" >> "$log_file"
        fi
    }
    
    output() {
        update_timestamp
        if [ -z "$output_file" ]; then
            echo "[$_timestamp]" "$@" >&1
        else
            echo "[$_timestamp]" "$@" >> "$output_file"
        fi
    }
    
    #
    # Write result json string to result file.
    #
    result() {
        # NOTE: don't insert timestamp in result file.
        if [ -z "$result_file" ]; then
            echo "$@" >&1
        else
            echo "$@" > "$result_file"
        fi
    }
    
    log "Log begin:"
    output "Output begin:"
    
    #
    # Parsing arguments
    #
    while [[ $1 != "" ]]; do
        case $1 in
    
        #
        # Component-related arguments.
        #
        # Following arguments and parameters will be populated by the Script Step Handler.
        #
    
        #
        # Device Update specific arguments.
        #
        --action-install)
            shift
            log_info "Will runscript as 'installer' script."
            do_install_action=yes
            ;;
    
        #
        # Update artifacts
        #
    
        --work-folder)
            shift
            if [[ -z $1 || $1 == -* ]]; then
                error "--work-folder parameter is mandatory."
                $ret 1
            fi
            workfolder="$1"
            echo "Workfolder: $workfolder"
            shift
            ;;
    
        #
        # Output-related arguments.
        #
        # --out-file <file_path>, --result-file <file_path>, --log-file <file_path>
        #
        --output-file)
            shift
            if [[ -z $1 || $1 == -* ]]; then
                error "--out-file parameter is mandatory."
                $ret 1
            fi
            output_file="$1"
    
            #
            #Create output file path.
            #
            # Delete existing log.
            rm -f -r "$output_file"
            # Create dir(s) recursively (include filename, well remove it in the following line...).
            mkdir -p "$output_file"
            shift
            ;;
    
        --result-file)
            shift
            if [[ -z $1 || $1 == -* ]]; then
                error "--result-file parameter is mandatory."
                $ret 1
            fi
            result_file="$1"
            #
            #Create result file path.
            #
            # Delete existing log.
            rm -f -r "$result_file"
            # Create dir(s) recursively (include filename, well remove it in the following line...).
            touch "$result_file"
            shift
            ;;
    
        --log-file)
            shift
            if [[ -z $1 || $1 == -* ]]; then
                error "--log-file parameter is mandatory."
                $ret 1
            fi
            log_file="$1"
            shift
            ;;
        --log-level)
            shift
            if [[ -z $1 || $1 == -* ]]; then
                error "--log-level parameter is mandatory."
                $ret 1
            fi
            log_level=$1
            shift
            ;;
    
        -h | --help)
            print_help
            $ret 0
            ;;
    
        *) # preserve positional arguments
            PARAMS="$PARAMS $1"
            shift
            ;;
        esac
    done
    
    #
    # Main
    #
    
    resultCode=0
    extendedResultCode=1
    resultDetails=""
    
    # Update apt-get
    sudo apt-get update
    
    # Install cowsay
    sudo apt-get install cowsay
    
    # Create a directory
    mkdir -p /home/azureuser/this_was_create_by_adu
    
    # Create a text file with specified content inside the directory
    echo "this file was generated by adu on $(TZ='UTC-1' date '+%Y-%m-%d %H:%M:%S %Z')" > /home/azureuser/this_was_create_by_adu/generated_file.txt
    
    # Confirmation message
    if [ -d "/home/azureuser/this_was_create_by_adu" ] && [ -f "/home/azureuser/this_was_create_by_adu/generated_file.txt" ]; then
        log_info "Both directory and file exist."
        resultCode=600
        extendedResultCode=0
        resultDetails="folder and file created"
        ret_val=0
    else
        log_info "Either the directory or file does not exist."
        resultDetails="Folder and/or file have been not created"
        exit 1
    fi
    
    # Prepare ADUC_Result json.
    aduc_result_json="{"resultCode":$resultCode, "extendedResultCode":$extendedResultCode,"resultDetails":"$resultDetails"}"
    
    # Show output.
    output "Result:" "$aduc_result_json"
    
    # Write ADUC_Result to result file.
    
    result "$aduc_result_json"
    
    exit 0
    

  2. I tried your code and received the same error while running the updates. There is an issue with the C and script_test.sh code, so I tried an alternative method using PowerShell to update the device.

    I used this doc to help with the process.

    Below code is to the import manifest in a single payload file of contoso.toaster.1.0.importmanifest.json

    Import-Module ./AduUpdate.psm1
    $file = './README.md'
    $updateId = New-AduUpdateId -Provider Contoso -Name Toaster -Version 1.0
    $compat = New-AduUpdateCompatibility -Properties @{ manufacturer = 'Contoso'; model = 'Toaster' }
    $installStep = New-AduInstallationStep -Handler 'microsoft/swupdate:1'-HandlerProperties @{ installedCriteria = '1.0' } -Files $file
    $update = New-AduImportManifest -UpdateId $updateId -Compatibility $compat -InstallationSteps $installStep
    $update | Out-File ./contoso.toaster.1.0.importmanifest.json -Encoding utf8
    
    

    enter image description here

    This creates a contoso.toaster.1.0.importmanifest.json file. You can use the following bash command to update the device with a single payload file to be installed:

    ./create-adu-import-manifest.sh -p 'Contoso' -n 'Toaster' -v '1.0' -c 'manufacturer:Contoso' -c 'model:Toaster' -h 'microsoft/swupdate:1' -r 'installedCriteria:1.0' ./README.md > ./contoso.toaster.1.0.importmanifest.json
    
    

    enter image description here

    Next step is we need to create an Azure storage account and a container in Azure.

    Create a Device Update for IoT Hub, link the Azure IoT instances, and assign the IoT Hub Data Contributor role to IoT.

    Go to IoT >> Updates and click on "Import New Update."

    enter image description here

    For the above image select the storage and container, then upload the files contoso.toaster.1.0.importmanifest.json and README.txt as shown below:

    enter image description here

    After some time, check the updates:

    enter image description here

    Upadated:

    For using microsoft/script:1 :

    ./create-adu-import-manifest.sh 
      -p 'Contoso' 
      -n 'Toaster' 
      -v '1.0' 
      -c 'manufacturer:Contoso' 
      -c 'model:Toaster' 
      -h 'microsoft/script:1' 
      -r 'installedCriteria:1.0' 
      ./README.md > ./contoso.toaster.1.0.importmanifest.json
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search