delete_inactive_ebs.py 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #
  2. # Copyright (c) Contributors to the Open 3D Engine Project.
  3. # For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. #
  5. # SPDX-License-Identifier: Apache-2.0 OR MIT
  6. #
  7. #
  8. import boto3
  9. from datetime import datetime, timedelta
  10. import logging
  11. log = logging.getLogger(__name__)
  12. log.setLevel(logging.INFO)
  13. ATTACH_DATE_TAG_NAME = 'AttachDate'
  14. INACTIVE_DAY_THRESHOLD = 5
  15. def get_tag_values(tag_name):
  16. """
  17. Call Resource Group Tagging API to get all values of a certain tag
  18. :param tag_name: Tag name
  19. :return: List of all values of the tag
  20. """
  21. client = boto3.client('resourcegroupstaggingapi')
  22. tag_values = []
  23. try:
  24. response = client.get_tag_values(
  25. Key=tag_name
  26. )
  27. tag_values += response['TagValues']
  28. while response and response.get('PaginationToken', ''):
  29. response = client.get_tag_values(
  30. PaginationToken=response['PaginationToken'],
  31. Key=tag_name
  32. )
  33. tag_values += response['TagValues']
  34. return tag_values
  35. except Exception as e:
  36. log.error(f'Failed to get tag values for {tag_name}.')
  37. log.error(e)
  38. return []
  39. def delete_volumes(inactive_dates):
  40. """
  41. Find and delete all EBS volumes that have AttachDate tag value in inactive_dates
  42. :param inactive_dates: List of String that considered as inactive dates, for example, ["2021-04-27", "2021-04-26"]
  43. :return: Number of EBS volumes that are deleted successfully, number of EBS volumes that are not deleted.
  44. """
  45. success = 0
  46. failure = 0
  47. ec2_client = boto3.resource('ec2')
  48. response = ec2_client.volumes.filter(Filters=[
  49. {
  50. 'Name': f'tag:{ATTACH_DATE_TAG_NAME}',
  51. 'Values': inactive_dates
  52. },
  53. {
  54. 'Name': 'status',
  55. 'Values': ['available']
  56. },
  57. ])
  58. log.info(f'Deleting inactive EBS volumes that haven\'t been used for {INACTIVE_DAY_THRESHOLD} days...')
  59. for volume in response:
  60. if volume.attachments:
  61. # Double check if volume has an attachment in case the volume is being used.
  62. continue
  63. try:
  64. log.info(f'Deleting volume {volume.volume_id}')
  65. volume.delete()
  66. success += 1
  67. except Exception as e:
  68. log.error(f'Failed to delete volume {volume.volume_id}.')
  69. log.error(e)
  70. failure += 1
  71. return success, failure
  72. def main():
  73. tag_values = get_tag_values(ATTACH_DATE_TAG_NAME)
  74. date_today = datetime.today().date()
  75. # Exclude dates of last {INACTIVE_DAY_THRESHOLD} days from tag values, the rest values are considered as inactive dates.
  76. dates_to_exclude = []
  77. for i in range(INACTIVE_DAY_THRESHOLD):
  78. dates_to_exclude.append(str(date_today - timedelta(i)))
  79. inactive_dates = set(tag_values).difference(dates_to_exclude)
  80. if inactive_dates:
  81. success, failure = delete_volumes(list(inactive_dates))
  82. log.info(f'{success} EBS volumes are deleted successfully.')
  83. if failure:
  84. log.info(f'{failure} EBS volumes are not deleted due to errors. See logs for more information.')
  85. if __name__ == "__main__":
  86. main()