storage: Handle guest collision checking

This pattern is already used in two places. Formalize and centralize
it
This commit is contained in:
Cole Robinson 2019-06-11 08:52:12 -04:00
parent 58dfe05344
commit 47a6f3a6d5
6 changed files with 28 additions and 23 deletions

View File

@ -1524,10 +1524,8 @@ class vmmAddHardware(vmmGObjectUI):
for c in self.vm.xmlobj.devices.controller])):
controller_model = "virtio-scsi"
collidelist = [d.path for d in self.vm.xmlobj.devices.disk]
disk = self.addstorage.build_device(self.vm.get_name(),
collidelist=collidelist, device=device)
collideguest=self.vm.xmlobj, device=device)
used = []
disk.bus = bus

View File

@ -142,7 +142,7 @@ class vmmAddStorage(vmmGObjectUI):
use_storage.set_sensitive(True)
storage_area.set_tooltip_text(storage_tooltip or "")
def get_default_path(self, name, collidelist=None):
def get_default_path(self, name, collideguest=None):
pool = self.conn.get_default_pool()
if not pool:
return
@ -151,15 +151,9 @@ class vmmAddStorage(vmmGObjectUI):
suffix = virtinst.StorageVolume.get_file_extension_for_format(fmt)
suffix = suffix or ".img"
# Sanitize collidelist to work with the collision checker
newcollidelist = []
for c in (collidelist or []):
if c and os.path.dirname(c) == pool.get_target_path():
newcollidelist.append(os.path.basename(c))
path = virtinst.StorageVolume.find_free_name(
pool.get_backend(), name,
suffix=suffix, collidelist=newcollidelist)
self.conn.get_backend(), pool.get_backend(), name,
suffix=suffix, collideguest=collideguest)
return os.path.join(pool.xmlobj.target_path, path)
@ -167,10 +161,10 @@ class vmmAddStorage(vmmGObjectUI):
return self.widget("storage-create").get_active()
def build_device(self, vmname,
path=None, device="disk", collidelist=None):
path=None, device="disk", collideguest=None):
if path is None:
if self.is_default_storage():
path = self.get_default_path(vmname, collidelist or [])
path = self.get_default_path(vmname, collideguest=collideguest)
else:
path = self.widget("storage-entry").get_text().strip()

View File

@ -160,6 +160,7 @@ class vmmCreateVolume(vmmGObjectUI):
ret = ""
try:
ret = StorageVolume.find_free_name(
self.conn.get_backend(),
self._parent_pool.get_backend(),
hint, suffix=suffix)
if ret and suffix:

View File

@ -2738,15 +2738,9 @@ def _get_default_image_format(conn, poolobj):
def _generate_new_volume_name(guest, poolobj, fmt):
collidelist = []
for disk in guest.devices.disk:
if (disk.get_vol_install() and
disk.get_vol_install().pool.name() == poolobj.name()):
collidelist.append(os.path.basename(disk.path))
ext = StorageVolume.get_file_extension_for_format(fmt)
return StorageVolume.find_free_name(
poolobj, guest.name, suffix=ext, collidelist=collidelist)
guest.conn, poolobj, guest.name, suffix=ext, collideguest=guest)
class ParserDisk(VirtCLIParser):

View File

@ -76,7 +76,7 @@ def _upload_file(conn, meter, destpool, src):
# Build placeholder volume
size = os.path.getsize(src)
basename = os.path.basename(src)
name = StorageVolume.find_free_name(destpool, basename)
name = StorageVolume.find_free_name(conn, destpool, basename)
if name != basename:
logging.debug("Generated non-colliding volume name %s", name)

View File

@ -535,11 +535,29 @@ class StorageVolume(_StorageObject):
return "." + fmt
@staticmethod
def find_free_name(pool_object, basename, **kwargs):
def find_free_name(conn, pool_object, basename, collideguest=None, **kwargs):
"""
Finds a name similar (or equal) to passed 'basename' that is not
in use by another volume. Extra params are passed to generate_name
:param collideguest: Guest object. If specified, also check to
ensure we don't collide with any disk paths there
"""
collidelist = []
if collideguest:
pooltarget = None
poolname = pool_object.name()
for poolxml in conn.fetch_all_pools():
if poolxml.name == poolname:
pooltarget = poolxml.target_path
break
for disk in collideguest.devices.disk:
if (pooltarget and disk.path and
os.path.dirname(disk.path) == pooltarget):
collidelist.append(os.path.basename(disk.path))
kwargs["collidelist"] = collidelist
StoragePool.ensure_pool_is_running(pool_object, refresh=True)
return generatename.generate_name(basename,
pool_object.storageVolLookupByName,