Give services panel a separate top-level view
This commit is contained in:
138
src/views/services.html
Normal file
138
src/views/services.html
Normal file
@@ -0,0 +1,138 @@
|
||||
<!-- Modal service configure -->
|
||||
<div class="modal fade" id="serviceConfigureModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">Configure {{ serviceConfigure.service.displayName }}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form name="serviceConfigureForm" role="form" novalidate ng-submit="serviceConfigure.submit()" autocomplete="off">
|
||||
<fieldset>
|
||||
<p class="has-error text-center" ng-show="serviceConfigure.error">{{ serviceConfigure.error }}</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="memoryLimit">Memory Limit : <b>{{ serviceConfigure.memoryLimit / 1024 / 1024 + 'MB' }}</b></label>
|
||||
<p><small>Cloudron allocates 50% of this value as RAM and 50% as swap.</small></p>
|
||||
<div style="padding: 0 10px;">
|
||||
<slider id="memoryLimit" ng-model="serviceConfigure.memoryLimit" step="134217728" tooltip="hide" ticks="serviceConfigure.memoryTicks" ticks-snap-bounds="67108864"></slider>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input class="ng-hide" type="submit" ng-disabled="serviceConfigureForm.$invalid || serviceConfigure.busy"/>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer ">
|
||||
<button type="button" class="btn btn-default pull-left" ng-click="serviceConfigure.submit(0)" ng-disabled="serviceConfigureForm.$invalid || serviceConfigure.busy">
|
||||
<i class="fa fa-circle-notch fa-spin" ng-show="serviceConfigure.busy"></i> Reset to defaults
|
||||
</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn btn-outline btn-success pull-right" ng-click="serviceConfigure.submit(serviceConfigure.memoryLimit)" ng-disabled="serviceConfigureForm.$invalid || serviceConfigure.busy">
|
||||
<i class="fa fa-circle-notch fa-spin" ng-show="serviceConfigure.busy"></i> Save
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
|
||||
<div class="text-left">
|
||||
<h1>Services</h1>
|
||||
</div>
|
||||
|
||||
<div class="card" style="margin-bottom: 15px;">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<p>
|
||||
Cloudron services implement functionality such as databases, email and authentication.<br/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="row ng-hide" ng-show="!servicesReady">
|
||||
<div class="col-md-12 text-center">
|
||||
<h2><i class="fa fa-circle-notch fa-spin"></i></h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row animateMeOpacity ng-hide" ng-show="servicesReady">
|
||||
<div class="col-md-12">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 5%;"></th>
|
||||
<th style="width: 20%">Service</th>
|
||||
<th style="width: 50%">Memory Usage</th>
|
||||
<th style="width: 20%" class="text-center">Memory Limit</th>
|
||||
<th style="width: 5%" class="text-right">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><i class="fa fa-circle" uib-tooltip="active" style="color: #27CE65"></i></td>
|
||||
<td class="elide-table-cell">cloudron</td>
|
||||
<td class="elide-table-cell"></td>
|
||||
<td class="elide-table-cell text-center"></td>
|
||||
<td class="text-right no-wrap" style="vertical-align: bottom">
|
||||
<a class="btn btn-xs btn-default" href="/logs.html?id=box" target="_blank" uib-tooltip="Logs"><i class="fa fa-file-alt"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-repeat="service in services | filter:{ isRedis: false } | orderBy:'name'">
|
||||
<td>
|
||||
<i class="fa fa-circle" uib-tooltip="{{ service.status }}" ng-style="{ color: service.status === 'active' ? '#27CE65' : (service.status === 'starting' ? '#f0ad4e' : '#d9534f') }" ng-show="service.status"></i>
|
||||
<i class="fa fa-circle-notch fa-spin" ng-hide="service.status"></i>
|
||||
</td>
|
||||
<td class="elide-table-cell">
|
||||
{{ service.displayName }}
|
||||
</td>
|
||||
<td class="elide-table-cell">
|
||||
<div class="progress progress-striped" ng-show="service.config.memory">
|
||||
<div class="progress-bar progress-bar-success" role="progressbar" style="width: {{ service.memoryPercent }}%"></div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="elide-table-cell text-center">
|
||||
<span ng-show="service.config.memory">{{ service.config.memorySwap | prettyByteSize }}</span>
|
||||
</td>
|
||||
<td class="text-right no-wrap" style="vertical-align: bottom">
|
||||
<button class="btn btn-xs btn-default" ng-click="serviceConfigure.show(service)" uib-tooltip="Configure Memory Limit" ng-show="service.config.memory"><i class="fa fa-pencil-alt"></i></button>
|
||||
<button class="btn btn-xs btn-default" ng-click="restartService(service.name)" uib-tooltip="Restart"><i class="fa fa-sync-alt" ng-class="{ 'fa-spin': service.status === 'starting' }"></i></button>
|
||||
<a class="btn btn-xs btn-default" ng-href="{{ '/logs.html?id=' + service.name }}" target="_blank" uib-tooltip="Logs"><i class="fa fa-file-alt"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-show="hasRedisServices" ng-click="redisServicesExpanded = !redisServicesExpanded" class="hand">
|
||||
<td>
|
||||
<i class="fas fa-angle-right" ng-class="{'fa-rotate-90': redisServicesExpanded }"></i>
|
||||
</td>
|
||||
<td colspan="4">redis</td>
|
||||
</tr>
|
||||
<tr ng-show="redisServicesExpanded" ng-repeat="service in services | filter:{ isRedis: true } | orderBy:'name'">
|
||||
<td>
|
||||
<i class="fa fa-circle" uib-tooltip="{{ service.status }}" ng-style="{ color: service.status === 'active' ? '#27CE65' : (service.status === 'starting' ? '#f0ad4e' : '#d9534f') }" ng-show="service.status"></i>
|
||||
<i class="fa fa-circle-notch fa-spin" ng-hide="service.status"></i>
|
||||
</td>
|
||||
<td class="elide-table-cell">
|
||||
{{ service.displayName }}
|
||||
</td>
|
||||
<td class="elide-table-cell">
|
||||
<div class="progress progress-striped" ng-show="service.config.memory">
|
||||
<div class="progress-bar progress-bar-success" role="progressbar" style="width: {{ service.memoryPercent }}%"></div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="elide-table-cell text-center">
|
||||
<span ng-show="service.config.memory">{{ service.config.memorySwap | prettyByteSize }}</span>
|
||||
</td>
|
||||
<td class="text-right no-wrap" style="vertical-align: bottom">
|
||||
<button class="btn btn-xs btn-default" ng-click="serviceConfigure.show(service)" uib-tooltip="Configure Memory Limit" ng-show="service.config.memory"><i class="fa fa-pencil-alt"></i></button>
|
||||
<button class="btn btn-xs btn-default" ng-click="restartService(service.name)" uib-tooltip="Restart"><i class="fa fa-sync-alt" ng-class="{ 'fa-spin': service.status === 'starting' }"></i></button>
|
||||
<a class="btn btn-xs btn-default" ng-href="{{ '/logs.html?id=' + service.name }}" target="_blank" uib-tooltip="Logs"><i class="fa fa-file-alt"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
152
src/views/services.js
Normal file
152
src/views/services.js
Normal file
@@ -0,0 +1,152 @@
|
||||
'use strict';
|
||||
|
||||
/* global angular */
|
||||
/* global $ */
|
||||
|
||||
angular.module('Application').controller('ServicesController', ['$scope', '$location', '$timeout', 'Client', function ($scope, $location, $timeout, Client) {
|
||||
Client.onReady(function () { if (!Client.getUserInfo().isAtLeastAdmin) $location.path('/'); });
|
||||
|
||||
$scope.config = Client.getConfig();
|
||||
$scope.servicesReady = false;
|
||||
$scope.services = [];
|
||||
$scope.hasRedisServices = false;
|
||||
$scope.redisServicesExpanded = false;
|
||||
$scope.memory = null;
|
||||
|
||||
function refresh(serviceName, callback) {
|
||||
callback = callback || function () {};
|
||||
|
||||
Client.getService(serviceName, function (error, result) {
|
||||
if (error) return console.log('Error getting status of ' + serviceName + ':' + error.message);
|
||||
|
||||
var service = $scope.services.find(function (s) { return s.name === serviceName; });
|
||||
if (!service) $scope.services.find(function (s) { return s.name === serviceName; });
|
||||
|
||||
service.status = result.status;
|
||||
service.config = result.config;
|
||||
service.memoryUsed = result.memoryUsed;
|
||||
service.memoryPercent = result.memoryPercent;
|
||||
|
||||
callback(null, service);
|
||||
});
|
||||
}
|
||||
|
||||
$scope.restartService = function (serviceName) {
|
||||
function waitForActive(serviceName) {
|
||||
refresh(serviceName, function (error, result) {
|
||||
if (result.status === 'active') return;
|
||||
|
||||
setTimeout(function () { waitForActive(serviceName); }, 3000);
|
||||
});
|
||||
}
|
||||
|
||||
$scope.services.find(function (s) { return s.name === serviceName; }).status = 'starting';
|
||||
|
||||
Client.restartService(serviceName, function (error) {
|
||||
if (error) return Client.error(error);
|
||||
|
||||
// show "busy" indicator for 3 seconds to show some ui activity
|
||||
setTimeout(function () { waitForActive(serviceName); }, 3000);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.serviceConfigure = {
|
||||
error: null,
|
||||
busy: false,
|
||||
service: null,
|
||||
|
||||
// form model
|
||||
memoryLimit: 0,
|
||||
memoryTicks: [],
|
||||
|
||||
show: function (service) {
|
||||
$scope.serviceConfigure.reset();
|
||||
|
||||
$scope.serviceConfigure.service = service;
|
||||
$scope.serviceConfigure.memoryLimit = service.config.memorySwap; // memory + swap
|
||||
|
||||
// TODO improve those
|
||||
$scope.serviceConfigure.memoryTicks = [];
|
||||
|
||||
// create ticks starting from manifest memory limit. the memory limit here is currently split into ram+swap (and thus *2 below)
|
||||
// TODO: the *2 will overallocate since 4GB is max swap that cloudron itself allocates
|
||||
$scope.serviceConfigure.memoryTicks = [];
|
||||
var npow2 = Math.pow(2, Math.ceil(Math.log($scope.memory.memory)/Math.log(2)));
|
||||
for (var i = 256; i <= (npow2*2/1024/1024); i *= 2) {
|
||||
$scope.serviceConfigure.memoryTicks.push(i * 1024 * 1024);
|
||||
}
|
||||
|
||||
$('#serviceConfigureModal').modal('show');
|
||||
},
|
||||
|
||||
submit: function (memoryLimit) {
|
||||
$scope.serviceConfigure.busy = true;
|
||||
$scope.serviceConfigure.error = null;
|
||||
|
||||
Client.configureService($scope.serviceConfigure.service.name, { memorySwap: memoryLimit, memory: memoryLimit/2 }, function (error) {
|
||||
$scope.serviceConfigure.busy = false;
|
||||
if (error) {
|
||||
$scope.serviceConfigure.error = error.message;
|
||||
return;
|
||||
}
|
||||
|
||||
refresh($scope.serviceConfigure.service.name);
|
||||
|
||||
$('#serviceConfigureModal').modal('hide');
|
||||
$scope.serviceConfigure.reset();
|
||||
});
|
||||
},
|
||||
|
||||
reset: function () {
|
||||
$scope.serviceConfigure.busy = false;
|
||||
$scope.serviceConfigure.error = null;
|
||||
$scope.serviceConfigure.service = null;
|
||||
|
||||
$scope.serviceConfigure.memoryLimit = 0;
|
||||
$scope.serviceConfigure.memoryTicks = [];
|
||||
|
||||
$scope.serviceConfigureForm.$setPristine();
|
||||
$scope.serviceConfigureForm.$setUntouched();
|
||||
}
|
||||
};
|
||||
|
||||
Client.onReady(function () {
|
||||
Client.memory(function (error, memory) {
|
||||
if (error) console.error(error);
|
||||
|
||||
$scope.memory = memory;
|
||||
|
||||
Client.getServices(function (error, result) {
|
||||
if (error) return Client.error(error);
|
||||
|
||||
$scope.services = result.map(function (name) {
|
||||
var displayName = name;
|
||||
var isRedis = false;
|
||||
|
||||
if (name.indexOf('redis') === 0) {
|
||||
isRedis = true;
|
||||
var app = Client.getCachedAppSync(name.slice('redis:'.length));
|
||||
if (app) {
|
||||
displayName = 'Redis (' + (app.label || app.fqdn) + ')';
|
||||
} else {
|
||||
displayName = 'Redis (unknown app)';
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
name: name,
|
||||
displayName: displayName,
|
||||
isRedis: isRedis
|
||||
};
|
||||
});
|
||||
$scope.hasRedisServices = !!$scope.services.find(function (service) { return service.isRedis; });
|
||||
|
||||
// just kick off the status fetching
|
||||
$scope.services.forEach(function (s) { refresh(s.name); });
|
||||
|
||||
$scope.servicesReady = true;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
}]);
|
||||
@@ -1,40 +1,3 @@
|
||||
<!-- Modal service configure -->
|
||||
<div class="modal fade" id="serviceConfigureModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">Configure {{ serviceConfigure.service.displayName }}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form name="serviceConfigureForm" role="form" novalidate ng-submit="serviceConfigure.submit()" autocomplete="off">
|
||||
<fieldset>
|
||||
<p class="has-error text-center" ng-show="serviceConfigure.error">{{ serviceConfigure.error }}</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="memoryLimit">Memory Limit : <b>{{ serviceConfigure.memoryLimit / 1024 / 1024 + 'MB' }}</b></label>
|
||||
<p><small>Cloudron allocates 50% of this value as RAM and 50% as swap.</small></p>
|
||||
<div style="padding: 0 10px;">
|
||||
<slider id="memoryLimit" ng-model="serviceConfigure.memoryLimit" step="134217728" tooltip="hide" ticks="serviceConfigure.memoryTicks" ticks-snap-bounds="67108864"></slider>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input class="ng-hide" type="submit" ng-disabled="serviceConfigureForm.$invalid || serviceConfigure.busy"/>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer ">
|
||||
<button type="button" class="btn btn-default pull-left" ng-click="serviceConfigure.submit(0)" ng-disabled="serviceConfigureForm.$invalid || serviceConfigure.busy">
|
||||
<i class="fa fa-circle-notch fa-spin" ng-show="serviceConfigure.busy"></i> Reset to defaults
|
||||
</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn btn-outline btn-success pull-right" ng-click="serviceConfigure.submit(serviceConfigure.memoryLimit)" ng-disabled="serviceConfigureForm.$invalid || serviceConfigure.busy">
|
||||
<i class="fa fa-circle-notch fa-spin" ng-show="serviceConfigure.busy"></i> Save
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal reboot server -->
|
||||
<div class="modal fade" id="rebootModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
@@ -129,103 +92,4 @@
|
||||
</div>
|
||||
|
||||
</uib-tabset>
|
||||
|
||||
<div class="text-left">
|
||||
<h3>Services</h3>
|
||||
</div>
|
||||
|
||||
<div class="card" style="margin-bottom: 15px;">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<p>
|
||||
Cloudron services implement functionality such as databases, email and authentication.<br/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="row ng-hide" ng-show="!servicesReady">
|
||||
<div class="col-md-12 text-center">
|
||||
<h2><i class="fa fa-circle-notch fa-spin"></i></h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row animateMeOpacity ng-hide" ng-show="servicesReady">
|
||||
<div class="col-md-12">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 5%;"></th>
|
||||
<th style="width: 20%">Service</th>
|
||||
<th style="width: 50%">Memory Usage</th>
|
||||
<th style="width: 20%" class="text-center">Memory Limit</th>
|
||||
<th style="width: 5%" class="text-right">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><i class="fa fa-circle" uib-tooltip="active" style="color: #27CE65"></i></td>
|
||||
<td class="elide-table-cell">cloudron</td>
|
||||
<td class="elide-table-cell"></td>
|
||||
<td class="elide-table-cell text-center"></td>
|
||||
<td class="text-right no-wrap" style="vertical-align: bottom">
|
||||
<a class="btn btn-xs btn-default" href="/logs.html?id=box" target="_blank" uib-tooltip="Logs"><i class="fa fa-file-alt"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-repeat="service in services | filter:{ isRedis: false } | orderBy:'name'">
|
||||
<td>
|
||||
<i class="fa fa-circle" uib-tooltip="{{ service.status }}" ng-style="{ color: service.status === 'active' ? '#27CE65' : (service.status === 'starting' ? '#f0ad4e' : '#d9534f') }" ng-show="service.status"></i>
|
||||
<i class="fa fa-circle-notch fa-spin" ng-hide="service.status"></i>
|
||||
</td>
|
||||
<td class="elide-table-cell">
|
||||
{{ service.displayName }}
|
||||
</td>
|
||||
<td class="elide-table-cell">
|
||||
<div class="progress progress-striped" ng-show="service.config.memory">
|
||||
<div class="progress-bar progress-bar-success" role="progressbar" style="width: {{ service.memoryPercent }}%"></div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="elide-table-cell text-center">
|
||||
<span ng-show="service.config.memory">{{ service.config.memorySwap | prettyByteSize }}</span>
|
||||
</td>
|
||||
<td class="text-right no-wrap" style="vertical-align: bottom">
|
||||
<button class="btn btn-xs btn-default" ng-click="serviceConfigure.show(service)" uib-tooltip="Configure Memory Limit" ng-show="service.config.memory"><i class="fa fa-pencil-alt"></i></button>
|
||||
<button class="btn btn-xs btn-default" ng-click="restartService(service.name)" uib-tooltip="Restart"><i class="fa fa-sync-alt" ng-class="{ 'fa-spin': service.status === 'starting' }"></i></button>
|
||||
<a class="btn btn-xs btn-default" ng-href="{{ '/logs.html?id=' + service.name }}" target="_blank" uib-tooltip="Logs"><i class="fa fa-file-alt"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-show="hasRedisServices" ng-click="redisServicesExpanded = !redisServicesExpanded" class="hand">
|
||||
<td>
|
||||
<i class="fas fa-angle-right" ng-class="{'fa-rotate-90': redisServicesExpanded }"></i>
|
||||
</td>
|
||||
<td colspan="4">redis</td>
|
||||
</tr>
|
||||
<tr ng-show="redisServicesExpanded" ng-repeat="service in services | filter:{ isRedis: true } | orderBy:'name'">
|
||||
<td>
|
||||
<i class="fa fa-circle" uib-tooltip="{{ service.status }}" ng-style="{ color: service.status === 'active' ? '#27CE65' : (service.status === 'starting' ? '#f0ad4e' : '#d9534f') }" ng-show="service.status"></i>
|
||||
<i class="fa fa-circle-notch fa-spin" ng-hide="service.status"></i>
|
||||
</td>
|
||||
<td class="elide-table-cell">
|
||||
{{ service.displayName }}
|
||||
</td>
|
||||
<td class="elide-table-cell">
|
||||
<div class="progress progress-striped" ng-show="service.config.memory">
|
||||
<div class="progress-bar progress-bar-success" role="progressbar" style="width: {{ service.memoryPercent }}%"></div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="elide-table-cell text-center">
|
||||
<span ng-show="service.config.memory">{{ service.config.memorySwap | prettyByteSize }}</span>
|
||||
</td>
|
||||
<td class="text-right no-wrap" style="vertical-align: bottom">
|
||||
<button class="btn btn-xs btn-default" ng-click="serviceConfigure.show(service)" uib-tooltip="Configure Memory Limit" ng-show="service.config.memory"><i class="fa fa-pencil-alt"></i></button>
|
||||
<button class="btn btn-xs btn-default" ng-click="restartService(service.name)" uib-tooltip="Restart"><i class="fa fa-sync-alt" ng-class="{ 'fa-spin': service.status === 'starting' }"></i></button>
|
||||
<a class="btn btn-xs btn-default" ng-href="{{ '/logs.html?id=' + service.name }}" target="_blank" uib-tooltip="Logs"><i class="fa fa-file-alt"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -9,10 +9,6 @@ angular.module('Application').controller('SystemController', ['$scope', '$locati
|
||||
Client.onReady(function () { if (!Client.getUserInfo().isAtLeastAdmin) $location.path('/'); });
|
||||
|
||||
$scope.config = Client.getConfig();
|
||||
$scope.servicesReady = false;
|
||||
$scope.services = [];
|
||||
$scope.hasRedisServices = false;
|
||||
$scope.redisServicesExpanded = false;
|
||||
$scope.memory = null;
|
||||
$scope.activeTab = 0;
|
||||
|
||||
@@ -33,103 +29,6 @@ angular.module('Application').controller('SystemController', ['$scope', '$locati
|
||||
return getRandomColor();
|
||||
}
|
||||
|
||||
function refresh(serviceName, callback) {
|
||||
callback = callback || function () {};
|
||||
|
||||
Client.getService(serviceName, function (error, result) {
|
||||
if (error) return console.log('Error getting status of ' + serviceName + ':' + error.message);
|
||||
|
||||
var service = $scope.services.find(function (s) { return s.name === serviceName; });
|
||||
if (!service) $scope.services.find(function (s) { return s.name === serviceName; });
|
||||
|
||||
service.status = result.status;
|
||||
service.config = result.config;
|
||||
service.memoryUsed = result.memoryUsed;
|
||||
service.memoryPercent = result.memoryPercent;
|
||||
|
||||
callback(null, service);
|
||||
});
|
||||
}
|
||||
|
||||
$scope.restartService = function (serviceName) {
|
||||
function waitForActive(serviceName) {
|
||||
refresh(serviceName, function (error, result) {
|
||||
if (result.status === 'active') return;
|
||||
|
||||
setTimeout(function () { waitForActive(serviceName); }, 3000);
|
||||
});
|
||||
}
|
||||
|
||||
$scope.services.find(function (s) { return s.name === serviceName; }).status = 'starting';
|
||||
|
||||
Client.restartService(serviceName, function (error) {
|
||||
if (error) return Client.error(error);
|
||||
|
||||
// show "busy" indicator for 3 seconds to show some ui activity
|
||||
setTimeout(function () { waitForActive(serviceName); }, 3000);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.serviceConfigure = {
|
||||
error: null,
|
||||
busy: false,
|
||||
service: null,
|
||||
|
||||
// form model
|
||||
memoryLimit: 0,
|
||||
memoryTicks: [],
|
||||
|
||||
show: function (service) {
|
||||
$scope.serviceConfigure.reset();
|
||||
|
||||
$scope.serviceConfigure.service = service;
|
||||
$scope.serviceConfigure.memoryLimit = service.config.memorySwap; // memory + swap
|
||||
|
||||
// TODO improve those
|
||||
$scope.serviceConfigure.memoryTicks = [];
|
||||
|
||||
// create ticks starting from manifest memory limit. the memory limit here is currently split into ram+swap (and thus *2 below)
|
||||
// TODO: the *2 will overallocate since 4GB is max swap that cloudron itself allocates
|
||||
$scope.serviceConfigure.memoryTicks = [];
|
||||
var npow2 = Math.pow(2, Math.ceil(Math.log($scope.memory.memory)/Math.log(2)));
|
||||
for (var i = 256; i <= (npow2*2/1024/1024); i *= 2) {
|
||||
$scope.serviceConfigure.memoryTicks.push(i * 1024 * 1024);
|
||||
}
|
||||
|
||||
$('#serviceConfigureModal').modal('show');
|
||||
},
|
||||
|
||||
submit: function (memoryLimit) {
|
||||
$scope.serviceConfigure.busy = true;
|
||||
$scope.serviceConfigure.error = null;
|
||||
|
||||
Client.configureService($scope.serviceConfigure.service.name, { memorySwap: memoryLimit, memory: memoryLimit/2 }, function (error) {
|
||||
$scope.serviceConfigure.busy = false;
|
||||
if (error) {
|
||||
$scope.serviceConfigure.error = error.message;
|
||||
return;
|
||||
}
|
||||
|
||||
refresh($scope.serviceConfigure.service.name);
|
||||
|
||||
$('#serviceConfigureModal').modal('hide');
|
||||
$scope.serviceConfigure.reset();
|
||||
});
|
||||
},
|
||||
|
||||
reset: function () {
|
||||
$scope.serviceConfigure.busy = false;
|
||||
$scope.serviceConfigure.error = null;
|
||||
$scope.serviceConfigure.service = null;
|
||||
|
||||
$scope.serviceConfigure.memoryLimit = 0;
|
||||
$scope.serviceConfigure.memoryTicks = [];
|
||||
|
||||
$scope.serviceConfigureForm.$setPristine();
|
||||
$scope.serviceConfigureForm.$setUntouched();
|
||||
}
|
||||
};
|
||||
|
||||
$scope.reboot = {
|
||||
busy: false,
|
||||
show: function () {
|
||||
@@ -378,37 +277,6 @@ angular.module('Application').controller('SystemController', ['$scope', '$locati
|
||||
$scope.memory = memory;
|
||||
|
||||
$scope.disks.update();
|
||||
|
||||
Client.getServices(function (error, result) {
|
||||
if (error) return Client.error(error);
|
||||
|
||||
$scope.services = result.map(function (name) {
|
||||
var displayName = name;
|
||||
var isRedis = false;
|
||||
|
||||
if (name.indexOf('redis') === 0) {
|
||||
isRedis = true;
|
||||
var app = Client.getCachedAppSync(name.slice('redis:'.length));
|
||||
if (app) {
|
||||
displayName = 'Redis (' + (app.label || app.fqdn) + ')';
|
||||
} else {
|
||||
displayName = 'Redis (unknown app)';
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
name: name,
|
||||
displayName: displayName,
|
||||
isRedis: isRedis
|
||||
};
|
||||
});
|
||||
$scope.hasRedisServices = !!$scope.services.find(function (service) { return service.isRedis; });
|
||||
|
||||
// just kick off the status fetching
|
||||
$scope.services.forEach(function (s) { refresh(s.name); });
|
||||
|
||||
$scope.servicesReady = true;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user