You can renew an ECS instance in the ECS console or on the instance buy page. You can also call an API operation provided by Alibaba Cloud to renew an ECS instance or query the expiration time of the instance.

Background information

The lifecycle is important to subscription ECS instances. If you fail to renew an ECS instance in a timely manner, the instance may be locked or even released. This can affect your service continuity. You can use API operations to query the expiration time of the ECS instance, and renew your instance.

This topic provides the sample code to show how to renew an ECS instance and also the explanation of the sample code. For more information, see the following topics:

Sample code

#  coding=utf-8
# if the python sdk is not install using 'sudo pip install aliyun-python-sdk-ecs'
# if the python sdk is install using 'sudo pip install --upgrade aliyun-python-sdk-ecs'
# make sure the sdk version is 4.4.3, you can use command 'pip show aliyun-python-sdk-ecs' to check

import json
import logging
from aliyunsdkcore import client
from aliyunsdkecs.request.v20140526.DescribeInstanceAutoRenewAttributeRequest import \
    DescribeInstanceAutoRenewAttributeRequest
from aliyunsdkecs.request.v20140526.DescribeInstancesRequest import DescribeInstancesRequest
from aliyunsdkecs.request.v20140526.ModifyInstanceAutoRenewAttributeRequest import \
    ModifyInstanceAutoRenewAttributeRequest
from aliyunsdkecs.request.v20140526.RenewInstanceRequest import RenewInstanceRequest

logging.basicConfig(level=logging.INFO, format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', datefmt='%a, %d %b %Y %H:%M:%S')
clt = client.AcsClient('<accessKeyId>', '<accessSecret>', '<region-Id>')

INSTANCE_EXPIRED_START_TIME_IN_UTC_STRING = '2017-01-22T00:00Z'
INSTANCE_EXPIRE_END_TIME_IN_UTC_STRING = '2017-01-28T00:00Z'
def renew_job(page_size=100, page_number=1, check_need_renew=True, security_group_id=None):
    response = describe_need_renew_instance(page_size=page_size, page_number=page_number, check_need_renew=check_need_renew, security_group_id=security_group_id)
    response_list = response.get('Instances').get('Instance')
    logging.info("%s instances need to renew", str(response.get('TotalCount')))
    if response_list > 0:
        instance_ids = ''
        for item in response_list:
            instance_id = item.get('InstanceId')
            instance_ids += instance_id + ','
            renew_instance(instance_id=instance_id)
        logging.info("%s execute renew action ready", instance_ids)

def describe_need_renew_instance(page_size=100, page_number=1, instance_id=None, check_need_renew=True, security_group_id=None):
    request = DescribeInstancesRequest()
    if check_need_renew is True:
        request.set_Filter3Key("ExpiredStartTime")
        request.set_Filter3Value(INSTANCE_EXPIRED_START_TIME_IN_UTC_STRING)
        request.set_Filter4Key("ExpiredEndTime")
        request.set_Filter4Value(INSTANCE_EXPIRE_END_TIME_IN_UTC_STRING)
    if instance_id is not None:
        request.set_InstanceIds(json.dumps([instance_id]))
    if security_group_id:
        request.set_SecurityGroupId(security_group_id)
    request.set_PageNumber(page_number)
    request.set_PageSize(page_size)
    return _send_request(request)

def describe_instance_auto_renew_setting(instance_ids, expected_auto_renew=True):
    describe_request = DescribeInstanceAutoRenewAttributeRequest()
    describe_request.set_InstanceId(instance_ids)
    response_detail = _send_request(request=describe_request)
    failed_instance_ids = ''
    if response_detail is not None:
        attributes = response_detail.get('InstanceRenewAttributes').get('InstanceRenewAttribute')
        if attributes:
            for item in attributes:
                auto_renew_status = item.get('AutoRenewEnabled')
                if auto_renew_status != expected_auto_renew:
                    failed_instance_ids += item.get('InstanceId') + ','
    if len(failed_instance_ids) > 0:
        logging.error("instance %s auto renew not match expect %s.", failed_instance_ids,
                      expected_auto_renew)

def setting_instance_auto_renew(instance_ids, auto_renew=True):
    logging.info('execute enable auto renew ' + instance_ids)
    request = ModifyInstanceAutoRenewAttributeRequest();
    request.set_Duration(1);
    request.set_AutoRenew(auto_renew);
    request.set_InstanceId(instance_ids)
    _send_request(request)
    describe_instance_auto_renew_setting(instance_ids, auto_renew)

def check_instance_need_renew(instance_id):
    response = describe_need_renew_instance(instance_id=instance_id)
    if response is not None:
        return response.get('TotalCount') == 1
    return False

def renew_instance(instance_id, period='1'):
    need_renew = check_instance_need_renew(instance_id)
    if need_renew:
        _renew_instance_action(instance_id, period)
        # describe_need_renew_instance(instance_id=instance_id, check_need_renew=False)

def _renew_instance_action(instance_id, period='1'):
    request = RenewInstanceRequest()
    request.set_Period(period)
    request.set_InstanceId(instance_id)
    response = _send_request(request)
    logging.info('renew %s ready, output is %s ', instance_id, response)

def _send_request(request):
    request.set_accept_format('json')
    try:
        response_str = clt.do_action(request)
        logging.info(response_str)
        response_detail = json.loads(response_str)
        return response_detail
    except Exception as e:
        logging.error(e)

if __name__ == '__main__':
    logging.info("Renew ECS Instance by OpenApi!")
    # Query instances that will expire within the specified time range.
    describe_need_renew_instance()
    # Renew the instances and renewal fees are automatically deducted.
    # renew_instance('i-bp1aet7s13lfpjop****')
    # Query the auto-renewal status of the instances.
    # describe_instance_auto_renew_setting('i-bp1aet7s13lfpjop****,i-bp13uh1twnfv7vp8****')
    # Set auto-renewal for the instances.
    # setting_instance_auto_renew('i-bp1aet7s13lfpjop****,i-bp13uh1twnfv7vp8****')

Query instances that will expire within the specified time range

You can call the DescribeInstances operation to query instances that will expire within the time range specified by the ExpiredStartTime and ExpiredEndTime parameters. Specify the time in the ISO 8601 standard in the yyyy-MM-ddTHH:mm:ssZ format. The time must be in UTC. If you want to filter instances by security group, add the ID of the security group.

INSTANCE_EXPIRED_START_TIME_IN_UTC_STRING = '2017-01-22T00:00Z'
INSTANCE_EXPIRE_END_TIME_IN_UTC_STRING = '2017-01-28T00:00Z'

def renew_job(page_size=100, page_number=1, check_need_renew=True, security_group_id=None):
    response = describe_need_renew_instance(page_size=page_size, page_number=page_number, check_need_renew=check_need_renew, security_group_id=security_group_id)
    response_list = response.get('Instances').get('Instance')
    logging.info("%s instances need to renew", str(response.get('TotalCount')))
    if response_list > 0:
        instance_ids = ''
        for item in response_list:
            instance_id = item.get('InstanceId')
            instance_ids += instance_id + ','
            renew_instance(instance_id=instance_id)
        logging.info("%s execute renew action ready", instance_ids)

Renew an ECS instance

You can renew only subscription ECS instances. Pay-as-you-go instances cannot be renewed. You can pay the renewal fee by account balance or credit. Fee deduction and order creation are in sync with API calling. Ensure that your account has sufficient funds to support automatic deduction of fees.

def _renew_instance_action(instance_id, period='1'):
    request = RenewInstanceRequest()
    request.set_Period(period)
    request.set_InstanceId(instance_id)
    response = _send_request(request)
    logging.info('renew %s ready, output is %s ', instance_id, response)

Fees are automatically deducted when the instance is renewed. After the renewal is complete, you can query the expiration time of the instance based on InstanceId. The expiration time may be updated in 10 seconds because the API operation is called asynchronously.

Enable auto-renewal for ECS instances

Alibaba Cloud provides auto-renewal for subscription ECS instances to help you reduce maintenance costs. Fees are automatically deducted at 08:00:00 nine days before the expiration date. If fee deduction fails on the first day, the deduction process will repeat on the following days until fees are deducted or resources are locked after nine days. You must make sure that your account has sufficient balance or credit.

  • Query the auto-renewal status

    You can use an API operation to query and set the auto-renewal status. The API operation supports only subscription ECS instances. If you use the API operation on pay-as-you-go instances, an error is returned. You can query the auto-renewal status of up to 100 subscription ECS instances at a time. Separate multiple instance IDs with commas.

    The input parameter of DescribeInstanceAutoRenewAttribute is the instance ID.

    InstanceId: the IDs of instances. You can specify up to 100 subscription instance IDs at a time. Separate multiple instance IDs with commas.

    def describe_instance_auto_renew_setting(instance_ids, expected_auto_renew=True):
        describe_request = DescribeInstanceAutoRenewAttributeRequest()
        describe_request.set_InstanceId(instance_ids)
        response_detail = _send_request(request=describe_request)
        failed_instance_ids = ''
        if response_detail is not None:
            attributes = response_detail.get('InstanceRenewAttributes').get('InstanceRenewAttribute')
            if attributes:
                for item in attributes:
                    auto_renew_status = item.get('AutoRenewEnabled')
                    if auto_renew_status != expected_auto_renew:
                        failed_instance_ids += item.get('InstanceId') + ','
    
    describe_instance_auto_renew_setting('i-bp1aet7s13lfpjop****,i-bp13uh1twnfv7vp8****')
    Sample responses:
    {"InstanceRenewAttributes":{"InstanceRenewAttribute":[{"Duration":0,"InstanceId":"i-1111","AutoRenewEnabled":false},{"Duration":0,"InstanceId":"i-2222","AutoRenewEnabled":false}]},"RequestId":"71FBB7A5-C793-4A0D-B17E-D6Bxxxxxxxxx"}

    If auto-renewal is set, the returned attribute of AutoRenewEnabled is true. Otherwise, the returned attribute is false.

  • Enable and disable auto-renewal for ECS instances

    You must set the following input parameters to enable auto-renewal:

    • InstanceId: the IDs of instances. You can specify up to 100 subscription instance IDs at a time. Separate multiple instance IDs with commas.
    • Duration: the duration of ECS instances. Valid values: 1, 2, 3, 6, and 12. Unit: months.
    • AutoRenew: specifies whether to enable the auto-renewal feature. Valid values: true and false. Set the value to true to enable auto-renewal. Set the value to false to disable auto-renewal.
    def setting_instance_auto_renew(instance_ids, auto_renew = True):
        logging.info('execute enable auto renew ' + instance_ids)
        request = ModifyInstanceAutoRenewAttributeRequest();
        request.set_Duration(1);
        request.set_AutoRenew(auto_renew);
        request.set_InstanceId(instance_ids)
        _send_request(request)
    If the operation is successful, the following response is returned:
    {"RequestId":"7DAC9984-AAB4-43EF-8FC7-7D7xxxxxxxxx"}

    After auto-renewal is enabled, you can query the auto-renewal status again. The system returns the auto-renewal duration and status in the following code:

    {"InstanceRenewAttributes":{"InstanceRenewAttribute":[{"Duration":1,"InstanceId":"i-1111","AutoRenewEnabled":true},{"Duration":1,"InstanceId":"i-2222","AutoRenewEnabled":true}]},"RequestId":"7F4D14B0-D0D2-48C7-B310-B1DF713D4331"}