5 changed files with 242 additions and 23 deletions
@ -1,23 +1,35 @@ |
|||
extends ../layouts/main |
|||
block content |
|||
|
|||
table.uk-table.uk-table-small.uk-table-divider |
|||
thead |
|||
th Host |
|||
th Status |
|||
th Memory |
|||
th Platform |
|||
th Arch |
|||
th Created |
|||
th Updated |
|||
tbody |
|||
each host in hosts |
|||
tr |
|||
td |
|||
a(href=`/admin/host/${host._id}`)= host.hostname |
|||
td= host.status |
|||
td= numeral((host.totalmem - host.freemem) / host.totalmem).format('0.00%') |
|||
td= host.platform |
|||
td= host.arch |
|||
td= moment(host.created).fromNow() |
|||
td= host.updated ? moment(host.updated).fromNow() : 'N/A' |
|||
mixin renderHostList (hosts) |
|||
if Array.isArray(hosts) && (hosts.length > 0) |
|||
table.uk-table.uk-table-small.uk-table-divider |
|||
thead |
|||
th Host |
|||
th Status |
|||
th Memory |
|||
th Platform |
|||
th Arch |
|||
th Created |
|||
th Updated |
|||
tbody |
|||
each host in hosts |
|||
tr(data-host-id= host._id) |
|||
td |
|||
a(href=`/admin/host/${host._id}`)= host.hostname |
|||
td= host.status |
|||
td= numeral((host.totalmem - host.freemem) / host.totalmem).format('0.00%') |
|||
td= host.platform |
|||
td= host.arch |
|||
td= moment(host.created).fromNow() |
|||
td= host.updated ? moment(host.updated).fromNow() : 'N/A' |
|||
else |
|||
div The host list is empty |
|||
|
|||
if Array.isArray(activeHosts) && (activeHosts.length > 0) |
|||
h2 Active hosts |
|||
+renderHostList(activeHosts) |
|||
|
|||
if Array.isArray(crashedHosts) && (crashedHosts.length > 0) |
|||
h2 Crashed hosts |
|||
+renderHostList(crashedHosts) |
@ -0,0 +1,80 @@ |
|||
// host-services.js
|
|||
// Copyright (C) 2021 Digital Telepresence, LLC
|
|||
// License: Apache-2.0
|
|||
|
|||
'use strict'; |
|||
|
|||
const path = require('path'); |
|||
|
|||
require('dotenv').config({ path: path.resolve(__dirname, '..', '..', '.env') }); |
|||
|
|||
const mongoose = require('mongoose'); |
|||
|
|||
const { |
|||
SitePlatform, |
|||
SiteAsync, |
|||
SiteLog, |
|||
SiteError, |
|||
} = require(path.join(__dirname, '..', '..', 'lib', 'site-lib')); |
|||
|
|||
const { CronJob } = require('cron'); |
|||
|
|||
const CRON_TIMEZONE = 'America/New_York'; |
|||
|
|||
module.pkg = require(path.resolve(__dirname, '..', '..', 'package.json')); |
|||
module.config = { |
|||
componentName: 'reeeper', |
|||
root: path.resolve(__dirname, '..', '..'), |
|||
}; |
|||
|
|||
module.log = new SiteLog(module, module.config.componentName); |
|||
|
|||
module.expireCrashedHosts = async ( ) => { |
|||
const NetHost = mongoose.model('NetHost'); |
|||
try { |
|||
await NetHost |
|||
.find({ status: 'crashed' }) |
|||
.select('_id hostname') |
|||
.lean() |
|||
.cursor() |
|||
.eachAsync(async (host) => { |
|||
module.log.info('deactivating crashed host', { hostname: host.hostname }); |
|||
await NetHost.updateOne({ _id: host._id }, { $set: { status: 'inactive' } }); |
|||
}); |
|||
} catch (error) { |
|||
module.log.error('failed to expire crashed hosts', { error }); |
|||
} |
|||
}; |
|||
|
|||
(async ( ) => { |
|||
try { |
|||
process.once('SIGINT', async ( ) => { |
|||
module.log.info('SIGINT received'); |
|||
module.log.info('requesting shutdown...'); |
|||
|
|||
const exitCode = await SitePlatform.shutdown(); |
|||
process.nextTick(( ) => { |
|||
process.exit(exitCode); |
|||
}); |
|||
}); |
|||
|
|||
/* |
|||
* Site Platform startup |
|||
*/ |
|||
await SitePlatform.startPlatform(module); |
|||
|
|||
await module.expireCrashedHosts(); // first-run the expirations
|
|||
|
|||
module.expireJob = new CronJob( |
|||
'*/5 * * * * *', |
|||
module.expireCrashedHosts, |
|||
null, true, CRON_TIMEZONE, |
|||
); |
|||
|
|||
module.log.info(`${module.pkg.name} v${module.pkg.version} ${module.config.componentName} started`); |
|||
} catch (error) { |
|||
module.log.error('failed to start Host Cache worker', { error }); |
|||
process.exit(-1); |
|||
} |
|||
|
|||
})(); |
@ -1,7 +1,86 @@ |
|||
.links-dashboard { |
|||
.dtp-dashboard-cluster { |
|||
|
|||
canvas.visit-graph { |
|||
width: 960px; |
|||
height: 360px; |
|||
} |
|||
|
|||
fieldset { |
|||
border-color: #9e9e9e; |
|||
color: #c8c8c8; |
|||
|
|||
legend { |
|||
font-family: 'Courier New', Courier, monospace; |
|||
font-size: 11px; |
|||
color: #9e9e9e; |
|||
} |
|||
} |
|||
|
|||
.dtp-cpu-graph { |
|||
background: none; |
|||
|
|||
&.cpu-overload { |
|||
background: #4e0000; |
|||
} |
|||
} |
|||
|
|||
.dtp-stat-cell { |
|||
line-height: 1; |
|||
} |
|||
|
|||
.dtp-stats-bar { |
|||
width: 100%; |
|||
height: 16px; |
|||
margin: 0; |
|||
padding: 0; |
|||
|
|||
.dtp-cpu-stat-bar { |
|||
display: inline-block; |
|||
height: 16px; |
|||
text-align: center; |
|||
font-size: 10px; |
|||
overflow: hidden; |
|||
|
|||
&.dtp-cpu-user { |
|||
background-color: #008000; |
|||
} |
|||
&.dtp-cpu-nice { |
|||
background-color: #808080; |
|||
} |
|||
&.dtp-cpu-sys { |
|||
background-color: #808000; |
|||
} |
|||
&.dtp-cpu-idle { |
|||
background-color: #484848; |
|||
} |
|||
&.dtp-cpu-irq { |
|||
background-color: #800000; |
|||
} |
|||
} |
|||
|
|||
.dtp-mem-stat-bar { |
|||
display: inline-block; |
|||
height: 16px; |
|||
text-align: center; |
|||
font-size: 10px; |
|||
overflow: hidden; |
|||
|
|||
&.dtp-mem-used { |
|||
background-color: #008000; |
|||
} |
|||
&.dtp-mem-available { |
|||
background-color: #404040; |
|||
} |
|||
|
|||
&.dtp-mem-cached { |
|||
background-color: #008000; |
|||
} |
|||
&.dtp-mem-buffers { |
|||
background-color: #004000; |
|||
} |
|||
&.dtp-mem-slab { |
|||
background-color: #808000; |
|||
} |
|||
} |
|||
} |
|||
} |
Loading…
Reference in new issue