Compare commits
7 Commits
docker_tes
...
v0.9.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed0ecac7a1 | ||
|
|
12ad14aad2 | ||
|
|
9a7520cb9c | ||
|
|
3b75f04a6c | ||
|
|
587dddb752 | ||
|
|
d7b012076b | ||
|
|
fab5e36bfe |
9
CHANGES
9
CHANGES
@@ -411,3 +411,12 @@
|
|||||||
- Fix bug in multdb mysql addon backup
|
- Fix bug in multdb mysql addon backup
|
||||||
- Add initial user group support
|
- Add initial user group support
|
||||||
- Improved app memory limit handling
|
- Improved app memory limit handling
|
||||||
|
|
||||||
|
[0.9.1]
|
||||||
|
- Introduce per app group access control
|
||||||
|
|
||||||
|
[0.9.2]
|
||||||
|
- Fix bug where reconfiguring apps would trigger memory limit warning
|
||||||
|
- Allow more apps to be installed in bigger sized cloudrons
|
||||||
|
- Allow user to override memory limit warning and install anyway
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ fi
|
|||||||
|
|
||||||
# all sizes are in mb
|
# all sizes are in mb
|
||||||
readonly physical_memory=$(free -m | awk '/Mem:/ { print $2 }')
|
readonly physical_memory=$(free -m | awk '/Mem:/ { print $2 }')
|
||||||
readonly swap_size="${physical_memory}"
|
readonly swap_size="${physical_memory}" # if you change this, fix enoughResourcesAvailable() in client.js
|
||||||
readonly app_count=$((${physical_memory} / 200)) # estimated app count
|
readonly app_count=$((${physical_memory} / 200)) # estimated app count
|
||||||
readonly disk_size_gb=$(fdisk -l ${disk_device} | grep "Disk ${disk_device}" | awk '{ print $3 }')
|
readonly disk_size_gb=$(fdisk -l ${disk_device} | grep "Disk ${disk_device}" | awk '{ print $3 }')
|
||||||
readonly disk_size=$((disk_size_gb * 1024))
|
readonly disk_size=$((disk_size_gb * 1024))
|
||||||
|
|||||||
@@ -9,6 +9,6 @@ exports = module.exports = {
|
|||||||
ADMIN_CLIENT_ID: 'webadmin', // oauth client id
|
ADMIN_CLIENT_ID: 'webadmin', // oauth client id
|
||||||
ADMIN_APPID: 'admin', // admin appid (settingsdb)
|
ADMIN_APPID: 'admin', // admin appid (settingsdb)
|
||||||
|
|
||||||
DEFAULT_MEMORY_LIMIT: (256 * 1024 * 1024)
|
DEFAULT_MEMORY_LIMIT: (256 * 1024 * 1024) // see also client.js
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
angular.module('Application').service('Client', ['$http', 'md5', 'Notification', function ($http, md5, Notification) {
|
angular.module('Application').service('Client', ['$http', 'md5', 'Notification', function ($http, md5, Notification) {
|
||||||
var client = null;
|
var client = null;
|
||||||
|
|
||||||
// Keep this in sync with docs and docker.js
|
// Keep this in sync with docs and constants.js, docker.js
|
||||||
var DEFAULT_MEMORY_LIMIT = 1024 * 1024 * 200;
|
var DEFAULT_MEMORY_LIMIT = 1024 * 1024 * 256;
|
||||||
|
|
||||||
function ClientError(statusCode, messageOrObject) {
|
function ClientError(statusCode, messageOrObject) {
|
||||||
Error.call(this);
|
Error.call(this);
|
||||||
@@ -774,9 +774,11 @@ angular.module('Application').service('Client', ['$http', 'md5', 'Notification',
|
|||||||
};
|
};
|
||||||
|
|
||||||
Client.prototype.enoughResourcesAvailable = function (app) {
|
Client.prototype.enoughResourcesAvailable = function (app) {
|
||||||
var needed = app.manifest.memoryLimit || DEFAULT_MEMORY_LIMIT;
|
var needed = app.manifest.memoryLimit || DEFAULT_MEMORY_LIMIT; // RAM+Swap
|
||||||
var used = this.getInstalledApps().reduce(function (prev, cur) { return prev + (cur.manifest.memoryLimit || DEFAULT_MEMORY_LIMIT); }, 0);
|
var used = this.getInstalledApps().reduce(function (prev, cur) { return prev + (cur.manifest.memoryLimit || DEFAULT_MEMORY_LIMIT); }, 0);
|
||||||
var available = (this.getConfig().memory || 0) - used;
|
var roundedMemory = Math.round(this.getConfig().memory / (1024 * 1024 * 1024)) * 1024 * 1024 * 1024; // round to nearest GB
|
||||||
|
var totalMemory = roundedMemory * 1.2; // box-setup.sh creates equal amount of swap. 1.2 factor is arbitrary
|
||||||
|
var available = (totalMemory || 0) - used;
|
||||||
|
|
||||||
return (available - needed) > 0;
|
return (available - needed) > 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -193,8 +193,8 @@ angular.module('Application').controller('AppsController', ['$scope', '$location
|
|||||||
portBindings: finalPortBindings,
|
portBindings: finalPortBindings,
|
||||||
accessRestriction: !$scope.appConfigure.accessRestrictionOption ? null : $scope.appConfigure.accessRestriction,
|
accessRestriction: !$scope.appConfigure.accessRestrictionOption ? null : $scope.appConfigure.accessRestriction,
|
||||||
cert: $scope.appConfigure.certificateFile,
|
cert: $scope.appConfigure.certificateFile,
|
||||||
key: $scope.appConfigure.keyFile,
|
key: $scope.appConfigure.keyFile
|
||||||
memoryLimit: $scope.appConfigure.memoryLimit
|
// memoryLimit: $scope.appConfigure.memoryLimit
|
||||||
};
|
};
|
||||||
|
|
||||||
Client.configureApp($scope.appConfigure.app.id, $scope.appConfigure.password, data, function (error) {
|
Client.configureApp($scope.appConfigure.app.id, $scope.appConfigure.password, data, function (error) {
|
||||||
|
|||||||
@@ -80,12 +80,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="collapse" id="collapseResourceConstraint" data-toggle="false">
|
<div class="collapse" id="collapseResourceConstraint" data-toggle="false">
|
||||||
<h4 class="text-danger">Not enough resources left to install this application.</h4>
|
<h4 class="text-danger">This Cloudron is running low on resources.</h4>
|
||||||
<p>The Cloudron's resources can be extended with a model upgrade or available resources may be freed up by uninstalling unused applications.</p>
|
<p>Installing this app might decrease the performance of other apps. The Cloudron's resources can be extended with a model upgrade or available resources may be freed up by uninstalling unused applications.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||||
|
<button type="button" class="btn btn-danger" ng-show="!appInstall.installFormVisible && user.admin && appInstall.resourceConstraintVisible" ng-click="showInstallForm(true)">Install anyway</button>
|
||||||
<button type="button" class="btn btn-success" ng-show="!appInstall.installFormVisible && user.admin && !appInstall.resourceConstraintVisible" ng-click="showInstallForm()">Install</button>
|
<button type="button" class="btn btn-success" ng-show="!appInstall.installFormVisible && user.admin && !appInstall.resourceConstraintVisible" ng-click="showInstallForm()">Install</button>
|
||||||
<button type="button" class="btn btn-success" ng-show="appInstall.installFormVisible && user.admin && !appInstall.resourceConstraintVisible" ng-click="doInstall()" ng-disabled="appInstallForm.$invalid || appInstall.busy"><i class="fa fa-spinner fa-pulse" ng-show="appInstall.busy"></i> Install</button>
|
<button type="button" class="btn btn-success" ng-show="appInstall.installFormVisible && user.admin && !appInstall.resourceConstraintVisible" ng-click="doInstall()" ng-disabled="appInstallForm.$invalid || appInstall.busy"><i class="fa fa-spinner fa-pulse" ng-show="appInstall.busy"></i> Install</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -157,13 +157,16 @@ angular.module('Application').controller('AppStoreController', ['$scope', '$loca
|
|||||||
$scope.appInstallForm.$setUntouched();
|
$scope.appInstallForm.$setUntouched();
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.showInstallForm = function () {
|
$scope.showInstallForm = function (force) {
|
||||||
if (Client.enoughResourcesAvailable($scope.appInstall.app)) {
|
if (Client.enoughResourcesAvailable($scope.appInstall.app) || force) {
|
||||||
$scope.appInstall.installFormVisible = true;
|
$scope.appInstall.installFormVisible = true;
|
||||||
|
$scope.appInstall.resourceConstraintVisible = false;
|
||||||
$('#collapseMediaLinksCarousel').collapse('hide');
|
$('#collapseMediaLinksCarousel').collapse('hide');
|
||||||
|
$('#collapseResourceConstraint').collapse('hide');
|
||||||
$('#collapseInstallForm').collapse('show');
|
$('#collapseInstallForm').collapse('show');
|
||||||
$('#appInstallLocationInput').focus();
|
$('#appInstallLocationInput').focus();
|
||||||
} else {
|
} else {
|
||||||
|
$scope.appInstall.installFormVisible = false;
|
||||||
$scope.appInstall.resourceConstraintVisible = true;
|
$scope.appInstall.resourceConstraintVisible = true;
|
||||||
$('#collapseMediaLinksCarousel').collapse('hide');
|
$('#collapseMediaLinksCarousel').collapse('hide');
|
||||||
$('#collapseResourceConstraint').collapse('show');
|
$('#collapseResourceConstraint').collapse('show');
|
||||||
|
|||||||
@@ -143,7 +143,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||||
<button type="button" class="btn btn-success" ng-click="doUserEdit()" ng-disabled="useredit_form.$invalid || useredit.busy"><i class="fa fa-spinner fa-pulse" ng-show="useredit.busy"></i> Edit</button>
|
<button type="button" class="btn btn-success" ng-click="doUserEdit()" ng-disabled="useredit_form.$invalid || useredit.busy"><i class="fa fa-spinner fa-pulse" ng-show="useredit.busy"></i> Save</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user