5 changed files with 242 additions and 23 deletions
@ -1,23 +1,35 @@ |
|||||
extends ../layouts/main |
extends ../layouts/main |
||||
block content |
block content |
||||
|
|
||||
table.uk-table.uk-table-small.uk-table-divider |
mixin renderHostList (hosts) |
||||
thead |
if Array.isArray(hosts) && (hosts.length > 0) |
||||
th Host |
table.uk-table.uk-table-small.uk-table-divider |
||||
th Status |
thead |
||||
th Memory |
th Host |
||||
th Platform |
th Status |
||||
th Arch |
th Memory |
||||
th Created |
th Platform |
||||
th Updated |
th Arch |
||||
tbody |
th Created |
||||
each host in hosts |
th Updated |
||||
tr |
tbody |
||||
td |
each host in hosts |
||||
a(href=`/admin/host/${host._id}`)= host.hostname |
tr(data-host-id= host._id) |
||||
td= host.status |
td |
||||
td= numeral((host.totalmem - host.freemem) / host.totalmem).format('0.00%') |
a(href=`/admin/host/${host._id}`)= host.hostname |
||||
td= host.platform |
td= host.status |
||||
td= host.arch |
td= numeral((host.totalmem - host.freemem) / host.totalmem).format('0.00%') |
||||
td= moment(host.created).fromNow() |
td= host.platform |
||||
td= host.updated ? moment(host.updated).fromNow() : 'N/A' |
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 { |
canvas.visit-graph { |
||||
width: 960px; |
width: 960px; |
||||
height: 360px; |
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