]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
pybind/mgr: add a wrapper exception for use with Responder
authorJohn Mulligan <jmulligan@redhat.com>
Mon, 11 Apr 2022 19:32:42 +0000 (15:32 -0400)
committerAdam King <adking@redhat.com>
Sat, 21 May 2022 23:22:05 +0000 (19:22 -0400)
In order to best get a "real" exception converted to something
that can be cleanly sent to the mgr response, this new exception
type can be invoked directly, or with the wrap method to automatically
pull as many properties as possibly from the original exception.

Signed-off-by: John Mulligan <jmulligan@redhat.com>
(cherry picked from commit 777814d59429bc28eeee0b13201b60b672226753)

src/pybind/mgr/object_format.py

index 2df6584b908090b9c4b13371e72d91f9ca7cd6ea..7ff15c6a616b15235c590821be56c5c8ce474bd1 100644 (file)
@@ -16,6 +16,8 @@ from typing import (
     Optional,
     TYPE_CHECKING,
     Tuple,
+    Type,
+    TypeVar,
     Union,
 )
 
@@ -267,6 +269,45 @@ class UnsupportedFormat(ErrorResponseBase):
         return -errno.EINVAL, "", f"Unsupported format: {self.format_name}"
 
 
+class ErrorResponse(ErrorResponseBase):
+    """General exception convertible to a mgr response."""
+
+    E = TypeVar("E", bound="ErrorResponse")
+
+    def __init__(self, status: str, return_value: Optional[int] = None) -> None:
+        self.return_value = (
+            return_value if return_value is not None else -errno.EINVAL
+        )
+        self.status = status
+
+    def format_response(self) -> Tuple[int, str, str]:
+        return (self.return_value, "", self.status)
+
+    def mgr_return_value(self) -> int:
+        return self.return_value
+
+    @property
+    def errno(self) -> int:
+        rv = self.return_value
+        return -rv if rv < 0 else rv
+
+    def __repr__(self) -> str:
+        return f"ErrorResponse({self.status!r}, {self.return_value!r})"
+
+    @classmethod
+    def wrap(
+        cls: Type[E], exc: Exception, return_value: Optional[int] = None
+    ) -> E:
+        if return_value is None:
+            try:
+                return_value = -int(getattr(exc, "errno"))
+            except (AttributeError, ValueError):
+                pass
+        err = cls(str(exc), return_value=return_value)
+        setattr(err, "__cause__", exc)
+        return err
+
+
 def _get_requested_format(f: ObjectResponseFuncType, kw: Dict[str, Any]) -> str:
     # todo: leave 'format' in kw dict iff its part of f's signature
     return kw.pop("format", None)