本文介绍如何使用函数计算控制台编写函数,以实现ECS重启后,函数自动查找出ECS挂接的云盘,并给云盘自动创建快照。

前提条件

  1. 创建服务
  2. 创建函数

编写函数代码

  1. 登录函数计算控制台
  2. 在顶部菜单栏,选择地域。
  3. 在左侧导航栏,单击服务/函数
  4. 找到目标服务下的目标函数,单击函数名称。
  5. 单击代码执行页签,在代码编辑器中编写代码。

    本文以Python为例,示例代码如下。

    # -*- coding: utf-8 -*-
    import logging
    import json, random, string, time
    from aliyunsdkcore import client
    from aliyunsdkecs.request.v20140526.DeleteSnapshotRequest import DeleteSnapshotRequest
    from aliyunsdkecs.request.v20140526.CreateSnapshotRequest import CreateSnapshotRequest
    from aliyunsdkecs.request.v20140526.DescribeDisksRequest import DescribeDisksRequest
    from aliyunsdkcore.auth.credentials import StsTokenCredential
    
    LOGGER = logging.getLogger()
    clt = None
    
    def handler(event, context):
      creds = context.credentials
      sts_token_credential = StsTokenCredential(creds.access_key_id, creds.access_key_secret, creds.security_token)
      '''
      {
        "product": "ECS",
        "content": {
            "executeFinishTime": "2018-06-08T01:25:37Z",
            "executeStartTime": "2018-06-08T01:23:37Z",
            "ecsInstanceName": "timewarp",
            "eventId": "e-t4nhcpqcu8fqushpn3mm",
            "eventType": "InstanceFailure.Reboot",
            "ecsInstanceId": "i-bp18l0uopocfc98xxxx" 
        },
        "resourceId": "acs:ecs:cn-hangzhou:12345678:instance/i-bp18l0uopocfc98xxxx",
        "level": "CRITICAL",
        "instanceName": "instanceName",
        "status": "Executing",
        "name": "Instance:SystemFailure.Reboot:Executing", 
        "regionId": "cn-hangzhou"
      }
      '''
    
      evt = json.loads(event)
      content = evt.get("content");
      ecsInstanceId = content.get("ecsInstanceId");
      regionId = evt.get("regionId");
    
      global clt
      clt = client.AcsClient(region_id=regionId, credential=sts_token_credential)
      name = evt.get("name");
      name = name.lower()
    
      if name in [ 'Instance:SystemFailure.Reboot:Executing'.lower(), "Instance:InstanceFailure.Reboot:Executing".lower()]:
        pass
        # do other things
    
      if name in ['Instance:SystemFailure.Reboot:Executed'.lower(), "Instance:InstanceFailure.Reboot:Executed".lower()]:
        request = DescribeDisksRequest()
        request.add_query_param("RegionId", regionId)
        request.set_InstanceId(ecsInstanceId)
        response = _send_request(request)
        disks = response.get('Disks').get('Disk', [])
        for disk in disks:
          diskId = disk["DiskId"]
          SnapshotId = create_ecs_snap_by_id(diskId)
          LOGGER.info("Create ecs snap sucess, ecs id = %s , disk id = %s ", ecsInstanceId, diskId)
    
    def create_ecs_snap_by_id(disk_id):
        LOGGER.info("Create ecs snap, disk id is %s ", disk_id)
        request = CreateSnapshotRequest()
        request.set_DiskId(disk_id)
        request.set_SnapshotName("reboot_" + ''.join(random.choice(string.ascii_lowercase) for _ in range(6)))
        response = _send_request(request)
        return response.get("SnapshotId")
    
    # send open api request
    def _send_request(request):
        request.set_accept_format('json')
        try:
            response_str = clt.do_action_with_exception(request)
            LOGGER.info(response_str)
            response_detail = json.loads(response_str)
            return response_detail
        except Exception as e:
            LOGGER.error(e)