如何检查带有 ID 的快照是否正在使用 Boto 中的 AWS AMI?

How to check whether a snapshot with ID is in use of AWS AMI's in Boto?

删除快照时出现以下错误。我想删除我的 AWS AMI 和其他实例当前未使用的快照。我也试过了,但遇到了这个错误。

Traceback (most recent call last):
<path to error file>
EC2ResponseError: EC2ResponseError: 400 Bad Request
<?xml version="1.0" encoding="UTF-8"?><Response><Errors><Error><Code>InvalidSnapshot.InUse</Code><Message>The snapshot snap-xxxxxxxx is currently in use by ami-xxxxxxxx</Message></Error></Errors><RequestID>bbe55333-4acf-4ca7-9aa3-49307b189ca3</RequestID></Response>

遗憾的是,没有 API 可以直接从 EBS 快照获取 AMI ID。

相反,你可以走另一条路。

  1. 使用ec2:DescribeImages 获取AMI 映像列表。
  2. 对于返回的每个 AMI 映像,检查与 AMI 映像关联的 EBS 快照列表。
  3. 查看是否包含有问题的 EBS 快照。

编辑:另一种可能性:

您可以使用 ec2:DescribeImages 和 EBS 快照 ID 上的过滤器。

https://ec2.amazonaws.com/?Action=DescribeImages
 &Filter.1.Name=block-device-mapping.snapshot-id
 &Filter.1.Value=snap-xxxx

参考:http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeImages.html

删除所有未使用的快照:

for s in $(comm -23 <(echo $(ec2-describe-snapshots --region ap-southeast-1 | grep SNAPSHOT | awk '{print }' | sort | uniq) | tr ' ' '\n') <(echo $(ec2-describe-images --region ap-southeast-1 | grep BLOCKDEVICEMAPPING | awk '{print }' | sort | uniq) | tr ' ' '\n') | tr '\n' ' ')
do
    echo Deleting snapshot $s
    ec2-delete-snapshot --region ap-southeast-1 $s  
done

1) 检索所有快照,使用正则表达式在快照描述中搜索 AMI-ID。

    reAmi = re.compile('ami-[^ ]+')
    snapshotImageId = reAmi.findall(snapshot.description)

2) 检索所有 AMI。检查第一步中检索到的 AMI-ID 是否仍然存在,如果不存在,则不再需要与该特定 AMI 关联的快照。

完整代码已发布here

希望对您有所帮助!!

以防万一还有人想知道该怎么做:

def if_associated_to_ami(client, snapshot_id):
  img = client.describe_images(
      Filters=[
          {'Name': 'block-device-mapping.snapshot-id', 'Values': [snapshot_id]}
      ]
  )
  try:
      ami_id = img['Images'][0]['ImageId']
      print("Snapshot(" + snapshot_id + ") is associated to image(" + ami_id + "). Return True")
      return True
  except IndexError:
      print("Snapshot(" + snapshot_id + ") is not associated to any image. Return False")
      return False