From 88fbf743f2faa6bc27e8d659db31789689c6c656 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Tue, 8 Apr 2025 01:57:59 +0200 Subject: [PATCH] Synchronize exc.py with core-admin Especially, add new devices-related exceptions. This is needed for salt to properly handle assigning devices. --- qubesadmin/exc.py | 149 +++++++++++++++++++++++++++++++--------------- 1 file changed, 101 insertions(+), 48 deletions(-) diff --git a/qubesadmin/exc.py b/qubesadmin/exc.py index 37162c4c..3efbab7e 100644 --- a/qubesadmin/exc.py +++ b/qubesadmin/exc.py @@ -18,121 +18,135 @@ # You should have received a copy of the GNU Lesser General Public License along # with this program; if not, see . -'''Exception hierarchy.''' +""" +Qubes OS exception hierarchy +""" class QubesException(Exception): - '''Base exception for all Qubes-related errors.''' + """Exception that can be shown to the user""" + def __init__(self, message_format, *args, **kwargs): # TODO: handle translations super().__init__( message_format % tuple(int(d) if d.isdigit() else d for d in args), - **kwargs) + **kwargs + ) class QubesVMNotFoundError(QubesException, KeyError): - '''Domain cannot be found in the system''' + """Domain cannot be found in the system""" def __str__(self): # KeyError overrides __str__ method return QubesException.__str__(self) +class QubesVMInvalidUUIDError(QubesException): + """Domain UUID is invalid""" + + class QubesVMError(QubesException): - '''Some problem with domain state.''' + """Some problem with domain state.""" + + +class QubesVMInUseError(QubesVMError): + """VM is in use, cannot remove.""" class QubesVMNotStartedError(QubesVMError): - '''Domain is not started. + """Domain is not started. This exception is thrown when machine is halted, but should be started (that is, either running or paused). - ''' + """ class QubesVMNotRunningError(QubesVMNotStartedError): - '''Domain is not running. + """Domain is not running. This exception is thrown when machine should be running but is either halted or paused. - ''' + """ class QubesVMNotPausedError(QubesVMNotStartedError): - '''Domain is not paused. + """Domain is not paused. This exception is thrown when machine should be paused, but is not. - ''' + """ class QubesVMNotSuspendedError(QubesVMError): - '''Domain is not suspended. + """Domain is not suspended. This exception is thrown when machine should be suspended but is either halted or running. - ''' + """ class QubesVMNotHaltedError(QubesVMError): - '''Domain is not halted. + """Domain is not halted. This exception is thrown when machine should be halted, but is not (either running or paused). - ''' + """ -class QubesVMShutdownTimeout(QubesVMError): - ''' Domain shutdown haven't completed in expected timeframe''' +class QubesVMShutdownTimeoutError(QubesVMError): + """Domain shutdown timed out.""" class QubesNoTemplateError(QubesVMError): - '''Cannot start domain, because there is no template''' + """Cannot start domain, because there is no template""" -class QubesVMInUseError(QubesVMError): - '''VM is in use, cannot remove.''' +class QubesPoolInUseError(QubesException): + """VM is in use, cannot remove.""" class QubesValueError(QubesException, ValueError): - '''Cannot set some value, because it is invalid, out of bounds, etc.''' + """Cannot set some value, because it is invalid, out of bounds, etc.""" class QubesPropertyValueError(QubesValueError): - '''Cannot set value of qubes.property, because user-supplied value is wrong. - ''' + """ + Cannot set value of qubes.property, because user-supplied value is wrong. + """ class QubesNoSuchPropertyError(QubesException, AttributeError): - '''Requested property does not exist - ''' + """Requested property does not exist""" class QubesNotImplementedError(QubesException, NotImplementedError): - '''Thrown at user when some feature is not implemented''' + """Thrown at user when some feature is not implemented""" class BackupCancelledError(QubesException): - '''Thrown at user when backup was manually cancelled''' + """Thrown at user when backup was manually cancelled""" class BackupAlreadyRunningError(QubesException): - '''Thrown at user when they try to run the same backup twice at - the same time''' + """Thrown at user when they try to run the same backup twice at + the same time""" -class QubesMemoryError(QubesException, MemoryError): - '''Cannot start domain, because not enough memory is available''' +class QubesMemoryError(QubesVMError, MemoryError): + """Cannot start domain, because not enough memory is available""" class QubesFeatureNotFoundError(QubesException, KeyError): - '''Feature not set for a given domain''' + """Feature not set for a given domain""" + def __str__(self): # KeyError overrides __str__ method return QubesException.__str__(self) class QubesTagNotFoundError(QubesException, KeyError): - '''Tag not set for a given domain''' + """Tag not set for a given domain""" + def __str__(self): # KeyError overrides __str__ method return QubesException.__str__(self) @@ -140,44 +154,83 @@ def __str__(self): class QubesLabelNotFoundError(QubesException, KeyError): """Label does not exists""" + def __str__(self): # KeyError overrides __str__ method return QubesException.__str__(self) -class StoragePoolException(QubesException): - ''' A general storage exception ''' +class ProtocolError(AssertionError): + """Raised when something is wrong with data received""" -class QubesDaemonCommunicationError(QubesException): - '''Error while communicating with qubesd, may mean insufficient - permissions as well''' +class PermissionDenied(Exception): + """Raised deliberately by handlers when we decide not to cooperate""" + + +class DeviceNotAssigned(QubesException, KeyError): + """ + Trying to unassign not assigned device. + """ class DeviceAlreadyAttached(QubesException, KeyError): - '''Trying to attach already attached device''' - def __str__(self): - # KeyError overrides __str__ method - return QubesException.__str__(self) + """ + Trying to attach already attached device. + """ + + +class DeviceAlreadyAssigned(QubesException, KeyError): + """ + Trying to assign already assigned device. + """ + + +class UnrecognizedDevice(QubesException, ValueError): + """ + Device identity is not as expected. + """ + + +class UnexpectedDeviceProperty(QubesException, ValueError): + """ + Device has unexpected property such as backend_domain, devclass etc. + """ + + +class StoragePoolException(QubesException): + """A general storage exception""" + + +### core-admin-client specific exceptions: + + +class QubesDaemonCommunicationError(QubesException): + """Error while communicating with qubesd, may mean insufficient + permissions as well""" class BackupRestoreError(QubesException): - '''Restoring a backup failed''' + """Restoring a backup failed""" + def __init__(self, msg, backup_log=None): super().__init__(msg) self.backup_log = backup_log + # pylint: disable=too-many-ancestors class QubesDaemonAccessError(QubesDaemonCommunicationError): - '''Got empty response from qubesd. This can be lack of permission, - or some server-side issue.''' + """Got empty response from qubesd. This can be lack of permission, + or some server-side issue.""" class QubesPropertyAccessError(QubesDaemonAccessError, AttributeError): - '''Failed to read/write property value, cause is unknown (insufficient - permissions, no such property, invalid value, other)''' + """Failed to read/write property value, cause is unknown (insufficient + permissions, no such property, invalid value, other)""" + def __init__(self, prop): - super().__init__('Failed to access \'%s\' property' % prop) + super().__init__("Failed to access '%s' property" % prop) + # legacy name QubesDaemonNoResponseError = QubesDaemonAccessError