diff --git a/package.json b/package.json
index b626a19f..ebbadeb5 100644
--- a/package.json
+++ b/package.json
@@ -64,6 +64,7 @@
"hammerjs": "^2.0.8",
"ini": "^1.3.5",
"material-design-icons": "^3.0.1",
+ "ng-circle-progress": "^1.5.1",
"ng2-file-upload": "^1.3.0",
"ngx-device-detector": "^1.3.18",
"ngx-electron": "^2.1.1",
diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index d2f2dd46..0f7167c2 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -60,6 +60,7 @@ import { TracengTemplateDetailsComponent } from './components/preferences/tracen
import { PageNotFoundComponent } from './components/page-not-found/page-not-found.component';
import { Gns3vmComponent } from './components/preferences/gns3vm/gns3vm.component';
import { DirectLinkComponent } from './components/direct-link/direct-link.component';
+import { SystemStatusComponent } from './components/system-status/system-status.component';
const routes: Routes = [
{
@@ -74,6 +75,7 @@ const routes: Routes = [
{ path: 'settings', component: SettingsComponent },
{ path: 'settings/console', component: ConsoleComponent },
{ path: 'installed-software', component: InstalledSoftwareComponent },
+ { path: 'server/:server_id/systemstatus', component: SystemStatusComponent },
{ path: 'server/:server_ip/:server_port/project/:project_id', component: DirectLinkComponent},
{ path: 'server/:server_id/project/:project_id/snapshots', component: ListOfSnapshotsComponent },
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index a95b4a10..a9dfdd09 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -260,6 +260,10 @@ import { ConfigureGns3VMDialogComponent } from './components/servers/configure-g
import { ImportApplianceComponent } from './components/project-map/import-appliance/import-appliance.component';
import { GoogleAnalyticsService } from './services/google-analytics.service';
import { DirectLinkComponent } from './components/direct-link/direct-link.component';
+import { SystemStatusComponent } from './components/system-status/system-status.component';
+import { StatusInfoComponent } from './components/system-status/status-info/status-info.component';
+import { StatusChartComponent } from './components/system-status/status-chart/status-chart.component';
+import { NgCircleProgressModule } from 'ng-circle-progress';
if (environment.production) {
Raven.config('https://b2b1cfd9b043491eb6b566fd8acee358@sentry.io/842726', {
@@ -437,7 +441,10 @@ if (environment.production) {
Gns3vmComponent,
ConfigureGns3VMDialogComponent,
ImportApplianceComponent,
- DirectLinkComponent
+ DirectLinkComponent,
+ SystemStatusComponent,
+ StatusInfoComponent,
+ StatusChartComponent
],
imports: [
BrowserModule,
@@ -457,7 +464,8 @@ if (environment.production) {
DragAndDropModule,
DragDropModule,
MATERIAL_IMPORTS,
- DeviceDetectorModule.forRoot()
+ DeviceDetectorModule.forRoot(),
+ NgCircleProgressModule.forRoot()
],
providers: [
SettingsService,
diff --git a/src/app/components/project-map/project-map.component.html b/src/app/components/project-map/project-map.component.html
index d976c9ee..d303bd0e 100644
--- a/src/app/components/project-map/project-map.component.html
+++ b/src/app/components/project-map/project-map.component.html
@@ -147,6 +147,12 @@
center_focus_strong
+
+
+
+
diff --git a/src/app/components/system-status/status-chart/status-chart.component.html b/src/app/components/system-status/status-chart/status-chart.component.html
new file mode 100644
index 00000000..63aa6801
--- /dev/null
+++ b/src/app/components/system-status/status-chart/status-chart.component.html
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Memory total: {{formatBytes(computeStatistics.statistics.memory_total)}}
+
+
+ Memory used: {{formatBytes(computeStatistics.statistics.memory_used)}}
+
+
+ Memory free: {{formatBytes(computeStatistics.statistics.memory_free)}}
+
+
+
+
+
+ Swap total: {{formatBytes(computeStatistics.statistics.swap_total)}}
+
+
+ Swap used: {{formatBytes(computeStatistics.statistics.swap_used)}}
+
+
+ Swap free: {{formatBytes(computeStatistics.statistics.swap_free)}}
+
+
+
diff --git a/src/app/components/system-status/status-chart/status-chart.component.scss b/src/app/components/system-status/status-chart/status-chart.component.scss
new file mode 100644
index 00000000..a639bdc2
--- /dev/null
+++ b/src/app/components/system-status/status-chart/status-chart.component.scss
@@ -0,0 +1,6 @@
+.wrapper {
+ width: 100%;
+ display: flex;
+ justify-content: space-between;
+ margin-bottom: 20px;
+}
diff --git a/src/app/components/system-status/status-chart/status-chart.component.spec.ts b/src/app/components/system-status/status-chart/status-chart.component.spec.ts
new file mode 100644
index 00000000..e69de29b
diff --git a/src/app/components/system-status/status-chart/status-chart.component.ts b/src/app/components/system-status/status-chart/status-chart.component.ts
new file mode 100644
index 00000000..05647246
--- /dev/null
+++ b/src/app/components/system-status/status-chart/status-chart.component.ts
@@ -0,0 +1,28 @@
+import { Component, OnInit, Input } from "@angular/core";
+import { ComputeStatistics } from '../../../models/computeStatistics';
+
+
+@Component({
+ selector: 'app-status-chart',
+ templateUrl: './status-chart.component.html',
+ styleUrls: ['./status-chart.component.scss']
+})
+export class StatusChartComponent implements OnInit {
+ @Input() computeStatistics: ComputeStatistics;
+
+ constructor() {}
+
+ ngOnInit() {}
+
+ formatBytes(bytes, decimals = 2) {
+ if (bytes === 0) return '0 Bytes';
+
+ const k = 1024;
+ const dm = decimals < 0 ? 0 : decimals;
+ const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
+
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
+
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
+ }
+}
diff --git a/src/app/components/system-status/status-info/status-info.component.html b/src/app/components/system-status/status-info/status-info.component.html
new file mode 100644
index 00000000..7e242219
--- /dev/null
+++ b/src/app/components/system-status/status-info/status-info.component.html
@@ -0,0 +1,4 @@
+
+ {{statistics.compute_name}}
+
+
diff --git a/src/app/components/system-status/status-info/status-info.component.scss b/src/app/components/system-status/status-info/status-info.component.scss
new file mode 100644
index 00000000..e69de29b
diff --git a/src/app/components/system-status/status-info/status-info.component.spec.ts b/src/app/components/system-status/status-info/status-info.component.spec.ts
new file mode 100644
index 00000000..e69de29b
diff --git a/src/app/components/system-status/status-info/status-info.component.ts b/src/app/components/system-status/status-info/status-info.component.ts
new file mode 100644
index 00000000..7647db93
--- /dev/null
+++ b/src/app/components/system-status/status-info/status-info.component.ts
@@ -0,0 +1,47 @@
+import { Component, OnInit } from "@angular/core";
+import { ActivatedRoute } from '@angular/router';
+import { ComputeService } from '../../../services/compute.service';
+import { ComputeStatistics } from '../../../models/computeStatistics';
+import { ServerService } from '../../../services/server.service';
+import { Server } from '../../../models/server';
+import { ToasterService } from '../../../services/toaster.service';
+
+
+@Component({
+ selector: 'app-status-info',
+ templateUrl: './status-info.component.html',
+ styleUrls: ['./status-info.component.scss']
+})
+export class StatusInfoComponent implements OnInit {
+ public serverId: string = "";
+ public computeStatistics: ComputeStatistics[] = [];
+
+ constructor(
+ private route: ActivatedRoute,
+ private computeService: ComputeService,
+ private serverService: ServerService,
+ private toasterService: ToasterService
+ ) {}
+
+ ngOnInit() {
+ this.serverId = this.route.snapshot.paramMap.get("server_id");
+ this.getStatistics();
+ }
+
+ getStatistics() {
+ this.serverService.get(Number(this.serverId)).then((server: Server) => {
+ this.computeService.getStatistics(server).subscribe(
+ (statistics: ComputeStatistics[]) => {
+ this.computeStatistics = statistics;
+ setTimeout(() =>
+ {
+ this.getStatistics();
+ },
+ 10000);
+ }),
+ error => {
+ this.toasterService.error('Required server version is 2.3')
+ }
+ });
+ }
+}
diff --git a/src/app/components/system-status/system-status.component.html b/src/app/components/system-status/system-status.component.html
new file mode 100644
index 00000000..d47624d2
--- /dev/null
+++ b/src/app/components/system-status/system-status.component.html
@@ -0,0 +1,10 @@
+
diff --git a/src/app/components/system-status/system-status.component.scss b/src/app/components/system-status/system-status.component.scss
new file mode 100644
index 00000000..e69de29b
diff --git a/src/app/components/system-status/system-status.component.spec.ts b/src/app/components/system-status/system-status.component.spec.ts
new file mode 100644
index 00000000..e69de29b
diff --git a/src/app/components/system-status/system-status.component.ts b/src/app/components/system-status/system-status.component.ts
new file mode 100644
index 00000000..f2915a0a
--- /dev/null
+++ b/src/app/components/system-status/system-status.component.ts
@@ -0,0 +1,20 @@
+import { Component, OnInit } from "@angular/core";
+import { ActivatedRoute } from '@angular/router';
+
+
+@Component({
+ selector: 'app-system-status',
+ templateUrl: './system-status.component.html',
+ styleUrls: ['./system-status.component.scss']
+})
+export class SystemStatusComponent implements OnInit {
+ public serverId: string = "";
+
+ constructor(
+ private route: ActivatedRoute
+ ) {}
+
+ ngOnInit() {
+ this.serverId = this.route.snapshot.paramMap.get("server_id");
+ }
+}
diff --git a/src/app/material.imports.ts b/src/app/material.imports.ts
index 267561d2..359be1a5 100644
--- a/src/app/material.imports.ts
+++ b/src/app/material.imports.ts
@@ -22,7 +22,8 @@ import {
MatGridListModule,
MatTabsModule,
MatTreeModule,
- MatBottomSheetModule
+ MatBottomSheetModule,
+ MatChipsModule
} from '@angular/material';
export const MATERIAL_IMPORTS = [
@@ -49,5 +50,6 @@ export const MATERIAL_IMPORTS = [
MatGridListModule,
MatTabsModule,
MatTreeModule,
- MatBottomSheetModule
+ MatBottomSheetModule,
+ MatChipsModule
];
diff --git a/src/app/models/computeStatistics.ts b/src/app/models/computeStatistics.ts
new file mode 100644
index 00000000..c5d19031
--- /dev/null
+++ b/src/app/models/computeStatistics.ts
@@ -0,0 +1,19 @@
+export interface Statistics {
+ cpu_usage_percent: number;
+ disk_usage_percent: number;
+ load_average_percent: number[];
+ memory_free: number;
+ memory_total: number;
+ memory_usage_percent: number;
+ memory_used: number;
+ swap_free: number;
+ swap_total: number;
+ swap_usage_percent: number;
+ swap_used: number;
+}
+
+export interface ComputeStatistics {
+ compute_id: string;
+ compute_name: string;
+ statistics: Statistics;
+}
diff --git a/src/app/services/compute.service.ts b/src/app/services/compute.service.ts
index e6b9bfac..1799e4e2 100644
--- a/src/app/services/compute.service.ts
+++ b/src/app/services/compute.service.ts
@@ -3,6 +3,7 @@ import { HttpServer } from './http-server.service';
import { Server } from '../models/server';
import { Compute } from '../models/compute';
import { Observable } from 'rxjs';
+import { ComputeStatistics } from '../models/computeStatistics';
@Injectable()
export class ComputeService {
@@ -15,4 +16,8 @@ export class ComputeService {
getUploadPath(server: Server, emulator: string, filename: string) {
return `http://${server.host}:${server.port}/v2/${emulator}/images/${filename}`;
}
+
+ getStatistics(server: Server): Observable {
+ return this.httpServer.get(server, `/statistics`)
+ }
}
diff --git a/yarn.lock b/yarn.lock
index 7e22c407..1a5ac95c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3748,11 +3748,6 @@ detect-indent@^4.0.0:
dependencies:
repeating "^2.0.0"
-detect-libc@^1.0.2:
- version "1.0.3"
- resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
- integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
-
detect-node@^2.0.4:
version "2.0.4"
resolved "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c"
@@ -5193,7 +5188,7 @@ humanize-ms@^1.2.1:
dependencies:
ms "^2.0.0"
-iconv-lite@0.4, iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
+iconv-lite@0.4, iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@~0.4.13:
version "0.4.24"
resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
@@ -6705,15 +6700,6 @@ nanomatch@^1.2.9:
snapdragon "^0.8.1"
to-regex "^3.0.1"
-needle@^2.2.1:
- version "2.4.0"
- resolved "https://registry.npmjs.org/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c"
- integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg==
- dependencies:
- debug "^3.2.6"
- iconv-lite "^0.4.4"
- sax "^1.2.4"
-
negotiator@0.6.2:
version "0.6.2"
resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
@@ -6724,6 +6710,13 @@ neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1:
resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c"
integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==
+ng-circle-progress@^1.5.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/ng-circle-progress/-/ng-circle-progress-1.5.1.tgz#ea4ea89318754b929dc1550d5779e391d7c5c646"
+ integrity sha512-gJ0SdWc+TkXckfbhbvUY522yjya3qcc1a3lGvvVyLsUfSOgll8LQaZGDEko84d8dk8vYO83n0O5vP+e8bJTInQ==
+ dependencies:
+ tslib "^1.9.0"
+
ng2-file-upload@^1.3.0:
version "1.4.0"
resolved "https://registry.npmjs.org/ng2-file-upload/-/ng2-file-upload-1.4.0.tgz#8dea28d573234c52af474ad2a4001b335271e5c4"
@@ -6816,22 +6809,6 @@ node-libs-browser@^2.2.1:
util "^0.11.0"
vm-browserify "^1.0.1"
-node-pre-gyp@*:
- version "0.14.0"
- resolved "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83"
- integrity sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==
- dependencies:
- detect-libc "^1.0.2"
- mkdirp "^0.5.1"
- needle "^2.2.1"
- nopt "^4.0.1"
- npm-packlist "^1.1.6"
- npmlog "^4.0.2"
- rc "^1.2.7"
- rimraf "^2.6.1"
- semver "^5.3.0"
- tar "^4.4.2"
-
node-releases@^1.1.25, node-releases@^1.1.42:
version "1.1.43"
resolved "https://registry.npmjs.org/node-releases/-/node-releases-1.1.43.tgz#2c6ca237f88ce11d49631f11190bb01f8d0549f2"
@@ -6964,7 +6941,7 @@ npm-package-arg@^6.0.0, npm-package-arg@^6.1.0:
semver "^5.6.0"
validate-npm-package-name "^3.0.0"
-npm-packlist@^1.1.12, npm-packlist@^1.1.6:
+npm-packlist@^1.1.12:
version "1.4.7"
resolved "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.7.tgz#9e954365a06b80b18111ea900945af4f88ed4848"
integrity sha512-vAj7dIkp5NhieaGZxBJB8fF4R0078rqsmhJcAfXZ6O7JJhjhPK96n5Ry1oZcfLXgfun0GWTZPOxaEyqv8GBykQ==
@@ -7010,7 +6987,7 @@ npm-run-path@^2.0.0:
dependencies:
path-key "^2.0.0"
-"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.2:
+"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0:
version "4.1.2"
resolved "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==
@@ -7846,7 +7823,7 @@ raw-loader@3.1.0:
loader-utils "^1.1.0"
schema-utils "^2.0.1"
-rc@^1.2.7, rc@^1.2.8:
+rc@^1.2.8:
version "1.2.8"
resolved "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
@@ -8229,7 +8206,7 @@ rfdc@^1.1.4:
resolved "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz#ba72cc1367a0ccd9cf81a870b3b58bd3ad07f8c2"
integrity sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==
-rimraf@2, rimraf@^2.2.8, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3:
+rimraf@2, rimraf@^2.2.8, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.2, rimraf@^2.6.3:
version "2.7.1"
resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
@@ -9232,7 +9209,7 @@ tar@^2.0.0:
fstream "^1.0.12"
inherits "2"
-tar@^4.4.2, tar@^4.4.8:
+tar@^4.4.8:
version "4.4.13"
resolved "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525"
integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==