block-cleaner-daemon.py 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. #!/usr/bin/python
  2. import xen.lowlevel.xs
  3. import time
  4. import subprocess
  5. xs = xen.lowlevel.xs.xs()
  6. domain_list = []
  7. def setup_watches():
  8. global domain_list
  9. new_domain_list = xs.ls('', '/local/domain')
  10. for dom in new_domain_list:
  11. if dom not in domain_list:
  12. print "Adding: %s" % dom
  13. xs.watch('/local/domain/%s/backend/vbd' % dom, int(dom))
  14. for dom in domain_list:
  15. if dom not in new_domain_list:
  16. print "Removing: %s" % dom
  17. xs.unwatch('/local/domain/%s/backend/vbd' % dom, int(dom))
  18. domain_list = new_domain_list
  19. def handle_vbd_state(path):
  20. state = xs.read('', path)
  21. if state == '6':
  22. # Closed state; wait a moment to not interrupt reconnect
  23. time.sleep(0.500)
  24. state = xs.read('', path)
  25. if state == '6':
  26. # If still closed, detach device
  27. path_components = path.split('/')
  28. # /local/domain/<BACK XID>/backend/vbd/<FRONT XID>/<DEV>/...
  29. vm_xid = path_components[6]
  30. vm_dev = path_components[7]
  31. if vm_xid in domain_list:
  32. subprocess.call(['xl', 'block-detach', vm_xid, vm_dev])
  33. def main():
  34. xs.watch('@introduceDomain', 'reload')
  35. xs.watch('@releaseDomain', 'reload')
  36. setup_watches()
  37. while True:
  38. (path, token) = xs.read_watch()
  39. if token == 'reload':
  40. setup_watches()
  41. else:
  42. if path.endswith('/state'):
  43. handle_vbd_state(path)
  44. main()