Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Task/WP-80 Implement dynamic execution system selection #921

Open
wants to merge 34 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
19c02c3
Working version of execution system changes
chandra-tacc Nov 17, 2023
31ae843
Add tests, fix issues found from unit tests
chandra-tacc Dec 17, 2023
95558cf
Fix job history and also lint
chandra-tacc Dec 18, 2023
560aedf
Use one attribute for exec systems instead of two
chandra-tacc Feb 2, 2024
b64317b
Merge branch 'main' into task/WP-80-execution-system
chandra-tacc Feb 10, 2024
9c3d577
Fix formatting
chandra-tacc Feb 10, 2024
e91c26b
Merge branch 'main' into task/WP-80-execution-system
chandra-tacc Feb 13, 2024
4c4251b
Sort system list in UI
chandra-tacc Feb 14, 2024
460de43
Merge branch 'main' into task/WP-80-execution-system
rstijerina Feb 27, 2024
e4242b4
Address code review comments
chandra-tacc Feb 28, 2024
3ef9a53
Adjusted exec system label text and fixed jest tests
chandra-tacc Mar 1, 2024
9014370
Working version of execution system changes
chandra-tacc Nov 17, 2023
ffa33a6
Add tests, fix issues found from unit tests
chandra-tacc Dec 17, 2023
d1146f6
Fix job history and also lint
chandra-tacc Dec 18, 2023
27e9476
Use one attribute for exec systems instead of two
chandra-tacc Feb 2, 2024
5bd7a39
Fix formatting
chandra-tacc Feb 10, 2024
e8acb8e
Sort system list in UI
chandra-tacc Feb 14, 2024
f5271ab
Address code review comments
chandra-tacc Feb 28, 2024
8be2d32
Adjusted exec system label text and fixed jest tests
chandra-tacc Mar 1, 2024
b2fad67
Fix bug related to job history execution system
chandra-tacc Mar 21, 2024
5de01b2
Merge branch 'task/WP-80-execution-system' of github.com:TACC/Core-Po…
chandra-tacc Mar 21, 2024
f6dcb19
Merge fix
chandra-tacc Mar 21, 2024
c31bc64
Redo the fix on job history
chandra-tacc Mar 21, 2024
ffaf67e
Rework commit for exec and allocation
chandra-tacc Apr 4, 2024
11b5ed9
Prettier, lint and test fix
chandra-tacc Apr 17, 2024
ed22ec7
Merge branch 'main' into task/WP-80-execution-system
chandra-tacc Apr 17, 2024
6d0bf31
Merge branch 'main' into task/WP-80-execution-system
chandra-tacc Apr 18, 2024
e33ccbf
Fix merge issues
chandra-tacc Apr 18, 2024
7a85c9d
Make exec system dependent on allocation
chandra-tacc Apr 30, 2024
3a2920f
Merge branch 'main' into task/WP-80-execution-system
chandra-tacc May 3, 2024
cd616d5
Fix job history display of system name
chandra-tacc May 3, 2024
ce7a917
Merge branch 'main' into task/WP-80-execution-system
chandra-tacc May 16, 2024
bfd9869
Handle max memory on a system
chandra-tacc May 17, 2024
0e30fe4
Merge branch 'task/WP-80-execution-system' of github.com:TACC/Core-Po…
chandra-tacc May 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
252 changes: 158 additions & 94 deletions client/src/components/Applications/AppForm/AppForm.jsx

Large diffs are not rendered by default.

479 changes: 470 additions & 9 deletions client/src/components/Applications/AppForm/AppForm.test.js

Large diffs are not rendered by default.

125 changes: 120 additions & 5 deletions client/src/components/Applications/AppForm/AppFormUtils.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import * as Yup from 'yup';
import { getSystemName } from 'utils/systems';
import { getExecSystemFromId } from 'utils/apps';

export const TARGET_PATH_FIELD_PREFIX = '_TargetPath_';

export const getQueueMaxMinutes = (app, queueName) => {
return app.exec_sys.batchLogicalQueues.find((q) => q.name === queueName)
.maxMinutes;
export const getQueueMaxMinutes = (exec_sys, queueName) => {
return (
exec_sys?.batchLogicalQueues.find((q) => q.name === queueName)
?.maxMinutes ?? 0
);
};

/**
Expand All @@ -16,6 +18,9 @@ export const getQueueMaxMinutes = (app, queueName) => {
* @returns {Yup.number()} min/max validation of max minutes
*/
export const getMaxMinutesValidation = (queue) => {
if (!queue) {
return Yup.number();
}
return Yup.number()
.min(
queue.minMinutes,
Expand Down Expand Up @@ -83,6 +88,9 @@ export const createMaxRunTimeRegex = (maxRunTime) => {
* @returns {Yup.number()} min/max validation of node count
*/
export const getNodeCountValidation = (queue) => {
if (!queue) {
return Yup.number();
}
return Yup.number()
.integer('Node Count must be an integer.')
.min(
Expand All @@ -103,6 +111,9 @@ export const getNodeCountValidation = (queue) => {
* @returns {Yup.number()} min/max validation of coresPerNode
*/
export const getCoresPerNodeValidation = (queue) => {
if (!queue) {
return Yup.number();
}
if (queue.maxCoresPerNode === -1) {
return Yup.number().integer();
}
Expand All @@ -123,8 +134,9 @@ export const getCoresPerNodeValidation = (queue) => {
* @returns {Object} updated/fixed values
*/
export const updateValuesForQueue = (app, values) => {
const exec_sys = getExecSystemFromId(app, values.execSystemId);
const updatedValues = { ...values };
const queue = app.exec_sys.batchLogicalQueues.find(
const queue = exec_sys.batchLogicalQueues.find(
(q) => q.name === values.execSystemLogicalQueue
);

Expand Down Expand Up @@ -168,6 +180,81 @@ export const updateValuesForQueue = (app, values) => {
return updatedValues;
};

/**
* Get the default queue for a execution system.
* Queue Name determination order:
* 1. Use given queue name.
* 2. Otherwise, use the app default queue.
* 3. Otherwise, use the execution system default queue.
*
* @function
* @param {any} app App Shape defined in AppForm.jsx
* @param {any} exec_sys execution system, shape defined in AppForm.jsx
* @returns {String} queue_name nullable, queue name to lookup
*/
export const getQueueValueForExecSystem = (app, exec_sys, queue_name) => {
const queueName =
queue_name ??
app.definition.jobAttributes.execSystemLogicalQueue ??
exec_sys?.batchDefaultLogicalQueue;
return (
exec_sys?.batchLogicalQueues.find((q) => q.name === queueName) ||
exec_sys?.batchLogicalQueues[0]
);
};

/**
* Apply the following two filters and get the list of queues applicable.
* Filters:
* 1. If Node and Core per Node is enabled, only allow
* queues which match min and max node count with job attributes
* 2. if queue filter list is set, only allow queues in that list.
* @returns list of queues in sorted order
*/
export const getAppQueueValues = (app, queues) => {
/*
Hide queues for which the app default nodeCount does not meet the minimum or maximum requirements
while hideNodeCountAndCoresPerNode is true
*/
return (queues ?? [])
.filter(
(q) =>
!app.definition.notes.hideNodeCountAndCoresPerNode ||
(app.definition.jobAttributes.nodeCount >= q.minNodeCount &&
app.definition.jobAttributes.nodeCount <= q.maxNodeCount)
)
.map((q) => q.name)
.filter((queueName) =>
app.definition.notes.queueFilter
? app.definition.notes.queueFilter.includes(queueName)
: true
)
.sort();
};

/**
* Build a map of allocations applicable to each execution
* system based on the host match.
* Handle case where dynamic execution system is provided.
* If there is no allocation for a given exec system, skip it.
* @param {*} app
* @param {*} allocations
* @returns a Map of allocations applicable to each execution system.
*/
export const matchExecSysWithAllocations = (app, allocations) => {
return app.execSystems.reduce((map, exec_sys) => {
const matchingExecutionHost = Object.keys(allocations.hosts).find(
(host) => exec_sys.host === host || exec_sys.host.endsWith(`.${host}`)
);

if (matchingExecutionHost) {
map.set(exec_sys.id, allocations.hosts[matchingExecutionHost]);
}

return map;
}, new Map());
};

/**
* Get the field name used for target path in AppForm
*
Expand Down Expand Up @@ -236,3 +323,31 @@ export const checkAndSetDefaultTargetPath = (targetPathFieldValue) => {

return targetPathFieldValue;
};

/**
* Gets the execution systems with portal's default allocation.
* It will return empty list, if there is no allocation system matching portal's
* default allocation.
* @param {Map} execSystemAllocationsMap
* @param {String} portalAllocation
*/
export const getExecSystemsForPortalAllocation = (
execSystemAllocationsMap,
portalAllocation
) => {
// Look at each execution system and its corressponding allocations
// Gather all execution system whose allocation is the default portal allocation.
const execSystems = [];
execSystemAllocationsMap.forEach((execAllocations, execSystem) => {
if (execAllocations.includes(portalAllocation)) {
execSystems.push(execSystem);
}
});
// If user does not have any execution systems matching portalAllocation,
// this list will be empty.
return execSystems;
};

export const isAppUsingDynamicExecSystem = (app) => {
return !!app.definition.notes.dynamicExecSystems;
};
15 changes: 9 additions & 6 deletions client/src/components/Applications/AppForm/AppFormUtils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import { helloWorldAppFixture } from './fixtures/AppForm.app.fixture';
import { getNodeCountValidation, updateValuesForQueue } from './AppFormUtils';

describe('AppFormUtils', () => {
const normalQueue = helloWorldAppFixture.exec_sys.batchLogicalQueues.find(
(q) => q.name === 'normal'
);
const smallQueue = helloWorldAppFixture.exec_sys.batchLogicalQueues.find(
(q) => q.name === 'small'
);
const normalQueue =
helloWorldAppFixture.execSystems[0].batchLogicalQueues.find(
(q) => q.name === 'normal'
);
const smallQueue =
helloWorldAppFixture.execSystems[0].batchLogicalQueues.find(
(q) => q.name === 'small'
);

const parallelFronteraApp = {
...helloWorldAppFixture,
Expand Down Expand Up @@ -37,6 +39,7 @@ describe('AppFormUtils', () => {
nodeCount: 1,
coresPerNode: 1,
maxMinutes: '',
execSystemId: 'frontera',
};

it('handles node count validation', () => {
Expand Down