docs: def do_cleanup(cleanup):
      '''
      Clean up clone domain leftovers as much as possible.
  
      Extra robust clean up in order to deal with some small changes in libvirt
      behavior over time. Passed in volumes and domains are deleted, any errors
      are ignored. Used when cloning/provisioning a domain fails.
  
      :param cleanup: list containing dictonaries with two keys: 'what' and 'item'.
                      If 'what' is domain the 'item' is a libvirt domain object.
                      If 'what' is volume then the item is a libvirt volume object.
  
      Returns:
          none
  
      .. versionadded: 2017.7.3
      '''
      log.info('Cleaning up after exception')
      for leftover in cleanup:
          what = leftover['what']
          item = leftover['item']
          if what == 'domain':
              log.info('Cleaning up %s %s', what, item.name())
              try:
                  item.destroy()
                  log.debug('%s %s forced off', what, item.name())
              except libvirtError:
                  pass
              try:
                  item.undefineFlags(libvirt.VIR_DOMAIN_UNDEFINE_MANAGED_SAVE+
                                     libvirt.VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA+
                                     libvirt.VIR_DOMAIN_UNDEFINE_NVRAM)
                  log.debug('%s %s undefined', what, item.name())
              except libvirtError:
                  pass
          if what == 'volume':
              try:
                  item.delete()
                  log.debug('%s %s cleaned up', what, item.name())
              except libvirtError:
                  pass