Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ interface SessionActionButtonsProps {
}

const isActive = (session: SessionActionButtonsFragment$data) => {
if (session?.type === 'system') {
return session?.status === 'RUNNING';
}
return !['TERMINATED', 'CANCELLED', 'TERMINATING'].includes(
session?.status || '',
);
Expand Down Expand Up @@ -283,9 +286,7 @@ const SessionActionButtons: React.FC<SessionActionButtonsProps> = ({
<Tooltip title={t('data.explorer.RunSSH/SFTPserver')}>
<Button
type="primary"
disabled={
!isAppSupported(session) || !isActive(session) || !isOwner
}
disabled={!isActive(session) || !isOwner}
size={size}
icon={<BAISftpIcon />}
onClick={() => {
Expand Down
30 changes: 7 additions & 23 deletions react/src/components/FileBrowserButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,10 @@ import { useTranslation } from 'react-i18next';
import { graphql, useFragment } from 'react-relay';
import { FileBrowserButtonFragment$key } from 'src/__generated__/FileBrowserButtonFragment.graphql';
import { useCurrentDomainValue, useSuspendedBackendaiClient } from 'src/hooks';
import { useSetBAINotification } from 'src/hooks/useBAINotification';
import { useCurrentProjectValue } from 'src/hooks/useCurrentProject';
import { useDefaultFileBrowserImageWithFallback } from 'src/hooks/useDefaultImagesWithFallback';
import { useMergedAllowedStorageHostPermission } from 'src/hooks/useMergedAllowedStorageHostPermission';
import {
startSessionErrorCodes,
StartSessionWithDefaultValue,
useStartSession,
} from 'src/hooks/useStartSession';
Expand Down Expand Up @@ -48,7 +46,6 @@ const FileBrowserButton: React.FC<FileBrowserButtonProps> = ({
const { getErrorMessage } = useErrorMessageResolver();
const { startSessionWithDefault, upsertSessionNotification } =
useStartSession();
const { upsertNotification } = useSetBAINotification();

const filebrowserImage = useDefaultFileBrowserImageWithFallback();

Expand Down Expand Up @@ -102,6 +99,8 @@ const FileBrowserButton: React.FC<FileBrowserButtonProps> = ({
return;
}
const fileBrowserFormValue: StartSessionWithDefaultValue = {
// If the resource setting is not included when the session is created,
// it is created with the value determined by the server.
sessionName: `filebrowser-${vfolder.row_id}`,
sessionType: 'interactive',
// use default file browser image if configured and allowed
Expand All @@ -112,17 +111,14 @@ const FileBrowserButton: React.FC<FileBrowserButtonProps> = ({
cluster_mode: 'single-node',
cluster_size: 1,
mount_ids: [vfolder.row_id?.replaceAll('-', '') || ''],
resource: {
cpu: 1,
mem: '0.5g',
},
};

await startSessionWithDefault(fileBrowserFormValue)
.then((results) => {
if (results?.fulfilled && results.fulfilled.length > 0) {
upsertSessionNotification(results.fulfilled, [
{
key: `filebrowser-${vfolder.row_id}`,
extraData: {
appName: 'filebrowser',
} as PrimaryAppOption,
Expand All @@ -131,22 +127,10 @@ const FileBrowserButton: React.FC<FileBrowserButtonProps> = ({
}
if (results?.rejected && results.rejected.length > 0) {
const error = results.rejected[0].reason;
if (
_.includes(
error.message,
startSessionErrorCodes.DUPLICATED_SESSION,
)
) {
upsertNotification({
key: `filebrowser-${vfolder.row_id}`,
open: true,
});
} else {
modal.error({
title: error?.title,
content: getErrorMessage(error),
});
}
modal.error({
title: error?.title,
content: getErrorMessage(error),
});
}
})
.catch((error) => {
Expand Down
43 changes: 7 additions & 36 deletions react/src/components/SFTPServerButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,13 @@ import { useTranslation } from 'react-i18next';
import { graphql, useFragment } from 'react-relay';
import { SFTPServerButtonFragment$key } from 'src/__generated__/SFTPServerButtonFragment.graphql';
import { useCurrentDomainValue, useSuspendedBackendaiClient } from 'src/hooks';
import { useSetBAINotification } from 'src/hooks/useBAINotification';
import {
useCurrentProjectValue,
useResourceGroupsForCurrentProject,
} from 'src/hooks/useCurrentProject';
import { useDefaultSystemSSHImageWithFallback } from 'src/hooks/useDefaultImagesWithFallback';
import { useMergedAllowedStorageHostPermission } from 'src/hooks/useMergedAllowedStorageHostPermission';
import {
startSessionErrorCodes,
StartSessionWithDefaultValue,
useStartSession,
} from 'src/hooks/useStartSession';
Expand Down Expand Up @@ -53,10 +51,8 @@ const SFTPServerButton: React.FC<SFTPServerButtonProps> = ({
const { getErrorMessage } = useErrorMessageResolver();
const { startSessionWithDefault, upsertSessionNotification } =
useStartSession();
const { upsertNotification } = useSetBAINotification();

const { systemSSHImage, systemSSHImageInfo } =
useDefaultSystemSSHImageWithFallback();
const { systemSSHImage } = useDefaultSystemSSHImageWithFallback();

const vfolder = useFragment(
graphql`
Expand Down Expand Up @@ -110,18 +106,9 @@ const SFTPServerButton: React.FC<SFTPServerButtonProps> = ({
/>
}
action={async () => {
const resource: StartSessionWithDefaultValue['resource'] = {
cpu:
_.toNumber(
_.find(systemSSHImageInfo?.resource_limits, { key: 'cpu' })
?.min,
) || 2,
mem:
_.find(systemSSHImageInfo?.resource_limits, { key: 'mem' })
?.min || '0.5g',
};

const sftpSessionConf: StartSessionWithDefaultValue = {
// If the resource setting is not included when the session is created,
// it is created with the value determined by the server.
sessionName: `sftp-${vfolder?.row_id}`,
sessionType: 'system',
// use default system SSH image if configured and allowed
Expand All @@ -142,10 +129,6 @@ const SFTPServerButton: React.FC<SFTPServerButtonProps> = ({
cluster_size: 1,
mount_ids: [vfolder?.row_id?.replaceAll('-', '') || ''],
resourceGroup: sftpScalingGroupByCurrentProject?.[0],
resource: {
cpu: resource.cpu < 2 ? 2 : resource.cpu,
mem: resource.mem,
},
};

await startSessionWithDefault(sftpSessionConf)
Expand All @@ -160,22 +143,10 @@ const SFTPServerButton: React.FC<SFTPServerButtonProps> = ({
}
if (results?.rejected && results.rejected.length > 0) {
const error = results.rejected[0].reason;
if (
_.includes(
error.message,
startSessionErrorCodes.DUPLICATED_SESSION,
)
) {
upsertNotification({
key: `sftp-${vfolder?.row_id}`,
open: true,
});
} else {
modal.error({
title: error?.title,
content: getErrorMessage(error),
});
}
modal.error({
title: error?.title,
content: getErrorMessage(error),
});
}
})
.catch((error) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ const ResourceAllocationFormItems: React.FC<
accessible_scaling_groups,
(group) => group?.name === currentResourceGroupInForm,
);
const currentResourceValue = Form.useWatch(['resource']);
const currentImage = Form.useWatch(['environments', 'image'], {
form,
preserve: true,
Expand Down Expand Up @@ -205,14 +206,19 @@ const ResourceAllocationFormItems: React.FC<
}, [currentImage, acceleratorSlotsInRG, currentEnvironmentManual]);

useEffect(() => {
if (!currentResourceValue) {
form.setFieldsValue({
allocationPreset: 'auto-select',
});
}
if (supportedAcceleratorTypesInRGByImage?.length === 0) {
form.setFieldsValue({
resource: {
accelerator: 0,
},
});
}
}, [supportedAcceleratorTypesInRGByImage, form]);
}, [supportedAcceleratorTypesInRGByImage, form, currentResourceValue]);

const sessionSliderLimitAndRemaining = {
min: 1,
Expand Down
55 changes: 23 additions & 32 deletions react/src/hooks/useStartSession.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,6 @@ interface CreateSessionInfo {
resources: SessionResources;
}

export const startSessionErrorCodes = {
DUPLICATED_SESSION: 'DUPLICATED_SESSION',
};

export const SESSION_LAUNCHER_NOTI_PREFIX = 'session-launcher:';

// Field names that have default values in SessionLauncherFormValue
Expand Down Expand Up @@ -136,7 +132,7 @@ export const useStartSession = () => {
baiClient._config.default_session_environment,
),
}),
...RESOURCE_ALLOCATION_INITIAL_FORM_VALUES,
..._.omit(RESOURCE_ALLOCATION_INITIAL_FORM_VALUES, ['resource']),
resourceGroup: currentGlobalResourceGroup || undefined,
};

Expand Down Expand Up @@ -214,26 +210,30 @@ export const useStartSession = () => {

config: {
// Resource allocation
resources: {
cpu: values.resource.cpu,
mem: values.resource.mem,
// Add accelerator only if specified
...(values.resource?.acceleratorType &&
values.resource?.accelerator &&
values.resource?.accelerator > 0
? {
[values.resource.acceleratorType]:
values.resource.accelerator,
}
: undefined),
},
...(values?.resource && {
resources: {
cpu: values?.resource?.cpu,
mem: values?.resource?.mem,
// Add accelerator only if specified
...(values.resource?.acceleratorType &&
values.resource?.accelerator &&
values.resource?.accelerator > 0
? {
[values.resource.acceleratorType]:
values.resource.accelerator,
}
: undefined),
},
}),
scaling_group: values.owner?.enabled
? values.owner.project
: values.resourceGroup,
resource_opts: {
shmem: values.resource.shmem,
// allow_fractional_resource_fragmentation can be added here if needed
},
...(values?.resource && {
resource_opts: {
shmem: values?.resource?.shmem,
// allow_fractional_resource_fragmentation can be added here if needed
},
}),

// Storage configuration
[supportsMountById ? 'mount_ids' : 'mounts']: values.mount_ids,
Expand Down Expand Up @@ -277,21 +277,12 @@ export const useStartSession = () => {
.createIfNotExists(
sessionInfo.kernelName,
formattedSessionName,
sessionInfo.resources,
sessionInfo?.resources,
undefined,
sessionInfo.architecture,
)
.then(
(res: { created: boolean; status: string; sessionId: string }) => {
// When session is already created with the same name, the status code
// is 200, but the response body has 'created' field as false.
// For such cases, we throw an error to be handled by using component.
if (!res?.created) {
const error = new Error(
startSessionErrorCodes.DUPLICATED_SESSION,
);
throw error;
}
return res;
},
)
Expand Down
2 changes: 1 addition & 1 deletion react/src/pages/SessionLauncherPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ const SessionLauncherPage = () => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

const mergedInitialValues = useMemo(() => {
const mergedInitialValues: SessionLauncherFormValue = useMemo(() => {
return _.merge({}, defaultFormValues, formValuesFromQueryParams);
}, [defaultFormValues, formValuesFromQueryParams]);

Expand Down