You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

105 lines
3.4 KiB

  1. #!/usr/bin/env python
  2. import argparse
  3. import openstack
  4. import logging
  5. import datetime
  6. import time
  7. DATE_FORMAT = '%Y-%m-%dT%H:%M:%SZ'
  8. PAUSE_SECONDS = 5
  9. log = logging.getLogger('openstack-cleanup')
  10. parser = argparse.ArgumentParser(description='Cleanup OpenStack resources')
  11. parser.add_argument('-v', '--verbose', action='store_true',
  12. help='Increase verbosity')
  13. parser.add_argument('--hours', type=int, default=4,
  14. help='Age (in hours) of VMs to cleanup (default: 4h)')
  15. parser.add_argument('--dry-run', action='store_true',
  16. help='Do not delete anything')
  17. args = parser.parse_args()
  18. oldest_allowed = datetime.datetime.now() - datetime.timedelta(hours=args.hours)
  19. def main():
  20. if args.dry_run:
  21. print('Running in dry-run mode')
  22. else:
  23. print('This will delete resources... (ctrl+c to cancel)')
  24. time.sleep(PAUSE_SECONDS)
  25. conn = openstack.connect()
  26. print('Servers...')
  27. map_if_old(conn.compute.delete_server,
  28. conn.compute.servers())
  29. print('Ports...')
  30. try:
  31. map_if_old(conn.network.delete_port,
  32. conn.network.ports())
  33. except openstack.exceptions.ConflictException as ex:
  34. # Need to find subnet-id which should be removed from a router
  35. for sn in conn.network.subnets():
  36. try:
  37. fn_if_old(conn.network.delete_subnet, sn)
  38. except openstack.exceptions.ConflictException:
  39. for r in conn.network.routers():
  40. print("Deleting subnet %s from router %s", sn, r)
  41. try:
  42. conn.network.remove_interface_from_router(
  43. r, subnet_id=sn.id)
  44. except Exception as ex:
  45. print("Failed to delete subnet from router as %s", ex)
  46. for ip in conn.network.ips():
  47. fn_if_old(conn.network.delete_ip, ip)
  48. # After removing unnecessary subnet from router, retry to delete ports
  49. map_if_old(conn.network.delete_port,
  50. conn.network.ports())
  51. print('Security groups...')
  52. try:
  53. map_if_old(conn.network.delete_security_group,
  54. conn.network.security_groups())
  55. except openstack.exceptions.ConflictException as ex:
  56. # Need to delete port when security groups is in used
  57. map_if_old(conn.network.delete_port,
  58. conn.network.ports())
  59. map_if_old(conn.network.delete_security_group,
  60. conn.network.security_groups())
  61. print('Subnets...')
  62. map_if_old(conn.network.delete_subnet,
  63. conn.network.subnets())
  64. print('Networks...')
  65. for n in conn.network.networks():
  66. if not n.is_router_external:
  67. fn_if_old(conn.network.delete_network, n)
  68. # runs the given fn to all elements of the that are older than allowed
  69. def map_if_old(fn, items):
  70. for item in items:
  71. fn_if_old(fn, item)
  72. # run the given fn function only if the passed item is older than allowed
  73. def fn_if_old(fn, item):
  74. created_at = datetime.datetime.strptime(item.created_at, DATE_FORMAT)
  75. if item.name == "default": # skip default security group
  76. return
  77. if created_at < oldest_allowed:
  78. print('Will delete %(name)s (%(id)s)' % item)
  79. if not args.dry_run:
  80. fn(item)
  81. if __name__ == '__main__':
  82. # execute only if run as a script
  83. main()