Offer to delete the storage files without removing the VM

we should let users decide whether they want to also delete the
storage files or just dev from UI when they click the Remove button

Reviewed-by: Cole Robinson <crobinso@redhat.com>
This commit is contained in:
Lily Nie 2019-12-18 16:39:57 +08:00 committed by Cole Robinson
parent 8b7854af1f
commit d52c9d1ffa
2 changed files with 42 additions and 12 deletions

View File

@ -31,6 +31,8 @@ STORAGE_ROW_TOOLTIP = 7
class vmmDeleteDialog(vmmGObjectUI): class vmmDeleteDialog(vmmGObjectUI):
disk = None
@classmethod @classmethod
def show_instance(cls, parentobj, vm): def show_instance(cls, parentobj, vm):
try: try:
@ -75,6 +77,9 @@ class vmmDeleteDialog(vmmGObjectUI):
self._set_vm(None) self._set_vm(None)
return 1 return 1
def set_disk(self, disk):
self.disk = disk
def _cleanup(self): def _cleanup(self):
pass pass
@ -93,9 +98,14 @@ class vmmDeleteDialog(vmmGObjectUI):
self.vm = newvm self.vm = newvm
def _reset_state(self): def _reset_state(self):
# Set VM name in title' # Set VM name or disk.target in title'
if self.disk:
text = self.disk.target
else:
text = self.vm.get_name()
title_str = ("<span size='large' color='white'>%s '%s'</span>" % title_str = ("<span size='large' color='white'>%s '%s'</span>" %
(_("Delete"), xmlutil.xml_escape(self.vm.get_name()))) (_("Delete"), xmlutil.xml_escape(text)))
self.widget("header-label").set_markup(title_str) self.widget("header-label").set_markup(title_str)
self.topwin.resize(1, 1) self.topwin.resize(1, 1)
@ -109,8 +119,10 @@ class vmmDeleteDialog(vmmGObjectUI):
# Enable storage removal by default # Enable storage removal by default
self.widget("delete-remove-storage").set_active(True) self.widget("delete-remove-storage").set_active(True)
self.widget("delete-remove-storage").toggled() self.widget("delete-remove-storage").toggled()
if self.disk:
diskdatas = _build_diskdata_for_vm(self.vm) diskdatas = [_DiskData.from_disk(self.disk)]
else:
diskdatas = _build_diskdata_for_vm(self.vm)
_populate_storage_list(self.widget("delete-storage-list"), _populate_storage_list(self.widget("delete-storage-list"),
self.vm, self.vm.conn, diskdatas) self.vm, self.vm.conn, diskdatas)
@ -172,10 +184,15 @@ class vmmDeleteDialog(vmmGObjectUI):
self.set_finish_cursor() self.set_finish_cursor()
title = _("Deleting virtual machine '%s'") % self.vm.get_name() if self.disk:
text = title title = _("Deleting the selected storage")
if devs: text = _('%s') % self.disk.target
text = title + _(" and selected storage (this may take a while)") else:
title = _("Deleting virtual machine '%s'") % self.vm.get_name()
text = title
if devs:
text = title + _(" and selected storage (this may take a while)")
progWin = vmmAsyncJob(self._async_delete, [self.vm, devs], progWin = vmmAsyncJob(self._async_delete, [self.vm, devs],
self._delete_finished_cb, [], self._delete_finished_cb, [],
@ -195,18 +212,20 @@ class vmmDeleteDialog(vmmGObjectUI):
conn = vm.conn.get_backend() conn = vm.conn.get_backend()
meter = asyncjob.get_meter() meter = asyncjob.get_meter()
if not paths and self.disk:
vm.remove_device(self.disk)
for path in paths: for path in paths:
try: try:
log.debug("Deleting path: %s", path) log.debug("Deleting path: %s", path)
meter.start(text=_("Deleting path '%s'") % path) meter.start(text=_("Deleting path '%s'") % path)
self._async_delete_path(conn, path, meter) self._async_delete_dev(vm, conn, path, meter)
except Exception as e: except Exception as e:
storage_errors.append((str(e), storage_errors.append((str(e),
"".join(traceback.format_exc()))) "".join(traceback.format_exc())))
meter.end(0) meter.end(0)
if undefine: if undefine and not self.disk:
log.debug("Removing VM '%s'", vm.get_name()) log.debug("Removing VM '%s'", vm.get_name())
vm.delete() vm.delete()
@ -239,7 +258,7 @@ class vmmDeleteDialog(vmmGObjectUI):
asyncjob.set_error(error, details) asyncjob.set_error(error, details)
vm.conn.schedule_priority_tick(pollvm=True) vm.conn.schedule_priority_tick(pollvm=True)
def _async_delete_path(self, conn, path, ignore): def _async_delete_dev(self, vm, conn, path, ignore):
vol = None vol = None
try: try:
@ -251,6 +270,14 @@ class vmmDeleteDialog(vmmGObjectUI):
vol.delete(0) vol.delete(0)
else: else:
os.unlink(path) os.unlink(path)
self._async_delete_xmldev(vm, path, ignore)
def _async_delete_xmldev(self, vm, path, ignore):
for d in vm.xmlobj.devices.disk:
if d.path == path:
dev = d
break
vm.remove_device(dev)
################### ###################

View File

@ -1109,7 +1109,10 @@ class vmmDetails(vmmGObjectUI):
str(e))) str(e)))
def remove_disk(self, disk): def remove_disk(self, disk):
self.remove_device(disk) from ..delete import vmmDeleteDialog
dialog = vmmDeleteDialog()
dialog.set_disk(disk)
dialog.show(self.topwin, self.vm)
def remove_xml_dev(self, src_ignore): def remove_xml_dev(self, src_ignore):
devobj = self.get_hw_row()[HW_LIST_COL_DEVICE] devobj = self.get_hw_row()[HW_LIST_COL_DEVICE]