summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCole Robinson <crobinso@redhat.com>2020-11-11 15:13:35 -0500
committerCole Robinson <crobinso@redhat.com>2020-11-11 18:07:50 -0500
commitc4f5812290beace541dca9668f373bc35e1e8136 (patch)
treef6f21eaa0a2e1046ffaa601f6ef4595f070de56b
parentb3ff59c75ca5958fae861d13c92bcbb0e025ec66 (diff)
downloadvirt-manager-c4f5812290beace541dca9668f373bc35e1e8136.tar.gz
device: disk: Group related functions
Signed-off-by: Cole Robinson <crobinso@redhat.com>
-rw-r--r--virtinst/devices/disk.py438
1 files changed, 225 insertions, 213 deletions
diff --git a/virtinst/devices/disk.py b/virtinst/devices/disk.py
index 134d5547..6841f425 100644
--- a/virtinst/devices/disk.py
+++ b/virtinst/devices/disk.py
@@ -444,10 +444,178 @@ class DeviceDisk(Device):
self.conn, self._get_xmlpath(), self._xmltype, self.driver_type)
+ ##################
+ # XML properties #
+ ##################
+
+ _xmltype = XMLProperty("./@type")
+ _device = XMLProperty("./@device")
+
+ driver_name = XMLProperty("./driver/@name")
+ driver_type = XMLProperty("./driver/@type")
+
+ source = XMLChildProperty(_DiskSource, is_single=True)
+
+ auth_username = XMLProperty("./auth/@username")
+ auth_secret_type = XMLProperty("./auth/secret/@type")
+ auth_secret_uuid = XMLProperty("./auth/secret/@uuid")
+
+ snapshot_policy = XMLProperty("./@snapshot")
+
+ driver_copy_on_read = XMLProperty("./driver/@copy_on_read", is_onoff=True)
+
+ sgio = XMLProperty("./@sgio")
+ rawio = XMLProperty("./@rawio")
+
+ bus = XMLProperty("./target/@bus")
+ target = XMLProperty("./target/@dev")
+ removable = XMLProperty("./target/@removable", is_onoff=True)
+
+ read_only = XMLProperty("./readonly", is_bool=True)
+ shareable = XMLProperty("./shareable", is_bool=True)
+ driver_cache = XMLProperty("./driver/@cache")
+ driver_discard = XMLProperty("./driver/@discard")
+ driver_detect_zeroes = XMLProperty("./driver/@detect_zeroes")
+ driver_io = XMLProperty("./driver/@io")
+ driver_iothread = XMLProperty("./driver/@iothread", is_int=True)
+
+ error_policy = XMLProperty("./driver/@error_policy")
+ serial = XMLProperty("./serial")
+ wwn = XMLProperty("./wwn")
+ startup_policy = XMLProperty("./source/@startupPolicy")
+ logical_block_size = XMLProperty("./blockio/@logical_block_size")
+ physical_block_size = XMLProperty("./blockio/@physical_block_size")
+
+ iotune_rbs = XMLProperty("./iotune/read_bytes_sec", is_int=True)
+ iotune_ris = XMLProperty("./iotune/read_iops_sec", is_int=True)
+ iotune_tbs = XMLProperty("./iotune/total_bytes_sec", is_int=True)
+ iotune_tis = XMLProperty("./iotune/total_iops_sec", is_int=True)
+ iotune_wbs = XMLProperty("./iotune/write_bytes_sec", is_int=True)
+ iotune_wis = XMLProperty("./iotune/write_iops_sec", is_int=True)
+
+ seclabels = XMLChildProperty(DeviceSeclabel, relative_xpath="./source")
+
+ geometry_cyls = XMLProperty("./geometry/@cyls", is_int=True)
+ geometry_heads = XMLProperty("./geometry/@heads", is_int=True)
+ geometry_secs = XMLProperty("./geometry/@secs", is_int=True)
+ geometry_trans = XMLProperty("./geometry/@trans")
+
+ reservations_managed = XMLProperty("./source/reservations/@managed")
+ reservations_source_type = XMLProperty("./source/reservations/source/@type")
+ reservations_source_path = XMLProperty("./source/reservations/source/@path")
+ reservations_source_mode = XMLProperty("./source/reservations/source/@mode")
+
+
#############################
- # Public property-esque API #
+ # Internal defaults helpers #
#############################
+ def _get_default_type(self):
+ if self.source.pool or self.source.volume:
+ return DeviceDisk.TYPE_VOLUME
+ if not self._storage_backend.is_stub():
+ return self._storage_backend.get_dev_type()
+ if self.source.protocol:
+ return DeviceDisk.TYPE_NETWORK
+ return self.TYPE_FILE
+
+ def _get_default_driver_name(self):
+ if not self.path:
+ return None
+
+ # Recommended xen defaults from here:
+ # https://bugzilla.redhat.com/show_bug.cgi?id=1171550#c9
+ # If type block, use name=phy. Otherwise do the same as qemu
+ if self.conn.is_xen() and self.type == self.TYPE_BLOCK:
+ return self.DRIVER_NAME_PHY
+ if self.conn.support.conn_disk_driver_name_qemu():
+ return self.DRIVER_NAME_QEMU
+ return None
+
+ def _get_default_driver_type(self):
+ """
+ Set driver type from passed parameters
+
+ Where possible, we want to force /driver/@type = "raw" if installing
+ a QEMU VM. Without telling QEMU to expect a raw file, the emulator
+ is forced to autodetect, which has security implications:
+
+ https://lists.gnu.org/archive/html/qemu-devel/2008-04/msg00675.html
+ """
+ if self.driver_name != self.DRIVER_NAME_QEMU:
+ return None
+
+ drvtype = self._storage_backend.get_driver_type()
+ return _qemu_sanitize_drvtype(self.type, drvtype)
+
+ def _get_type(self):
+ if self._xmltype:
+ return self._xmltype
+ return self._get_default_type()
+ def _set_type(self, val):
+ self._xmltype = val
+ type = property(_get_type, _set_type)
+
+ def _get_device(self):
+ if self._device:
+ return self._device
+ return self.DEVICE_DISK
+ def _set_device(self, val):
+ self._device = val
+ device = property(_get_device, _set_device)
+
+
+ ############################
+ # Storage backend handling #
+ ############################
+
+ def _change_backend(self, path, vol_object, parent_pool):
+ backend = diskbackend.StorageBackend(self.conn, path,
+ vol_object, parent_pool)
+ self._storage_backend = backend
+
+ def set_backend_for_existing_path(self):
+ # This is an entry point for parsexml Disk instances to request
+ # a _storage_backend to be initialized from the XML path. That
+ # will cause validate() to actually validate the path exists.
+ # We need this so addhw XML editing will still validate the disk path
+ if self._storage_backend.is_stub():
+ self._resolve_storage_backend()
+
+ def _resolve_storage_backend(self):
+ """
+ Convert the relevant <source> XML values into self._storage_backend
+ """
+ path = None
+ vol_object = None
+ parent_pool = None
+ self._source_volume_err = None
+ typ = self._get_default_type()
+
+ if self.type == DeviceDisk.TYPE_NETWORK:
+ # Fill in a completed URL for virt-manager UI, path comparison, etc
+ path = self.source.build_url_from_network()
+
+ if typ == DeviceDisk.TYPE_VOLUME:
+ try:
+ parent_pool = self.conn.storagePoolLookupByName(
+ self.source.pool)
+ vol_object = parent_pool.storageVolLookupByName(
+ self.source.volume)
+ except Exception as e:
+ self._source_volume_err = str(e)
+ log.debug("Error fetching source pool=%s vol=%s",
+ self.source.pool, self.source.volume, exc_info=True)
+
+ if vol_object is None and path is None:
+ path = self._get_xmlpath()
+
+ if path and not vol_object and not parent_pool:
+ (vol_object, parent_pool) = diskbackend.manage_path(
+ self.conn, path)
+
+ self._change_backend(path, vol_object, parent_pool)
+
def _get_path(self):
if (self._storage_backend.is_stub() and not
self._storage_backend.get_path()):
@@ -467,14 +635,6 @@ class DeviceDisk(Device):
self._set_xmlpath(self.path)
path = property(_get_path, _set_path)
- def set_backend_for_existing_path(self):
- # This is an entry point for parsexml Disk instances to request
- # a _storage_backend to be initialized from the XML path. That
- # will cause validate() to actually validate the path exists.
- # We need this so addhw XML editing will still validate the disk path
- if self._storage_backend.is_stub():
- self._resolve_storage_backend()
-
def set_vol_object(self, vol_object, parent_pool):
log.debug("disk.set_vol_object: volxml=\n%s",
vol_object.XMLDesc(0))
@@ -500,46 +660,6 @@ class DeviceDisk(Device):
return self._storage_backend.get_size()
- #############################
- # Internal defaults helpers #
- #############################
-
- def _get_default_driver_name(self):
- if not self.path:
- return None
-
- # Recommended xen defaults from here:
- # https://bugzilla.redhat.com/show_bug.cgi?id=1171550#c9
- # If type block, use name=phy. Otherwise do the same as qemu
- if self.conn.is_xen() and self.type == self.TYPE_BLOCK:
- return self.DRIVER_NAME_PHY
- if self.conn.support.conn_disk_driver_name_qemu():
- return self.DRIVER_NAME_QEMU
- return None
-
- def _get_default_driver_type(self):
- """
- Set driver type from passed parameters
-
- Where possible, we want to force /driver/@type = "raw" if installing
- a QEMU VM. Without telling QEMU to expect a raw file, the emulator
- is forced to autodetect, which has security implications:
-
- https://lists.gnu.org/archive/html/qemu-devel/2008-04/msg00675.html
- """
- if self.driver_name != self.DRIVER_NAME_QEMU:
- return None
-
- drvtype = self._storage_backend.get_driver_type()
- return _qemu_sanitize_drvtype(self.type, drvtype)
-
-
- #############################
- # XML source media handling #
- #############################
-
- source = XMLChildProperty(_DiskSource, is_single=True)
-
def _set_source_network_from_storage(self, volxml, poolxml):
self.type = "network"
if poolxml.auth_type:
@@ -558,16 +678,6 @@ class DeviceDisk(Device):
elif self._storage_backend.get_path():
self.source.set_from_url(self._storage_backend.get_path())
- def _get_default_type(self):
- if self.source.pool or self.source.volume:
- return DeviceDisk.TYPE_VOLUME
- if not self._storage_backend.is_stub():
- return self._storage_backend.get_dev_type()
- if self.source.protocol:
- return DeviceDisk.TYPE_NETWORK
- return self.TYPE_FILE
-
-
def _disk_type_to_object_prop_name(self):
disk_type = self.type
if disk_type == DeviceDisk.TYPE_BLOCK:
@@ -590,6 +700,7 @@ class DeviceDisk(Device):
if self.source.dir:
return self.source.dir
return None
+
def _set_xmlpath(self, val):
self.source.clear_source()
@@ -602,118 +713,6 @@ class DeviceDisk(Device):
return
return setattr(self.source, propname, val)
-
- ##################
- # XML properties #
- ##################
-
- # type, device, driver_name, driver_type handling
- # These are all weirdly intertwined so require some special handling
- def _get_type(self):
- if self._xmltype:
- return self._xmltype
- return self._get_default_type()
- def _set_type(self, val):
- self._xmltype = val
- type = property(_get_type, _set_type)
- _xmltype = XMLProperty("./@type")
-
- def _get_device(self):
- if self._device:
- return self._device
- return self.DEVICE_DISK
- def _set_device(self, val):
- self._device = val
- device = property(_get_device, _set_device)
- _device = XMLProperty("./@device")
- driver_name = XMLProperty("./driver/@name")
- driver_type = XMLProperty("./driver/@type")
-
- auth_username = XMLProperty("./auth/@username")
- auth_secret_type = XMLProperty("./auth/secret/@type")
- auth_secret_uuid = XMLProperty("./auth/secret/@uuid")
-
- snapshot_policy = XMLProperty("./@snapshot")
-
- driver_copy_on_read = XMLProperty("./driver/@copy_on_read", is_onoff=True)
-
- sgio = XMLProperty("./@sgio")
- rawio = XMLProperty("./@rawio")
-
- bus = XMLProperty("./target/@bus")
- target = XMLProperty("./target/@dev")
- removable = XMLProperty("./target/@removable", is_onoff=True)
-
- read_only = XMLProperty("./readonly", is_bool=True)
- shareable = XMLProperty("./shareable", is_bool=True)
- driver_cache = XMLProperty("./driver/@cache")
- driver_discard = XMLProperty("./driver/@discard")
- driver_detect_zeroes = XMLProperty("./driver/@detect_zeroes")
- driver_io = XMLProperty("./driver/@io")
- driver_iothread = XMLProperty("./driver/@iothread", is_int=True)
-
- error_policy = XMLProperty("./driver/@error_policy")
- serial = XMLProperty("./serial")
- wwn = XMLProperty("./wwn")
- startup_policy = XMLProperty("./source/@startupPolicy")
- logical_block_size = XMLProperty("./blockio/@logical_block_size")
- physical_block_size = XMLProperty("./blockio/@physical_block_size")
-
- iotune_rbs = XMLProperty("./iotune/read_bytes_sec", is_int=True)
- iotune_ris = XMLProperty("./iotune/read_iops_sec", is_int=True)
- iotune_tbs = XMLProperty("./iotune/total_bytes_sec", is_int=True)
- iotune_tis = XMLProperty("./iotune/total_iops_sec", is_int=True)
- iotune_wbs = XMLProperty("./iotune/write_bytes_sec", is_int=True)
- iotune_wis = XMLProperty("./iotune/write_iops_sec", is_int=True)
-
- seclabels = XMLChildProperty(DeviceSeclabel, relative_xpath="./source")
-
- geometry_cyls = XMLProperty("./geometry/@cyls", is_int=True)
- geometry_heads = XMLProperty("./geometry/@heads", is_int=True)
- geometry_secs = XMLProperty("./geometry/@secs", is_int=True)
- geometry_trans = XMLProperty("./geometry/@trans")
-
- reservations_managed = XMLProperty("./source/reservations/@managed")
- reservations_source_type = XMLProperty("./source/reservations/source/@type")
- reservations_source_path = XMLProperty("./source/reservations/source/@path")
- reservations_source_mode = XMLProperty("./source/reservations/source/@mode")
-
-
- #################################
- # Validation assistance methods #
- #################################
-
- def _resolve_storage_backend(self):
- path = None
- vol_object = None
- parent_pool = None
- self._source_volume_err = None
- typ = self._get_default_type()
-
- if self.type == DeviceDisk.TYPE_NETWORK:
- # Fill in a completed URL for virt-manager UI, path comparison, etc
- path = self.source.build_url_from_network()
-
- if typ == DeviceDisk.TYPE_VOLUME:
- try:
- parent_pool = self.conn.storagePoolLookupByName(
- self.source.pool)
- vol_object = parent_pool.storageVolLookupByName(
- self.source.volume)
- except Exception as e:
- self._source_volume_err = str(e)
- log.debug("Error fetching source pool=%s vol=%s",
- self.source.pool, self.source.volume, exc_info=True)
-
- if vol_object is None and path is None:
- path = self._get_xmlpath()
-
- if path and not vol_object and not parent_pool:
- (vol_object, parent_pool) = diskbackend.manage_path(
- self.conn, path)
-
- self._change_backend(path, vol_object, parent_pool)
-
def set_local_disk_to_clone(self, disk, sparse):
"""
Set a path to manually clone (as in, not through libvirt)
@@ -721,6 +720,11 @@ class DeviceDisk(Device):
self._storage_backend = diskbackend.CloneStorageCreator(self.conn,
self.path, disk.path, disk.get_size(), sparse)
+
+ #####################
+ # Utility functions #
+ #####################
+
def is_cdrom(self):
return self.device == self.DEVICE_CDROM
def is_floppy(self):
@@ -736,27 +740,6 @@ class DeviceDisk(Device):
# Don't error for unknown types
return True
- def _change_backend(self, path, vol_object, parent_pool):
- backend = diskbackend.StorageBackend(self.conn, path,
- vol_object, parent_pool)
- self._storage_backend = backend
-
- def sync_path_props(self):
- """
- Fills in the values of type, driver_type, and driver_name for
- the associated backing storage. This needs to be manually called
- if changing an existing disk's media.
- """
- path = self._get_xmlpath()
-
- self.type = self._get_default_type()
- self.driver_name = self._get_default_driver_name()
- self.driver_type = self._get_default_driver_type()
-
- # Need to retrigger this if self.type changed
- if path:
- self._set_xmlpath(path)
-
def wants_storage_creation(self):
"""
If true, this disk needs storage creation parameters or things
@@ -764,24 +747,10 @@ class DeviceDisk(Device):
"""
return not self._storage_backend.exists()
- def validate(self):
- if self.path is None:
- if self._source_volume_err:
- raise RuntimeError(self._source_volume_err)
-
- if not self.can_be_empty():
- raise ValueError(_("Device type '%s' requires a path") %
- self.device)
-
- return
- if (not self._storage_backend.exists() and
- not self._storage_backend.will_create_storage()):
- raise ValueError(
- _("Must specify storage creation parameters for "
- "non-existent path '%s'.") % self.path)
-
- self._storage_backend.validate()
+ ####################
+ # Storage building #
+ ####################
def build_storage(self, meter):
"""
@@ -803,6 +772,30 @@ class DeviceDisk(Device):
parent_pool = self.get_vol_install().pool
self._change_backend(None, vol_object, parent_pool)
+
+ ######################
+ # validation helpers #
+ ######################
+
+ def validate(self):
+ if self.path is None:
+ if self._source_volume_err:
+ raise RuntimeError(self._source_volume_err)
+
+ if not self.can_be_empty():
+ raise ValueError(_("Device type '%s' requires a path") %
+ self.device)
+
+ return
+
+ if (not self._storage_backend.exists() and
+ not self._storage_backend.will_create_storage()):
+ raise ValueError(
+ _("Must specify storage creation parameters for "
+ "non-existent path '%s'.") % self.path)
+
+ self._storage_backend.validate()
+
def is_size_conflict(self):
"""
reports if disk size conflicts with available space
@@ -828,6 +821,26 @@ class DeviceDisk(Device):
return ret
+ ###########################
+ # Misc functional helpers #
+ ###########################
+
+ def sync_path_props(self):
+ """
+ Fills in the values of type, driver_type, and driver_name for
+ the associated backing storage. This needs to be manually called
+ if changing an existing disk's media.
+ """
+ path = self._get_xmlpath()
+
+ self.type = self._get_default_type()
+ self.driver_name = self._get_default_driver_name()
+ self.driver_type = self._get_default_driver_type()
+
+ # Need to retrigger this if self.type changed
+ if path:
+ self._set_xmlpath(path)
+
def get_target_prefix(self):
"""
Returns the suggested disk target prefix (hd, xvd, sd ...) for the
@@ -857,7 +870,6 @@ class DeviceDisk(Device):
# sata, scsi, usb, sd
return _return("sd")
-
def generate_target(self, skip_targets):
"""
Generate target device ('hda', 'sdb', etc..) for disk, excluding
@@ -922,9 +934,9 @@ class DeviceDisk(Device):
self.generate_target(used)
- ##################
- # Default config #
- ##################
+ #########################
+ # set_defaults handling #
+ #########################
def _default_bus(self, guest):
if self.is_floppy():