diff --git a/app/components/createContainer/createContainerController.js b/app/components/createContainer/createContainerController.js index 2906f81b5..ebc5255c8 100644 --- a/app/components/createContainer/createContainerController.js +++ b/app/components/createContainer/createContainerController.js @@ -1,8 +1,8 @@ // @@OLD_SERVICE_CONTROLLER: this service should be rewritten to use services. // See app/components/templates/templatesController.js as a reference. angular.module('createContainer', []) -.controller('CreateContainerController', ['$q', '$scope', '$state', '$transition$', '$filter', 'Container', 'ContainerHelper', 'Image', 'ImageHelper', 'Volume', 'NetworkService', 'ResourceControlService', 'Authentication', 'Notifications', 'ContainerService', 'ImageService', 'FormValidator', 'ModalService', 'RegistryService', 'SettingsService', -function ($q, $scope, $state, $transition$, $filter, Container, ContainerHelper, Image, ImageHelper, Volume, NetworkService, ResourceControlService, Authentication, Notifications, ContainerService, ImageService, FormValidator, ModalService, RegistryService, SettingsService) { +.controller('CreateContainerController', ['$q', '$scope', '$state', '$timeout', '$transition$', '$filter', 'Container', 'ContainerHelper', 'Image', 'ImageHelper', 'Volume', 'NetworkService', 'ResourceControlService', 'Authentication', 'Notifications', 'ContainerService', 'ImageService', 'FormValidator', 'ModalService', 'RegistryService', 'SystemService', 'SettingsService', +function ($q, $scope, $state, $timeout, $transition$, $filter, Container, ContainerHelper, Image, ImageHelper, Volume, NetworkService, ResourceControlService, Authentication, Notifications, ContainerService, ImageService, FormValidator, ModalService, RegistryService, SystemService, SettingsService) { $scope.formValues = { alwaysPull: true, @@ -13,13 +13,22 @@ function ($q, $scope, $state, $transition$, $filter, Container, ContainerHelper, ExtraHosts: [], IPv4: '', IPv6: '', - AccessControlData: new AccessControlFormData() + AccessControlData: new AccessControlFormData(), + CpuLimit: 0, + MemoryLimit: 0, + MemoryReservation: 0 }; $scope.state = { formValidationError: '' }; + $scope.refreshSlider = function () { + $timeout(function () { + $scope.$broadcast('rzSliderForceRender'); + }); + }; + $scope.config = { Image: '', Env: [], @@ -221,6 +230,25 @@ function ($q, $scope, $state, $transition$, $filter, Container, ContainerHelper, config.HostConfig.Devices = path; } + function prepareResources(config) { + // Memory Limit - Round to 0.125 + var memoryLimit = (Math.round($scope.formValues.MemoryLimit * 8) / 8).toFixed(3); + memoryLimit *= 1024 * 1024; + if (memoryLimit > 0) { + config.HostConfig.Memory = memoryLimit; + } + // Memory Resevation - Round to 0.125 + var memoryReservation = (Math.round($scope.formValues.MemoryReservation * 8) / 8).toFixed(3); + memoryReservation *= 1024 * 1024; + if (memoryReservation > 0) { + config.HostConfig.MemoryReservation = memoryReservation; + } + // CPU Limit + if ($scope.formValues.CpuLimit > 0) { + config.HostConfig.NanoCpus = $scope.formValues.CpuLimit * 1000000000; + } + } + function prepareConfiguration() { var config = angular.copy($scope.config); config.Cmd = ContainerHelper.commandStringToArray(config.Cmd); @@ -232,6 +260,7 @@ function ($q, $scope, $state, $transition$, $filter, Container, ContainerHelper, prepareVolumes(config); prepareLabels(config); prepareDevices(config); + prepareResources(config); return config; } @@ -416,6 +445,18 @@ function ($q, $scope, $state, $transition$, $filter, Container, ContainerHelper, }); } + function loadFromContainerResources(d) { + if (d.HostConfig.NanoCpus) { + $scope.formValues.CpuLimit = d.HostConfig.NanoCpus / 1000000000; + } + if (d.HostConfig.Memory) { + $scope.formValues.MemoryLimit = d.HostConfig.Memory / 1024 / 1024; + } + if (d.HostConfig.MemoryReservation) { + $scope.formValues.MemoryReservation = d.HostConfig.MemoryReservation / 1024 / 1024; + } + } + function loadFromContainerSpec() { // Get container Container.get({ id: $transition$.params().from }).$promise @@ -435,6 +476,7 @@ function ($q, $scope, $state, $transition$, $filter, Container, ContainerHelper, loadFromContainerConsole(d); loadFromContainerDevices(d); loadFromContainerImageConfig(d); + loadFromContainerResources(d); }) .catch(function error(err) { Notifications.error('Failure', err, 'Unable to retrieve container'); @@ -482,6 +524,21 @@ function ($q, $scope, $state, $transition$, $filter, Container, ContainerHelper, Notifications.error('Failure', e, 'Unable to retrieve running containers'); }); + SystemService.info() + .then(function success(data) { + $scope.state.sliderMaxCpu = 32; + if (data.NCPU) { + $scope.state.sliderMaxCpu = data.NCPU; + } + $scope.state.sliderMaxMemory = 32768; + if (data.MemTotal) { + $scope.state.sliderMaxMemory = Math.floor(data.MemTotal / 1000 / 1000); + } + }) + .catch(function error(err) { + Notifications.error('Failure', err, 'Unable to retrieve engine details'); + }); + SettingsService.publicSettings() .then(function success(data) { $scope.allowBindMounts = data.AllowBindMountsForRegularUsers; diff --git a/app/components/createContainer/createcontainer.html b/app/components/createContainer/createcontainer.html index 2701fe7d6..c784d7517 100644 --- a/app/components/createContainer/createcontainer.html +++ b/app/components/createContainer/createcontainer.html @@ -141,7 +141,7 @@
  • Env
  • Labels
  • Restart policy
  • -
  • Runtime
  • +
  • Runtime & Resources
  • @@ -466,9 +466,12 @@
    - -
    + +
    +
    + Runtime +
    @@ -510,10 +513,63 @@
    +
    + Resources +
    + +
    + +
    + +
    +
    + +
    +
    +

    + Memory soft limit (MB) +

    +
    +
    + + +
    + +
    + +
    +
    + +
    +
    +

    + Memory limit (MB) +

    +
    +
    + + +
    + +
    + +
    +
    +

    + Maximum CPU usage +

    +
    +
    + -
    - +
    diff --git a/app/components/createService/createServiceController.js b/app/components/createService/createServiceController.js index 5b0cb0a62..887fe7cb3 100644 --- a/app/components/createService/createServiceController.js +++ b/app/components/createService/createServiceController.js @@ -352,6 +352,29 @@ function ($q, $scope, $state, $timeout, Service, ServiceHelper, SecretHelper, Se createNewService(config, accessControlData); }; + function initSlidersMaxValuesBasedOnNodeData(nodes) { + var maxCpus = 0; + var maxMemory = 0; + for (var n in nodes) { + if (nodes[n].CPUs && nodes[n].CPUs > maxCpus) { + maxCpus = nodes[n].CPUs; + } + if (nodes[n].Memory && nodes[n].Memory > maxMemory) { + maxMemory = nodes[n].Memory; + } + } + if (maxCpus > 0) { + $scope.state.sliderMaxCpu = maxCpus / 1000000000; + } else { + $scope.state.sliderMaxCpu = 32; + } + if (maxMemory > 0) { + $scope.state.sliderMaxMemory = Math.floor(maxMemory / 1000 / 1000); + } else { + $scope.state.sliderMaxMemory = 32768; + } + } + function initView() { $('#loadingViewSpinner').show(); var apiVersion = $scope.applicationState.endpoint.apiVersion; @@ -368,18 +391,8 @@ function ($q, $scope, $state, $timeout, Service, ServiceHelper, SecretHelper, Se $scope.availableVolumes = data.volumes; $scope.availableNetworks = data.networks; $scope.availableSecrets = 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; - } + var nodes = data.nodes; + initSlidersMaxValuesBasedOnNodeData(nodes); var settings = data.settings; $scope.allowBindMounts = settings.AllowBindMountsForRegularUsers; var userDetails = Authentication.getUserDetails(); diff --git a/app/components/createService/includes/resources-placement.html b/app/components/createService/includes/resources-placement.html index 6c8b85dd6..17fc9b6a9 100644 --- a/app/components/createService/includes/resources-placement.html +++ b/app/components/createService/includes/resources-placement.html @@ -4,42 +4,36 @@
    -
    -