You can use Cloud Assistant to simultaneously run a command on multiple Elastic Compute Service (ECS) instances. The command can be a shell, batch, or PowerShell command. You can use SSH or Remote Desktop Protocol (RDP) to log on to ECS instances and perform O&M. Cloud Assistant allows you to perform O&M on ECS instances without logging on to the instances. This topic describes how to use Cloud Assistant to manage ECS instances in a Python development environment.

Prerequisites

  • The Cloud Assistant Agent is installed on the ECS instances that you want to manage. For more information, see Install the Cloud Assistant Agent.
  • The aliyun-python-sdk-ecs SDK dependency in Python is updated to V2.1.2 or later. For more information about the latest versions, visit GitHub Repo Alibaba Cloud.

Procedure

  1. Compile the shell, batch, or PowerShell command based on the instance configurations and the operations that you want to perform.
  2. Find the instances that meet the specified requirements.
    The instances must be in the running state. For more information about how to use ECS SDK for Python to query instances, see Query an ECS instance.
  3. Obtain the AccessKey pair of your account and query the region ID.
    For more information, see Regions and zones and Obtain an AccessKey pair.
  4. Run a Cloud Assistant command on one or more ECS instances.
    Sample code:
    # coding=utf-8
    # If the Python sdk is not installed, run 'sudo pip install aliyun-python-sdk-ecs'.
    # Make sure you're using the latest sdk version.
    # Run 'sudo pip install --upgrade aliyun-python-sdk-ecs' to upgrade.
    
    from aliyunsdkcore.client import AcsClient
    from aliyunsdkcore.acs_exception.exceptions import ClientException
    from aliyunsdkcore.acs_exception.exceptions import ServerException
    from aliyunsdkecs.request.v20140526.RunCommandRequest import RunCommandRequest
    from aliyunsdkecs.request.v20140526.DescribeInvocationResultsRequest import DescribeInvocationResultsRequest
    import json
    import sys
    import base64
    import time
    import logging
    
    # Configure the log output formatter
    logging.basicConfig(level=logging.INFO,
                        format="%(asctime)s %(name)s [%(levelname)s]: %(message)s",
                        datefmt='%m-%d %H:%M')
    
    logger = logging.getLogger()
    
    access_key = '<yourAccessKey ID>'             # Enter your AccessKey ID.
    access_key_secret = '<yourAccessKey Secret>'  # Enter your AccessKey secret.
    region_id = '<yourRegionId>'                  # Enter your region ID.
    
    
    
    
    client = AcsClient(access_key, access_key_secret, region_id)
    
    def base64_decode(content, code='utf-8'):
        if sys.version_info.major == 2:
            return base64.b64decode(content)
        else:
            return base64.b64decode(content).decode(code)
    
    
    def get_invoke_result(invoke_id):
        request = DescribeInvocationResultsRequest()
        request.set_accept_format('json')
    
        request.set_InvokeId(invoke_id)
        response = client.do_action_with_exception(request)
        response_detail = json.loads(response)["Invocation"]["InvocationResults"]["InvocationResult"][0]
        status = response_detail.get("InvocationStatus","")
        output = base64_decode(response_detail.get("Output",""))
        return status,output
    
    
    def run_command(cmdtype,cmdcontent,instance_id,timeout=60):
        """
        cmdtype: The command type. Valid values: RunBatScript, RunPowerShellScript, or RunShellScript.
        cmdcontent: The command content.
        instance_id: The instance ID.
        """
        try:
            request = RunCommandRequest()
            request.set_accept_format('json')
    
            request.set_Type(cmdtype)
            request.set_CommandContent(cmdcontent)
            request.set_InstanceIds([instance_id])
            # Specify the timeout period for running the command. Unit: seconds. The default value is 60. Specify this parameter based on the actual command.
            request.set_Timeout(timeout)
            response = client.do_action_with_exception(request)
            invoke_id = json.loads(response).get("InvokeId")
            return invoke_id
        except Exception as e:
            logger.error("run command failed")
    
    
    
    def wait_invoke_finished_get_out(invoke_id,wait_count,wait_interval):
        for i in range(wait_count):
            status,output = get_invoke_result(invoke_id)
            if status not in ["Running","Pending","Stopping"]:
                return status,output
            time.sleep(wait_interval)
    
        logger.error("after wait %d times, still can not wait invoke-id %s finished")
        return "",""
    
    
    
    def run_task():
        # Specify the type of the Cloud Assistant command.
        cmdtype = "RunShellScript"
        # Specify the content of the Cloud Assistant command.
        cmdcontent = """
        #!/bin/bash
        yum check-update
        """
        # Specify the timeout period.
        timeout = 60
        # Specify the ID of your instance.
        ins_id = "i-wz9bsqk9pa0d2oge****" 
        # Run the command.
        invoke_id = run_command(cmdtype,cmdcontent,ins_id,timeout)
        logger.info("run command,invoke-id:%s" % invoke_id)
    
        # Wait for the command to be run. Query the command running state 10 times at an interval of 5 seconds. Specify the query times and the interval based on your actual requirements.
        status,output = wait_invoke_finished_get_out(invoke_id,10,5)
        if status:
            logger.info("invoke-id execute finished,status: %s,output:%s" %(status,output))
    
    
    if __name__ == '__main__':
        run_task()