“阿里云的OpenAPI”的版本间的差异
第1行: | 第1行: | ||
− | # | + | |
+ | #!/usr/bin/env python | ||
+ | # coding=utf-8 | ||
+ | import json | ||
+ | import time | ||
+ | import traceback | ||
+ | from multiprocessing.pool import ThreadPool | ||
+ | |||
+ | from aliyunsdkcore.client import AcsClient | ||
+ | from aliyunsdkcore.acs_exception.exceptions import ClientException, ServerException | ||
+ | from aliyunsdkecs.request.v20140526.RenewInstanceRequest import RenewInstanceRequest | ||
+ | from aliyunsdkecs.request.v20140526.DescribeInstancesRequest import DescribeInstancesRequest | ||
+ | |||
+ | |||
+ | RUNNING_STATUS = 'Running' | ||
+ | CHECK_INTERVAL = 2 | ||
+ | CHECK_TIMEOUT = 60 | ||
+ | |||
+ | |||
+ | class InvalidInstanceId(Exception): | ||
+ | pass | ||
+ | |||
+ | |||
+ | class AliyunRenewInstancesExample(object): | ||
+ | |||
+ | def __init__(self): | ||
+ | self.access_id = '<ACCESS_KEY_ID>' | ||
+ | self.access_secret = '<ACCESS_SECRET>' | ||
+ | # 实例所属的地域ID | ||
+ | self.region_id = 'cn-hangzhou' | ||
+ | # 指定的需要续费的实例 ID | ||
+ | self.instance_ids = ['i-23if47pnv'] | ||
+ | # 预付费续费时长 | ||
+ | self.period = 1 | ||
+ | # 续费时长单位,取值:Week/Month | ||
+ | self.period_unit = 'Month' | ||
+ | |||
+ | self.instance_charge_type = 'PrePaid' | ||
+ | # "ecs.api.generator.renew_expire_time" | ||
+ | self.expired_start_time = 'ExpiredStartTime' | ||
+ | self.expired_end_time = 'ExpiredEndTime' | ||
+ | # "ecs.api.generator.renew_page_size" | ||
+ | self.page_size = 100 | ||
+ | |||
+ | self.client = AcsClient(self.access_id, self.access_secret, self.region_id) | ||
+ | self.pool = ThreadPool(100) | ||
+ | |||
+ | def run(self): | ||
+ | try: | ||
+ | self.renew_instances() | ||
+ | except ClientException as e: | ||
+ | print('Fail. Something with your connection with Aliyun go incorrect.' | ||
+ | ' Code: {code}, Message: {msg}' | ||
+ | .format(code=e.error_code, msg=e.message)) | ||
+ | except ServerException as e: | ||
+ | print('Fail. Business error.' | ||
+ | ' Code: {code}, Message: {msg}' | ||
+ | .format(code=e.error_code, msg=e.message)) | ||
+ | except InvalidInstanceId as e: | ||
+ | print(e) | ||
+ | except Exception: | ||
+ | print('Unhandled error') | ||
+ | print(traceback.format_exc()) | ||
+ | |||
+ | def renew_instances(self): | ||
+ | """ | ||
+ | 批量续费实例,若需查询需要续费的实例,可查看 get_renew_instances 方法 | ||
+ | :return: | ||
+ | """ | ||
+ | # self.instance_ids = self.get_renew_instances() | ||
+ | instances = self.describe_instances() | ||
+ | # 更新实例过期时间 | ||
+ | original_expired_time = {} | ||
+ | for instance in instances: | ||
+ | original_expired_time[instance['InstanceId']] = instance['ExpiredTime'] | ||
+ | # 通过多线程的方式进行批量续费 | ||
+ | self.pool.map(self.renew_instance, self.instance_ids) | ||
+ | self.pool.close() | ||
+ | self.pool.join() | ||
+ | # 检查续费是否成功 | ||
+ | self._check_instances_expired_time(original_expired_time) | ||
+ | |||
+ | def renew_instance(self, instance_id): | ||
+ | """ | ||
+ | 续费单个实例 | ||
+ | :param instance_id: 实例ID | ||
+ | :return: | ||
+ | """ | ||
+ | request = RenewInstanceRequest() | ||
+ | request.set_InstanceId(instance_id) | ||
+ | request.set_Period(self.period) | ||
+ | request.set_PeriodUnit(self.period_unit) | ||
+ | # 发送请求 | ||
+ | self.client.do_action_with_exception(request) | ||
+ | |||
+ | def get_renew_instance_ids(self): | ||
+ | """ | ||
+ | 获取需要续费的实例ID | ||
+ | :param instance_id: 实例ID列表 | ||
+ | :return: | ||
+ | """ | ||
+ | start_time_utc = '2018-10-21T16:00Z' | ||
+ | end_time_utc = '2018-12-01T16:00Z' | ||
+ | page_num = 1 | ||
+ | total_count = 1 | ||
+ | instance_ids = [] | ||
+ | while len(instance_ids) < total_count: | ||
+ | request = DescribeInstancesRequest() | ||
+ | request.set_Filter3Key(self.expired_start_time) | ||
+ | request.set_Filter3Value(start_time_utc) | ||
+ | request.set_Filter4Key(self.expired_end_time) | ||
+ | request.set_Filter4Value(end_time_utc) | ||
+ | request.set_InstanceChargeType(self.instance_charge_type) | ||
+ | request.set_PageSize(self.page_size) | ||
+ | request.set_PageNumber(page_num) | ||
+ | body = self.client.do_action_with_exception(request) | ||
+ | data = json.loads(body) | ||
+ | |||
+ | if not data['TotalCount']: | ||
+ | return instance_ids | ||
+ | |||
+ | ids = [str(instance['InstanceId']) for instance in data['Instances']['Instance']] | ||
+ | instance_ids.extend(ids) | ||
+ | total_count = data['TotalCount'] | ||
+ | page_num += 1 | ||
+ | print('Success. Instances which should be renewed include: {}'.format(', '.join(instance_ids))) | ||
+ | return instance_ids | ||
+ | |||
+ | def describe_instances(self): | ||
+ | """ | ||
+ | 获取实例信息 | ||
+ | :return: 实例信息列表 | ||
+ | """ | ||
+ | offset = 0 | ||
+ | total_count = len(self.instance_ids) | ||
+ | instances = [] | ||
+ | while offset < total_count: | ||
+ | ids = self.instance_ids[offset:min(offset+self.page_size, total_count)] | ||
+ | request = DescribeInstancesRequest() | ||
+ | request.set_PageSize(self.page_size) | ||
+ | request.set_InstanceChargeType(self.instance_charge_type) | ||
+ | request.set_InstanceIds(ids) | ||
+ | body = self.client.do_action_with_exception(request) | ||
+ | data = json.loads(body) | ||
+ | ins = data['Instances']['Instance'] | ||
+ | ret_instance_ids = [instance['InstanceId'] for instance in ins] | ||
+ | invalid_instance_ids = set(ids) - set(ret_instance_ids) | ||
+ | if invalid_instance_ids: | ||
+ | raise InvalidInstanceId('Fail. Invalid InstanceIds: {}' | ||
+ | .format(', '.join(invalid_instance_ids))) | ||
+ | instances.extend(ins) | ||
+ | offset += self.page_size | ||
+ | return instances | ||
+ | |||
+ | def _check_instances_expired_time(self, original_expired_time): | ||
+ | """ | ||
+ | 每2秒中检查一次实例的到期时间,超时时间设为1分钟 | ||
+ | :param original_expired_time: 记录实例ID和原始过期时间的映射关系的字典。 | ||
+ | :return: | ||
+ | """ | ||
+ | start = time.time() | ||
+ | while True: | ||
+ | all_completed = True | ||
+ | uncompleted_instance_ids = [] | ||
+ | instances = self.describe_instances() | ||
+ | for instance in instances: | ||
+ | if instance['ExpiredTime'] == original_expired_time[instance['InstanceId']]: | ||
+ | uncompleted_instance_ids.append(instance['InstanceId']) | ||
+ | all_completed = False | ||
+ | |||
+ | if all_completed: | ||
+ | print('Instances renew successfully') | ||
+ | break | ||
+ | |||
+ | if time.time() - start > CHECK_TIMEOUT: | ||
+ | print('Check instance expired time timeout. ' | ||
+ | 'Following instances still not renewed successfully: {}' | ||
+ | .format(', '.join(uncompleted_instance_ids))) | ||
+ | break | ||
+ | |||
+ | time.sleep(CHECK_INTERVAL) | ||
+ | return all_completed | ||
+ | |||
+ | |||
+ | if __name__ == '__main__': | ||
+ | AliyunRenewInstancesExample().run() |
2023年3月27日 (一) 11:32的版本
#!/usr/bin/env python # coding=utf-8 import json import time import traceback from multiprocessing.pool import ThreadPool from aliyunsdkcore.client import AcsClient from aliyunsdkcore.acs_exception.exceptions import ClientException, ServerException from aliyunsdkecs.request.v20140526.RenewInstanceRequest import RenewInstanceRequest from aliyunsdkecs.request.v20140526.DescribeInstancesRequest import DescribeInstancesRequest RUNNING_STATUS = 'Running' CHECK_INTERVAL = 2 CHECK_TIMEOUT = 60 class InvalidInstanceId(Exception): pass class AliyunRenewInstancesExample(object): def __init__(self): self.access_id = '<ACCESS_KEY_ID>' self.access_secret = '<ACCESS_SECRET>' # 实例所属的地域ID self.region_id = 'cn-hangzhou' # 指定的需要续费的实例 ID self.instance_ids = ['i-23if47pnv'] # 预付费续费时长 self.period = 1 # 续费时长单位,取值:Week/Month self.period_unit = 'Month' self.instance_charge_type = 'PrePaid' # "ecs.api.generator.renew_expire_time" self.expired_start_time = 'ExpiredStartTime' self.expired_end_time = 'ExpiredEndTime' # "ecs.api.generator.renew_page_size" self.page_size = 100
self.client = AcsClient(self.access_id, self.access_secret, self.region_id) self.pool = ThreadPool(100) def run(self): try: self.renew_instances() except ClientException as e: print('Fail. Something with your connection with Aliyun go incorrect.' ' Code: {code}, Message: {msg}' .format(code=e.error_code, msg=e.message)) except ServerException as e: print('Fail. Business error.' ' Code: {code}, Message: {msg}' .format(code=e.error_code, msg=e.message)) except InvalidInstanceId as e: print(e) except Exception: print('Unhandled error') print(traceback.format_exc()) def renew_instances(self): """ 批量续费实例,若需查询需要续费的实例,可查看 get_renew_instances 方法 :return: """ # self.instance_ids = self.get_renew_instances() instances = self.describe_instances() # 更新实例过期时间 original_expired_time = {} for instance in instances: original_expired_time[instance['InstanceId']] = instance['ExpiredTime'] # 通过多线程的方式进行批量续费 self.pool.map(self.renew_instance, self.instance_ids) self.pool.close() self.pool.join() # 检查续费是否成功 self._check_instances_expired_time(original_expired_time)
def renew_instance(self, instance_id): """ 续费单个实例 :param instance_id: 实例ID :return: """ request = RenewInstanceRequest() request.set_InstanceId(instance_id) request.set_Period(self.period) request.set_PeriodUnit(self.period_unit) # 发送请求 self.client.do_action_with_exception(request) def get_renew_instance_ids(self): """ 获取需要续费的实例ID :param instance_id: 实例ID列表 :return: """ start_time_utc = '2018-10-21T16:00Z' end_time_utc = '2018-12-01T16:00Z' page_num = 1 total_count = 1 instance_ids = [] while len(instance_ids) < total_count: request = DescribeInstancesRequest() request.set_Filter3Key(self.expired_start_time) request.set_Filter3Value(start_time_utc) request.set_Filter4Key(self.expired_end_time) request.set_Filter4Value(end_time_utc) request.set_InstanceChargeType(self.instance_charge_type) request.set_PageSize(self.page_size) request.set_PageNumber(page_num) body = self.client.do_action_with_exception(request) data = json.loads(body) if not data['TotalCount']: return instance_ids ids = [str(instance['InstanceId']) for instance in data['Instances']['Instance']] instance_ids.extend(ids) total_count = data['TotalCount'] page_num += 1 print('Success. Instances which should be renewed include: {}'.format(', '.join(instance_ids))) return instance_ids def describe_instances(self): """ 获取实例信息 :return: 实例信息列表 """ offset = 0 total_count = len(self.instance_ids) instances = [] while offset < total_count: ids = self.instance_ids[offset:min(offset+self.page_size, total_count)] request = DescribeInstancesRequest() request.set_PageSize(self.page_size) request.set_InstanceChargeType(self.instance_charge_type) request.set_InstanceIds(ids) body = self.client.do_action_with_exception(request) data = json.loads(body) ins = data['Instances']['Instance'] ret_instance_ids = [instance['InstanceId'] for instance in ins] invalid_instance_ids = set(ids) - set(ret_instance_ids) if invalid_instance_ids: raise InvalidInstanceId('Fail. Invalid InstanceIds: {}' .format(', '.join(invalid_instance_ids))) instances.extend(ins) offset += self.page_size return instances def _check_instances_expired_time(self, original_expired_time): """ 每2秒中检查一次实例的到期时间,超时时间设为1分钟 :param original_expired_time: 记录实例ID和原始过期时间的映射关系的字典。 :return: """ start = time.time() while True: all_completed = True uncompleted_instance_ids = [] instances = self.describe_instances() for instance in instances: if instance['ExpiredTime'] == original_expired_time[instance['InstanceId']]: uncompleted_instance_ids.append(instance['InstanceId']) all_completed = False if all_completed: print('Instances renew successfully') break if time.time() - start > CHECK_TIMEOUT: print('Check instance expired time timeout. ' 'Following instances still not renewed successfully: {}' .format(', '.join(uncompleted_instance_ids))) break time.sleep(CHECK_INTERVAL) return all_completed if __name__ == '__main__': AliyunRenewInstancesExample().run()