From b95ce28244a169092913c4ec48d8472d46a4c054 Mon Sep 17 00:00:00 2001 From: Naved Ansari Date: Fri, 22 Jun 2018 18:25:02 -0400 Subject: [PATCH] Catch a bunch of errors everywhere: This PR is pretty much copy-pasta from @chemistry-sourabh's #111 PR since dealing with the merge conflicts was nasty and it made some changes which I now feel are not necessary. This has some fixes for database issues, ceph image issues, and tgt targets. --- ims/database/image.py | 27 +++++++++++++++++++++++++-- ims/einstein/ceph.py | 10 +++++++--- ims/einstein/iscsi/tgt.py | 13 +++++++++---- ims/exception/db_exceptions.py | 14 ++++++++++++++ 4 files changed, 55 insertions(+), 9 deletions(-) diff --git a/ims/database/image.py b/ims/database/image.py index 4864716..6fc1187 100644 --- a/ims/database/image.py +++ b/ims/database/image.py @@ -1,7 +1,7 @@ from sqlalchemy import Boolean, ForeignKey from sqlalchemy import Column, Integer, String from sqlalchemy import UniqueConstraint -from sqlalchemy.exc import SQLAlchemyError +from sqlalchemy.exc import SQLAlchemyError, IntegrityError from sqlalchemy.orm import relationship import ims.exception.db_exceptions as db_exceptions @@ -37,6 +37,15 @@ def insert(self, image_name, project_id, parent_id=None, is_public=False, img.id = id self.connection.session.add(img) self.connection.session.commit() + except IntegrityError: + logger.info("Integrity Error Caused for %s in project with id %d " + "and parent id %d" % (image_name, project_id, + parent_id)) + self.connection.session.rollback() + actual_parent_id = self.fetch_parent_id_with_project_id(image_name, + project_id) + if actual_parent_id != parent_id: + raise db_exceptions.ImageExistsException(image_name) except SQLAlchemyError as e: self.connection.session.rollback() raise db_exceptions.ORMException(e.message) @@ -61,7 +70,8 @@ def delete_with_name_from_project(self, name, project_name): self.connection.session.delete(image) self.connection.session.commit() else: - raise db_exceptions.ImageNotFoundException(name) + logger.info("%s in project %s already " + "deleted" % (name, project_name)) except SQLAlchemyError as e: self.connection.session.rollback() raise db_exceptions.ORMException(e.message) @@ -230,6 +240,19 @@ def fetch_parent_id(self, project_name, name): except SQLAlchemyError as e: raise db_exceptions.ORMException(e.message) + @log + def fetch_parent_id_with_project_id(self, name, project_id): + try: + image = self.connection.session.query(Image). \ + filter_by(project_id=project_id).filter_by( + name=name).one_or_none() + if image is not None and image.parent_id is not None: + return image.parent_id + elif image is None: + raise db_exceptions.ImageNotFoundException(name) + except SQLAlchemyError as e: + raise db_exceptions.ORMException(e.message) + def fetch_images(self): try: images = self.connection.session.query(Image) diff --git a/ims/einstein/ceph.py b/ims/einstein/ceph.py index 4d78f73..e653315 100755 --- a/ims/einstein/ceph.py +++ b/ims/einstein/ceph.py @@ -116,7 +116,11 @@ def clone(self, parent_img_name, parent_snap_name, clone_img_name): img_name = parent_snap_name raise file_system_exceptions.ImageNotFoundException(img_name) except rbd.ImageExists: - raise file_system_exceptions.ImageExistsException(clone_img_name) + logger.info("Clone with name %s exists" % clone_img_name) + actual_parent = self.get_parent_info(clone_img_name)[1] + if actual_parent != parent_img_name: + raise file_system_exceptions.ImageExistsException( + clone_img_name) # No Clue when will this be raised so not testing except rbd.FunctionNotSupported: raise file_system_exceptions.FunctionNotSupportedException() @@ -145,15 +149,15 @@ def list_children(self, img_id, parent_snap): def remove(self, img_id): try: self.rbd.remove(self.context, img_id) - return True except rbd.ImageNotFound: - raise file_system_exceptions.ImageNotFoundException(img_id) + logger.info("%s image is not found" % img_id) # Don't know how to raise this except rbd.ImageBusy: raise file_system_exceptions.ImageBusyException(img_id) # Forgot to test this except rbd.ImageHasSnapshots: raise file_system_exceptions.ImageHasSnapshotException(img_id) + return true @log def write(self, img_id, data, offset): diff --git a/ims/einstein/iscsi/tgt.py b/ims/einstein/iscsi/tgt.py index 08ec020..3ab096a 100644 --- a/ims/einstein/iscsi/tgt.py +++ b/ims/einstein/iscsi/tgt.py @@ -125,14 +125,19 @@ def remove_target(self, target_name): try: targets = self.list_targets() if target_name in targets: - os.remove(os.path.join(self.TGT_ISCSI_CONFIG, - target_name + ".conf")) command = "tgt-admin -f --delete {0}".format(target_name) output = shell.call(command, sudo=True) logger.debug("Output = %s", output) + os.remove(os.path.join(self.TGT_ISCSI_CONFIG, + target_name + ".conf")) else: - raise iscsi_exceptions.TargetDoesntExistException() - except (IOError, OSError) as e: + logger.info("%s target doesnt exist" % target_name) + except OSError as e: + if "[Errno 2] No such file or directory" in str(e): + logger.info("tgt: Target file did not exist") + else: + raise iscsi_exceptions.TargetDeletionFailed(str(e)) + except IOError as e: raise iscsi_exceptions.TargetDeletionFailed(str(e)) except shell_exceptions.CommandFailedException as e: raise iscsi_exceptions.TargetDeletionFailed(str(e)) diff --git a/ims/exception/db_exceptions.py b/ims/exception/db_exceptions.py index 1979b68..177e919 100644 --- a/ims/exception/db_exceptions.py +++ b/ims/exception/db_exceptions.py @@ -27,6 +27,20 @@ def __str__(self): return self.name + " not found" +class ImageExistsException(DBException): + """ Should be raised when an image with the same name exists """ + + @property + def status_code(self): + return 500 + + def __init__(self, name): + self.name = name + + def __str__(self): + return self.name + " already exists" + + class ImageHasClonesException(DBException): @property def status_code(self):