mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Merge pull request #17390 from davelopez/cancel_deleted_user_jobs
Cancel all active jobs when the user is deleted
This commit is contained in:
@@ -40,6 +40,7 @@ from galaxy.managers import (
|
||||
)
|
||||
from galaxy.managers.base import combine_lists
|
||||
from galaxy.model import (
|
||||
Job,
|
||||
User,
|
||||
UserAddress,
|
||||
UserQuotaUsage,
|
||||
@@ -161,6 +162,21 @@ class UserManager(base.ModelManager, deletable.PurgableManagerMixin):
|
||||
"The configuration of this Galaxy instance does not allow admins to delete users."
|
||||
)
|
||||
super().delete(user, flush=flush)
|
||||
self._stop_all_jobs_from_user(user)
|
||||
|
||||
def _stop_all_jobs_from_user(self, user):
|
||||
active_jobs = self._get_all_active_jobs_from_user(user)
|
||||
session = self.session()
|
||||
for job in active_jobs:
|
||||
job.mark_deleted(self.app.config.track_jobs_in_database)
|
||||
with transaction(session):
|
||||
session.commit()
|
||||
|
||||
def _get_all_active_jobs_from_user(self, user: User) -> List[Job]:
|
||||
"""Get all jobs that are not ready yet and belong to the given user."""
|
||||
stmt = select(Job).where(and_(Job.user_id == user.id, Job.state.in_(Job.non_ready_states)))
|
||||
jobs = self.session().scalars(stmt)
|
||||
return jobs
|
||||
|
||||
def undelete(self, user, flush=True):
|
||||
"""Remove the deleted flag for the given user."""
|
||||
|
||||
@@ -2,13 +2,18 @@ from galaxy_test.api._framework import ApiTestCase
|
||||
from galaxy_test.base.api_asserts import assert_object_id_error
|
||||
from galaxy_test.base.decorators import (
|
||||
requires_admin,
|
||||
requires_new_history,
|
||||
requires_new_user,
|
||||
)
|
||||
from galaxy_test.base.populators import skip_without_tool
|
||||
from galaxy_test.base.populators import (
|
||||
DatasetPopulator,
|
||||
skip_without_tool,
|
||||
)
|
||||
|
||||
TEST_USER_EMAIL = "user_for_users_index_test@bx.psu.edu"
|
||||
TEST_USER_EMAIL_INDEX_DELETED = "user_for_users_index_deleted_test@bx.psu.edu"
|
||||
TEST_USER_EMAIL_DELETE = "user_for_delete_test@bx.psu.edu"
|
||||
TEST_USER_EMAIL_DELETE_CANCEL_JOBS = "user_for_delete_cancel_jobs_test@bx.psu.edu"
|
||||
TEST_USER_EMAIL_PURGE = "user_for_purge_test@bx.psu.edu"
|
||||
TEST_USER_EMAIL_UNDELETE = "user_for_undelete_test@bx.psu.edu"
|
||||
TEST_USER_EMAIL_SHOW = "user_for_show_test@bx.psu.edu"
|
||||
@@ -129,6 +134,45 @@ class TestUsersApi(ApiTestCase):
|
||||
undeleted_user = self._get(f"users/{user['id']}", admin=True).json()
|
||||
assert undeleted_user["deleted"] is False, undeleted_user
|
||||
|
||||
@requires_admin
|
||||
@requires_new_user
|
||||
@requires_new_history
|
||||
@skip_without_tool("cat_data_and_sleep")
|
||||
def test_delete_user_cancel_all_jobs(self):
|
||||
dataset_populator = DatasetPopulator(self.galaxy_interactor)
|
||||
with self._different_user(TEST_USER_EMAIL_DELETE_CANCEL_JOBS):
|
||||
user_id = self._get_current_user_id()
|
||||
history_id = dataset_populator.new_history()
|
||||
hda_id = dataset_populator.new_dataset(history_id)["id"]
|
||||
|
||||
inputs = {
|
||||
"input1": {"src": "hda", "id": hda_id},
|
||||
"sleep_time": 6000,
|
||||
}
|
||||
run_response = dataset_populator.run_tool_raw(
|
||||
"cat_data_and_sleep",
|
||||
inputs,
|
||||
history_id,
|
||||
)
|
||||
self._assert_status_code_is_ok(run_response)
|
||||
|
||||
job_id = run_response.json()["jobs"][0]["id"]
|
||||
|
||||
# Wait a bit for the job to be ready
|
||||
expected_job_states = ["new", "queued", "running"]
|
||||
dataset_populator.wait_for_job(job_id, ok_states=expected_job_states)
|
||||
|
||||
# Get the job state
|
||||
job_response = self._get(f"jobs/{job_id}").json()
|
||||
assert job_response["state"] in expected_job_states, job_response
|
||||
|
||||
# Delete user will cancel all jobs
|
||||
self._delete(f"users/{user_id}", admin=True)
|
||||
|
||||
# Get the job state again (this time as admin), it should be deleting
|
||||
job_response = self._get(f"jobs/{job_id}", admin=True).json()
|
||||
assert job_response["state"] == "deleting", job_response
|
||||
|
||||
@requires_new_user
|
||||
def test_information(self):
|
||||
user = self._setup_user(TEST_USER_EMAIL)
|
||||
|
||||
Reference in New Issue
Block a user