1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-02 12:25:22 +02:00

feat(gpu): rework docker GPU for UI performance [EE-4918] (#8518)

This commit is contained in:
Ali 2023-03-03 14:47:10 +13:00 committed by GitHub
parent 769c8372fb
commit fd916bc8a2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
52 changed files with 692 additions and 285 deletions

View file

@ -2,10 +2,13 @@ import { FeatureId } from '@/react/portainer/feature-flags/enums';
export default class DockerFeaturesConfigurationController {
/* @ngInject */
constructor($async, $scope, EndpointService, Notifications, StateManager) {
constructor($async, $scope, $state, $analytics, EndpointService, SettingsService, Notifications, StateManager) {
this.$async = $async;
this.$scope = $scope;
this.$state = $state;
this.$analytics = $analytics;
this.EndpointService = EndpointService;
this.SettingsService = SettingsService;
this.Notifications = Notifications;
this.StateManager = StateManager;
@ -35,6 +38,8 @@ export default class DockerFeaturesConfigurationController {
this.save = this.save.bind(this);
this.onChangeField = this.onChangeField.bind(this);
this.onToggleAutoUpdate = this.onToggleAutoUpdate.bind(this);
this.onToggleGPUManagement = this.onToggleGPUManagement.bind(this);
this.onGpusChange = this.onGpusChange.bind(this);
this.onChangeEnableHostManagementFeatures = this.onChangeField('enableHostManagementFeatures');
this.onChangeAllowVolumeBrowserForRegularUsers = this.onChangeField('allowVolumeBrowserForRegularUsers');
this.onChangeDisableBindMountsForRegularUsers = this.onChangeField('disableBindMountsForRegularUsers');
@ -52,6 +57,12 @@ export default class DockerFeaturesConfigurationController {
});
}
onToggleGPUManagement(checked) {
this.$scope.$evalAsync(() => {
this.state.enableGPUManagement = checked;
});
}
onChange(values) {
return this.$scope.$evalAsync(() => {
this.formValues = {
@ -69,6 +80,12 @@ export default class DockerFeaturesConfigurationController {
};
}
onGpusChange(value) {
return this.$async(async () => {
this.endpoint.Gpus = value;
});
}
isContainerEditDisabled() {
const {
disableBindMountsForRegularUsers,
@ -92,7 +109,11 @@ export default class DockerFeaturesConfigurationController {
return this.$async(async () => {
try {
this.state.actionInProgress = true;
const securitySettings = {
const validGpus = this.endpoint.Gpus.filter((gpu) => gpu.name && gpu.value);
const gpus = this.state.enableGPUManagement ? validGpus : [];
const settings = {
enableHostManagementFeatures: this.formValues.enableHostManagementFeatures,
allowBindMountsForRegularUsers: !this.formValues.disableBindMountsForRegularUsers,
allowPrivilegedModeForRegularUsers: !this.formValues.disablePrivilegedModeForRegularUsers,
@ -102,33 +123,53 @@ export default class DockerFeaturesConfigurationController {
allowStackManagementForRegularUsers: !this.formValues.disableStackManagementForRegularUsers,
allowContainerCapabilitiesForRegularUsers: !this.formValues.disableContainerCapabilitiesForRegularUsers,
allowSysctlSettingForRegularUsers: !this.formValues.disableSysctlSettingForRegularUsers,
enableGPUManagement: this.state.enableGPUManagement,
gpus,
};
await this.EndpointService.updateSecuritySettings(this.endpoint.Id, securitySettings);
const publicSettings = await this.SettingsService.publicSettings();
const analyticsAllowed = publicSettings.EnableTelemetry;
if (analyticsAllowed) {
// send analytics if GPU management is changed (with the new state)
if (this.initialEnableGPUManagement !== this.state.enableGPUManagement) {
this.$analytics.eventTrack('enable-gpu-management-updated', { category: 'portainer', metadata: { enableGPUManagementState: this.state.enableGPUManagement } });
}
// send analytics if the number of GPUs is changed (with a list of the names)
if (gpus.length > this.initialGPUs.length) {
const numberOfGPUSAdded = this.endpoint.Gpus.length - this.initialGPUs.length;
this.$analytics.eventTrack('gpus-added', { category: 'portainer', metadata: { gpus: gpus.map((gpu) => gpu.name), numberOfGPUSAdded } });
}
if (gpus.length < this.initialGPUs.length) {
const numberOfGPUSRemoved = this.initialGPUs.length - this.endpoint.Gpus.length;
this.$analytics.eventTrack('gpus-removed', { category: 'portainer', metadata: { gpus: gpus.map((gpu) => gpu.name), numberOfGPUSRemoved } });
}
this.initialGPUs = gpus;
this.initialEnableGPUManagement = this.state.enableGPUManagement;
}
this.endpoint.SecuritySettings = securitySettings;
await this.EndpointService.updateSecuritySettings(this.endpoint.Id, settings);
this.endpoint.SecuritySettings = settings;
this.Notifications.success('Success', 'Saved settings successfully');
} catch (e) {
this.Notifications.error('Failure', e, 'Failed saving settings');
}
this.state.actionInProgress = false;
this.$state.reload();
});
}
checkAgent() {
const applicationState = this.StateManager.getState();
return applicationState.endpoint.mode.agentProxy;
}
$onInit() {
const securitySettings = this.endpoint.SecuritySettings;
const isAgent = this.checkAgent();
this.isAgent = isAgent;
const applicationState = this.StateManager.getState();
this.isAgent = applicationState.endpoint.mode.agentProxy;
this.isDockerStandaloneEnv = applicationState.endpoint.mode.provider === 'DOCKER_STANDALONE';
this.formValues = {
enableHostManagementFeatures: isAgent && securitySettings.enableHostManagementFeatures,
allowVolumeBrowserForRegularUsers: isAgent && securitySettings.allowVolumeBrowserForRegularUsers,
enableHostManagementFeatures: this.isAgent && securitySettings.enableHostManagementFeatures,
allowVolumeBrowserForRegularUsers: this.isAgent && securitySettings.allowVolumeBrowserForRegularUsers,
disableBindMountsForRegularUsers: !securitySettings.allowBindMountsForRegularUsers,
disablePrivilegedModeForRegularUsers: !securitySettings.allowPrivilegedModeForRegularUsers,
disableHostNamespaceForRegularUsers: !securitySettings.allowHostNamespaceForRegularUsers,
@ -137,5 +178,9 @@ export default class DockerFeaturesConfigurationController {
disableContainerCapabilitiesForRegularUsers: !securitySettings.allowContainerCapabilitiesForRegularUsers,
disableSysctlSettingForRegularUsers: !securitySettings.allowSysctlSettingForRegularUsers,
};
this.state.enableGPUManagement = this.isDockerStandaloneEnv && (this.endpoint.EnableGPUManagement || this.endpoint.Gpus.length > 0);
this.initialGPUs = this.endpoint.Gpus;
this.initialEnableGPUManagement = this.endpoint.EnableGPUManagement;
}
}

View file

@ -150,9 +150,42 @@
<!-- other -->
<div class="col-sm-12 form-section-title"> Other </div>
<div class="form-group">
<div class="col-sm-12 pb-3">
<insights-box
header="'GPU settings update'"
set-html-content="true"
insight-close-id="'gpu-settings-update-closed'"
content="'
<p>
From 2.18 on, the set-up of available GPUs for a Docker Standalone environment has been shifted from Add environment and Environment details to Host -> Setup, so as to align with other settings.
</p>
<p>
A toggle has been introduced for enabling/disabling management of GPU settings in the Portainer UI - to alleviate the performance impact of showing those settings.
</p>
<p>
The UI has been updated to clarify that GPU settings support is only for Docker Standalone (and not Docker Swarm, which was never supported in the UI).
</p>'"
></insights-box>
</div>
<div class="col-sm-12">
<por-switch-field
label="'Show a notification to indicate out-of-date images for Docker environments'"
label="'Show GPU in the UI'"
tooltip="'This allows managing of GPUs for container/stack hardware acceleration via the Portainer UI.'"
checked="$ctrl.state.enableGPUManagement"
name="'enableGPUManagement'"
on-change="($ctrl.onToggleGPUManagement)"
label-class="'col-sm-7 col-lg-4'"
disabled="!$ctrl.isDockerStandaloneEnv"
></por-switch-field>
</div>
<div class="col-sm-12">
<div class="pl-4">
<gpus-list ng-if="$ctrl.state.enableGPUManagement && $ctrl.endpoint" value="$ctrl.endpoint.Gpus" on-change="($ctrl.onGpusChange)"></gpus-list>
</div>
</div>
<div class="col-sm-12">
<por-switch-field
label="'Show an image(s) up to date indicator for Stacks, Services and Containers'"
checked="false"
name="'outOfDateImageToggle'"
label-class="'col-sm-7 col-lg-4'"
@ -166,7 +199,13 @@
<div class="col-sm-12 form-section-title"> Actions </div>
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-click="$ctrl.save()" ng-disabled="$ctrl.state.actionInProgress" button-spinner="$ctrl.state.actionInProgress">
<button
type="button"
class="btn btn-primary btn-sm !ml-0"
ng-click="$ctrl.save()"
ng-disabled="$ctrl.state.actionInProgress"
button-spinner="$ctrl.state.actionInProgress"
>
<span ng-hide="$ctrl.state.actionInProgress">Save configuration</span>
<span ng-show="$ctrl.state.actionInProgress">Saving...</span>
</button>