Skip to content

Commit

Permalink
Improved error messages for private object stores.
Browse files Browse the repository at this point in the history
  • Loading branch information
jmchilton committed Mar 19, 2024
1 parent 7850c04 commit 6cd4f68
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { useDatasetStore } from "@/stores/datasetStore";
import { type ItemUrls } from ".";
import DatasetActions from "./DatasetActions.vue";
import DatasetMiscInfo from "./DatasetMiscInfo.vue";
const datasetStore = useDatasetStore();
Expand Down Expand Up @@ -56,9 +57,7 @@ function toggleHighlights() {
result.genome_build
}}</BLink>
</span>
<div v-if="result.misc_info" class="info">
<span class="value">{{ result.misc_info }}</span>
</div>
<DatasetMiscInfo v-if="result.misc_info" :misc-info="result.misc_info" />
</div>
<DatasetActions
:item="result"
Expand Down
64 changes: 64 additions & 0 deletions client/src/components/History/Content/Dataset/DatasetMiscInfo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<script setup lang="ts">
import { computed, ref, watch } from "vue";
interface Props {
miscInfo: string;
}
const showErrorHelp = ref(false);
const sharingError = ref(false);
// old sharable error: Attempted to create shared output datasets in objectstore with sharing disabled
// new sharable error: Job attempted to create sharable output datasets in a storage location with sharing disabled
const sharingErrorRex: RegExp = /with sharing disabled/g;
const knownErrors = [{ regex: sharingErrorRex, modalRef: sharingError }];
const props = defineProps<Props>();
const fixable = computed(() => {
return true;
});
watch(
props,
() => {
for (const knownError of knownErrors) {
const regex = knownError.regex;
if (props.miscInfo.match(regex)) {
knownError.modalRef.value = true;
}
}
},
{ immediate: true }
);
function showHelp() {
showErrorHelp.value = true;
}
</script>

<template>
<div class="info">
<b-modal v-if="sharingError" v-model="showErrorHelp" title="Dataset Sharing Misconfigured" ok-only>
<p>
This error message indicates that your history is setup to allow sharing but your job was run in a
configuration to target a storage location that explicitly disables sharing.
</p>
<p>
To fix this configure your history so that new datasets are private or target a different storage
location.
</p>
<p>
To re-configure your history, click the history menu and go to the "Set Permissions" option in the
dropdown. This should result in a toggle that allows you to configure the history so that new datasets
are created as private datasets.
</p>
<p>
There are many ways to instead target different storage for your job. This can be selected in the tool
or workflow form right before you execute your job or a different default for your history or user can
be chosen that allows for sharing.
</p>
</b-modal>
<span class="value">{{ miscInfo }} <a v-if="fixable" href="#" @click="showHelp">How do I fix this?</a></span>
</div>
</template>
5 changes: 3 additions & 2 deletions lib/galaxy/jobs/runners/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,10 @@ def put(self, job_wrapper: "MinimalJobWrapper"):
queue_job = job_wrapper.enqueue()
except Exception as e:
queue_job = False
# Required for exceptions thrown by object store incompatiblity.
# Required for exceptions thrown by object store incompatibility.
# tested by test/integration/objectstore/test_private_handling.py
job_wrapper.fail(str(e), exception=e)
message = e.client_message if hasattr(e, "client_message") else str(e)
job_wrapper.fail(message, exception=e)
log.debug(f"Job [{job_wrapper.job_id}] failed to queue {put_timer}")
return
if queue_job:
Expand Down
20 changes: 18 additions & 2 deletions lib/galaxy/objectstore/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1609,6 +1609,22 @@ def ids_per_quota_source(self, include_default_quota_source=False):
return quota_sources


class ObjectCreationProblem(Exception):
pass


# Calling these client_message to make it clear they should use the language of the
# Galaxy UI/UX - for instance "storage location" not "objectstore".
class ObjectCreationProblemSharingDisabled(ObjectCreationProblem):
client_message = "Job attempted to create sharable output datasets in a storage location with sharing disabled"


class ObjectCreationProblemStoreFull(ObjectCreationProblem):
client_message = (
"Job attempted to create output datasets in a full storage location, please contact your admin for more details"
)


class ObjectStorePopulator:
"""Small helper for interacting with the object store and making sure all
datasets from a job end up with the same object_store_id.
Expand All @@ -1635,9 +1651,9 @@ def set_dataset_object_store_id(self, dataset, require_shareable=True):
ensure_non_private = require_shareable
concrete_store = self.object_store.create(dataset, ensure_non_private=ensure_non_private)
if concrete_store.private and require_shareable:
raise Exception("Attempted to create shared output datasets in objectstore with sharing disabled")
raise ObjectCreationProblemSharingDisabled()
except ObjectInvalid:
raise Exception("Unable to create output dataset: object store is full")
raise ObjectCreationProblemStoreFull()
self.object_store_id = dataset.object_store_id # these will be the same thing after the first output


Expand Down

0 comments on commit 6cd4f68

Please sign in to comment.