diff options
| author | Rob van der Linde <rob@catalyst.net.nz> | 2023-06-23 12:24:24 +1200 |
|---|---|---|
| committer | Andrew Bartlett <abartlet@samba.org> | 2023-06-25 23:29:32 +0000 |
| commit | ca4e36d17a8392c6228b791b41024cf1b1db0c93 (patch) | |
| tree | 7696702c4f023e3e4cfd112ec840f740c8a04239 /python | |
| parent | b00761da1d1777943f7ab4ef99dda0866f408053 (diff) | |
| download | samba-ca4e36d17a8392c6228b791b41024cf1b1db0c93.tar.gz samba-ca4e36d17a8392c6228b791b41024cf1b1db0c93.tar.bz2 samba-ca4e36d17a8392c6228b791b41024cf1b1db0c93.zip | |
netcmd: domain: add model exceptions and error handling
* Only handle what we know, otherwise raise the existing LdbError
* Cutom messages added in the model layer so we don't have to do it in
the commands themselves
Signed-off-by: Rob van der Linde <rob@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Diffstat (limited to 'python')
| -rw-r--r-- | python/samba/netcmd/domain/models/auth_silo.py | 13 | ||||
| -rw-r--r-- | python/samba/netcmd/domain/models/exceptions.py | 30 | ||||
| -rw-r--r-- | python/samba/netcmd/domain/models/model.py | 60 |
3 files changed, 88 insertions, 15 deletions
diff --git a/python/samba/netcmd/domain/models/auth_silo.py b/python/samba/netcmd/domain/models/auth_silo.py index 4c40027463d..e694e1874c6 100644 --- a/python/samba/netcmd/domain/models/auth_silo.py +++ b/python/samba/netcmd/domain/models/auth_silo.py @@ -20,8 +20,9 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # -from ldb import FLAG_MOD_ADD, FLAG_MOD_DELETE, Message, MessageElement +from ldb import FLAG_MOD_ADD, FLAG_MOD_DELETE, LdbError, Message, MessageElement +from .exceptions import AddMemberError, RemoveMemberError from .fields import DnField, BooleanField, StringField from .model import Model @@ -65,7 +66,10 @@ class AuthenticationSilo(Model): "msDS-AuthNPolicySiloMembers")) # Update authentication silo. - ldb.modify(message) + try: + ldb.modify(message) + except LdbError as e: + raise AddMemberError(f"Failed to add silo member: {e}") # If the modify operation was successful refresh members field. self.refresh(ldb, fields=["members"]) @@ -85,7 +89,10 @@ class AuthenticationSilo(Model): "msDS-AuthNPolicySiloMembers")) # Update authentication silo. - ldb.modify(message) + try: + ldb.modify(message) + except LdbError as e: + raise RemoveMemberError(f"Failed to remove silo member: {e}") # If the modify operation was successful refresh members field. self.refresh(ldb, fields=["members"]) diff --git a/python/samba/netcmd/domain/models/exceptions.py b/python/samba/netcmd/domain/models/exceptions.py index 01bf3f8c1b8..805c7a221b7 100644 --- a/python/samba/netcmd/domain/models/exceptions.py +++ b/python/samba/netcmd/domain/models/exceptions.py @@ -20,5 +20,33 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # -class MultipleObjectsReturned(Exception): +class ModelError(Exception): + pass + + +class MultipleObjectsReturned(ModelError): + pass + + +class DoesNotExist(ModelError): + pass + + +class AddMemberError(ModelError): + pass + + +class RemoveMemberError(ModelError): + pass + + +class ProtectError(ModelError): + pass + + +class UnprotectError(ModelError): + pass + + +class DeleteError(ModelError): pass diff --git a/python/samba/netcmd/domain/models/model.py b/python/samba/netcmd/domain/models/model.py index f04176131b2..00722c04272 100644 --- a/python/samba/netcmd/domain/models/model.py +++ b/python/samba/netcmd/domain/models/model.py @@ -27,7 +27,8 @@ from ldb import ERR_NO_SUCH_OBJECT, FLAG_MOD_ADD, FLAG_MOD_REPLACE, LdbError,\ Message, MessageElement, SCOPE_BASE, SCOPE_SUBTREE, binary_encode from samba.sd_utils import SDUtils -from .exceptions import MultipleObjectsReturned +from .exceptions import DeleteError, DoesNotExist, MultipleObjectsReturned,\ + ProtectError, UnprotectError from .fields import DateTimeField, DnField, Field, GUIDField, IntegerField,\ StringField @@ -173,7 +174,15 @@ class Model(metaclass=ModelMeta): :param fields: Optional list of field names to refresh """ attrs = [self.fields[f].name for f in fields] if fields else None - res = ldb.search(self.dn, scope=SCOPE_BASE, attrs=attrs) + + # This shouldn't normally happen but in case the object refresh fails. + try: + res = ldb.search(self.dn, scope=SCOPE_BASE, attrs=attrs) + except LdbError as e: + if e.args[0] == ERR_NO_SUCH_OBJECT: + raise DoesNotExist(f"Refresh failed, object gone: {self.dn}") + raise + self._apply(ldb, res[0]) def as_dict(self, include_hidden=False): @@ -225,9 +234,17 @@ class Model(metaclass=ModelMeta): :param ldb: Ldb connection :param kwargs: Search criteria as keyword args """ - result = ldb.search(cls.get_search_dn(ldb), - scope=SCOPE_SUBTREE, - expression=cls.build_expression(**kwargs)) + base_dn = cls.get_search_dn(ldb) + + # If the container does not exist produce a friendly error message. + try: + result = ldb.search(base_dn, + scope=SCOPE_SUBTREE, + expression=cls.build_expression(**kwargs)) + except LdbError as e: + if e.args[0] == ERR_NO_SUCH_OBJECT: + raise DoesNotExist(f"Container does not exist: {base_dn}") + raise # For now this returns a simple generator of model instances. # This could eventually become a QuerySet class if we need to add @@ -262,9 +279,17 @@ class Model(metaclass=ModelMeta): else: raise else: - res = ldb.search(cls.get_search_dn(ldb), - scope=SCOPE_SUBTREE, - expression=cls.build_expression(**kwargs)) + base_dn = cls.get_search_dn(ldb) + + # If the container does not exist produce a friendly error message. + try: + res = ldb.search(base_dn, + scope=SCOPE_SUBTREE, + expression=cls.build_expression(**kwargs)) + except LdbError as e: + if e.args[0] == ERR_NO_SUCH_OBJECT: + raise DoesNotExist(f"Container does not exist: {base_dn}") + raise # Expect to get one object back or raise MultipleObjectsReturned. # For multiple records, please call .query() instead. @@ -382,8 +407,13 @@ class Model(metaclass=ModelMeta): :param ldb: Ldb connection """ - if self.dn is not None: + if self.dn is None: + raise DeleteError("Cannot delete object that doesn't have a dn.") + + try: ldb.delete(self.dn) + except LdbError as e: + raise DeleteError(f"Delete failed: {e}") def protect(self, ldb): """Protect object from accidental deletion. @@ -391,7 +421,11 @@ class Model(metaclass=ModelMeta): :param ldb: Ldb connection """ utils = SDUtils(ldb) - utils.dacl_add_ace(self.dn, "(D;;DTSD;;;WD)") + + try: + utils.dacl_add_ace(self.dn, "(D;;DTSD;;;WD)") + except LdbError as e: + raise ProtectError(f"Failed to protect object: {e}") def unprotect(self, ldb): """Unprotect object from accidental deletion. @@ -399,4 +433,8 @@ class Model(metaclass=ModelMeta): :param ldb: Ldb connection """ utils = SDUtils(ldb) - utils.dacl_delete_aces(self.dn, "(D;;DTSD;;;WD)") + + try: + utils.dacl_delete_aces(self.dn, "(D;;DTSD;;;WD)") + except LdbError as e: + raise UnprotectError(f"Failed to unprotect object: {e}") |
