1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-05 13:55:21 +02:00

#516 feat(services) - add the ability to manage cpu/mem limits

This commit is contained in:
Thomas Krzero 2017-09-20 08:32:19 +02:00 committed by Anthony Lapenna
parent d695657711
commit 3cb96235b7
13 changed files with 353 additions and 92 deletions

View file

@ -6,31 +6,77 @@
<table class="table">
<tbody>
<tr>
<td>CPU limits</td>
<td ng-if="service.LimitNanoCPUs">
{{ service.LimitNanoCPUs / 1000000000 }}
<td style="vertical-align : middle;">
Memory reservation (MB)
</td>
<td ng-if="!service.LimitNanoCPUs">None</td>
</tr>
<tr>
<td>Memory limits</td>
<td ng-if="service.LimitMemoryBytes">{{service.LimitMemoryBytes|humansize}}</td>
<td ng-if="!service.LimitMemoryBytes">None</td>
</tr>
<tr>
<td>CPU reservation</td>
<td ng-if="service.ReservationNanoCPUs">
{{service.ReservationNanoCPUs / 1000000000}}
<td>
<input class="input-sm" type="number" step="0.125" min="0" ng-model="service.ReservationMemoryBytes" ng-change="updateServiceAttribute(service, 'ReservationMemoryBytes')" ng-disabled="isUpdating"/>
</td>
<td style="vertical-align : middle;">
<p class="small text-muted">
Minimum memory available on a node to run a task (set to 0 for unlimited)
</p>
</td>
<td ng-if="!service.ReservationNanoCPUs">None</td>
</tr>
<tr>
<td>Memory reservation</td>
<td ng-if="service.ReservationMemoryBytes">{{service.ReservationMemoryBytes|humansize}}</td>
<td ng-if="!service.ReservationMemoryBytes">None</td>
<td style="vertical-align : middle;">
Memory limit (MB)
</td>
<td>
<input class="input-sm" type="number" step="0.125" min="0" ng-model="service.LimitMemoryBytes" ng-change="updateServiceAttribute(service, 'LimitMemoryBytes')" ng-disabled="isUpdating"/>
</td>
<td style="vertical-align : middle;">
<p class="small text-muted">
Maximum memory usage per task (set to 0 for unlimited)
</p>
</td>
</tr>
<tr>
<td style="vertical-align : middle;">
<div>
CPU reservation
</div>
</td>
<td>
<por-slider model="service.ReservationNanoCPUs" floor="0" ceil="state.sliderMaxCpu" step="0.25" precision="2" ng-if="service && state.sliderMaxCpu" on-change="updateServiceAttribute(service, 'ReservationNanoCPUs')"></por-slider>
</td>
<td style="vertical-align : middle;">
<p class="small text-muted">
Minimum CPU available on a node to run a task
</p>
</td>
</tr>
<tr>
<td style="vertical-align : middle;">
<div>
CPU limit
</div>
</td>
<td>
<por-slider model="service.LimitNanoCPUs" floor="0" ceil="state.sliderMaxCpu" step="0.25" precision="2" ng-if="service && state.sliderMaxCpu" on-change="updateServiceAttribute(service, 'LimitNanoCPUs')"></por-slider>
</td>
<td style="vertical-align : middle;">
<p class="small text-muted">
Maximum CPU usage per task
</p>
</td>
</tr>
</tbody>
</table>
</rd-widget-body>
<rd-widget-footer>
<div class="btn-toolbar" role="toolbar">
<div class="btn-group" role="group">
<button type="button" class="btn btn-primary btn-sm" ng-disabled="!hasChanges(service, ['LimitNanoCPUs', 'LimitMemoryBytes', 'ReservationNanoCPUs', 'ReservationMemoryBytes'])" ng-click="updateService(service)">Apply changes</button>
<button type="button" class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li><a ng-click="cancelChanges(service, ['LimitNanoCPUs', 'LimitMemoryBytes', 'ReservationNanoCPUs', 'ReservationMemoryBytes'])">Reset changes</a></li>
<li><a ng-click="cancelChanges(service)">Reset all changes</a></li>
</ul>
</div>
</div>
</rd-widget-footer>
</rd-widget>
</div>

View file

@ -204,14 +204,19 @@ function ($q, $scope, $stateParams, $state, $location, $timeout, $anchorScroll,
config.TaskTemplate.Placement.Constraints = ServiceHelper.translateKeyValueToPlacementConstraints(service.ServiceConstraints);
config.TaskTemplate.Placement.Preferences = ServiceHelper.translateKeyValueToPlacementPreferences(service.ServicePreferences);
// Round memory values to 0.125 and convert MB to B
var memoryLimit = (Math.round(service.LimitMemoryBytes * 8) / 8).toFixed(3);
memoryLimit *= 1024 * 1024;
var memoryReservation = (Math.round(service.ReservationMemoryBytes * 8) / 8).toFixed(3);
memoryReservation *= 1024 * 1024;
config.TaskTemplate.Resources = {
Limits: {
NanoCPUs: service.LimitNanoCPUs,
MemoryBytes: service.LimitMemoryBytes
NanoCPUs: service.LimitNanoCPUs * 1000000000,
MemoryBytes: memoryLimit
},
Reservations: {
NanoCPUs: service.ReservationNanoCPUs,
MemoryBytes: service.ReservationMemoryBytes
NanoCPUs: service.ReservationNanoCPUs * 1000000000,
MemoryBytes: memoryReservation
}
};
@ -244,7 +249,11 @@ function ($q, $scope, $stateParams, $state, $location, $timeout, $anchorScroll,
Service.update({ id: service.Id, version: service.Version }, config, function (data) {
$('#loadingViewSpinner').hide();
Notifications.success('Service successfully updated', 'Service updated');
if (data.message && data.message.match(/^rpc error:/)) {
Notifications.error(data.message, 'Error');
} else {
Notifications.success('Service successfully updated', 'Service updated');
}
$scope.cancelChanges({});
initView();
}, function (e) {
@ -288,6 +297,13 @@ function ($q, $scope, $stateParams, $state, $location, $timeout, $anchorScroll,
service.ServicePreferences = ServiceHelper.translatePreferencesToKeyValue(service.Preferences);
}
function transformResources(service) {
service.LimitNanoCPUs = service.LimitNanoCPUs / 1000000000 || 0;
service.ReservationNanoCPUs = service.ReservationNanoCPUs / 1000000000 || 0;
service.LimitMemoryBytes = service.LimitMemoryBytes / 1024 / 1024 || 0;
service.ReservationMemoryBytes = service.ReservationMemoryBytes / 1024 / 1024 || 0;
}
function initView() {
$('#loadingViewSpinner').show();
var apiVersion = $scope.applicationState.endpoint.apiVersion;
@ -299,6 +315,7 @@ function ($q, $scope, $stateParams, $state, $location, $timeout, $anchorScroll,
$scope.lastVersion = service.Version;
}
transformResources(service);
translateServiceArrays(service);
$scope.service = service;
originalService = angular.copy(service);
@ -314,6 +331,19 @@ function ($q, $scope, $stateParams, $state, $location, $timeout, $anchorScroll,
$scope.nodes = data.nodes;
$scope.secrets = data.secrets;
// Set max cpu value
var maxCpus = 0;
for (var n in data.nodes) {
if (data.nodes[n].CPUs && data.nodes[n].CPUs > maxCpus) {
maxCpus = data.nodes[n].CPUs;
}
}
if (maxCpus > 0) {
$scope.state.sliderMaxCpu = maxCpus / 1000000000;
} else {
$scope.state.sliderMaxCpu = 32;
}
$timeout(function() {
$anchorScroll();
});