全部產品
Search
文件中心

:續約ECS執行個體

更新時間:Jun 19, 2024

除了通過ECS控制台或售賣頁進行雲端服務器續約外,阿里雲還支援直接通過API進行續約查詢和續約管理。

背景資訊

對於訂用帳戶的雲端服務器,生命週期非常重要。如果雲端服務器資源不能按時續約,將可能導致伺服器被鎖定甚至被釋放,從而影響業務持久性。API協助您及時瞭解和檢查資源的到期時間,並完成續約儲值功能。

本文提供了完整程式碼範例,並提供了程式碼範例解析,請參見:

完整代碼

#  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
import os
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

# 請確保代碼運行環境設定了環境變數 ALIBABA_CLOUD_ACCESS_KEY_ID 和 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
# 工程代碼泄露可能會導致 AccessKey 泄露,並威脅帳號下所有資源的安全性。以下程式碼範例使用環境變數擷取 AccessKey 的方式進行調用,僅供參考,建議使用更安全的 STS 方式
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(os.environ['ALIBABA_CLOUD_ACCESS_KEY_ID'], os.environ['ALIBABA_CLOUD_ACCESS_KEY_SECRET'], '<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!")
    # 查詢在指定的時間範圍內是否有需要續約的執行個體。
    describe_need_renew_instance()
    # 續約執行個體, 直接執行費用扣除。
    # renew_instance('i-bp1aet7s13lfpjop****')
    # 查詢執行個體自動續約的狀態。
    # describe_instance_auto_renew_setting('i-bp1aet7s13lfpjop****,i-bp13uh1twnfv7vp8****')
    # 設定執行個體自動續約。
    # setting_instance_auto_renew('i-bp1aet7s13lfpjop****,i-bp13uh1twnfv7vp8****')

查詢指定範圍內到期的雲端服務器

查詢執行個體列表的API,通過過濾參數,您可以查詢一定時間範圍內到期的執行個體資訊。通過設定過濾參數ExpiredStartTimeExpiredEndTime(時間參數按照ISO8601標準表示,並需要使用UTC時間。 格式為:yyyy-MM-ddTHH:mmZ) ,可以方便地查詢該時間範圍內到期的執行個體列表。如果需要通過安全性群組進行過濾,只需加上安全性群組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)

續約雲端服務器

續約執行個體只支援訂用帳戶的伺服器類型,不支援隨用隨付的伺服器,同時要求使用者必須支援帳號的餘額支付或信用支付。執行API的時候將執行同步的計費和訂單產生。因此,執行API的時候必須保證您的帳號有足夠的資金支援自動計費。

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)

續約執行個體將會自動完成計費。在完成續約後,您可以根據InstanceId查詢執行個體的資源到期時間。由於API為非同步任務,查詢資源到期時間可能需要延遲10秒才會變化。

開啟雲端服務器自動續約

為了減少您的資源到期維護成本,針對訂用帳戶的ECS執行個體,阿里雲還推出了自動續約功能。 自動續約扣款日為伺服器到期前第9天的08:00:00。如果前一日執行自動計費失敗,將會繼續下一日定時執行,直到完成計費或者9天后到期資源鎖定。您只需要保證自己的帳號餘額或者信用額度充足即可。

  • 查詢自動續約設定

    您可以通過OpenAPI來查詢和設定自動續約。該API僅支援訂用帳戶的執行個體,隨用隨付的執行個體執行將會報錯。查詢執行個體的自動續約狀態支援一次最多查詢100個訂用帳戶的執行個體,多個執行個體ID以逗號串連。

    DescribeInstanceAutoRenewAttribute的入參為執行個體ID。

    InstanceId:支援最多查詢100個訂用帳戶的執行個體,多個執行個體ID以逗號串連。

    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****')

    返回樣本如下:

    {"InstanceRenewAttributes":{"InstanceRenewAttribute":[{"Duration":0,"InstanceId":"i-1111","AutoRenewEnabled":false},{"Duration":0,"InstanceId":"i-2222","AutoRenewEnabled":false}]},"RequestId":"71FBB7A5-C793-4A0D-B17E-D6Bxxxxxxxxx"}

    如果設定自動續約,則返回的屬性AutoRenewEnabledtrue,否則返回false

  • 設定和取消雲端服務器的自動續約

    設定自動續約有三個入參:

    • InstanceId:支援最多查詢100個訂用帳戶的執行個體,多個執行個體ID以逗號串連。

    • Duration:支援1、2、3、6、12,單位為月。

    • AutoRenewtrue/falsetrue為開啟自動續約,false為取消自動續約。

    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)

    執行成功返回Response如下:

    {"RequestId":"7DAC9984-AAB4-43EF-8FC7-7D7xxxxxxxxx"}

    續約成功後,您可以再執行一次查詢。如果續約成功將返回續約時間長度以及是否開啟自動續約。

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