You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

161 lines
5.5 KiB

const { Injectable } = require('flitter-di')
const ImplementationError = require('libflitter/errors/ImplementationError')
const uuid = require('uuid/v4')
const UniversalPath = require('../logical/UniversalPath')
const SystemMetrics = require('../logical/SystemMetrics')
const DNFManager = require('../logical/packages/DNFManager')
const APTManager = require('../logical/packages/APTManager')
const SystemDManager = require('../logical/services/SystemDManager')
class Host extends Injectable {
static get services() {
return [...super.services, 'utility']
}
_temp_path_command = 'mktemp -d'
_temp_file_command = 'mktemp'
_cpu_percentage_command = `grep 'cpu ' /proc/stat | awk '{usage=($2+$4)*100/($2+$4+$5)} END {print usage}'`
_ram_percentage_command = `free | grep Mem | awk '{print $3/$2 * 100.0}'`
_mount_point_percentage_command = `df -hl | grep -w '%%MOUNTPOINT%%$' | awk '{print $5}'`
_list_mount_points_command = `df -hl | grep '/' | awk '{print $6}'`
_file_directory_delete_command = `rm -rf "%%RESOURCE%%"`
_resolve_path_command = `readlink -f "%%PATH%%"`
_reboot_command = `reboot`
constructor(config) {
super()
this.config = config
this.name = config.name
if ( config.packages && config.packages.type ) {
if ( config.packages.type === 'dnf' ) {
this.packages = new DNFManager(this)
} else if ( config.packages.type === 'apt' ) {
this.packages = new APTManager(this)
} else {
throw new Error(`Invalid or unknown package manager type: ${config.packages.type}`)
}
}
if ( config.services && config.services.type ) {
if ( config.services.type === 'systemd' ) {
this.services = new SystemDManager(this)
} else {
throw new Error(`Invalid or unknown service manager type: ${config.services.type}`)
}
}
}
async execute(command) {
throw new ImplementationError()
}
async open_file_read_stream(file_path) {
throw new ImplementationError()
}
async open_file_write_stream(file_path) {
throw new ImplementationError()
}
async is_alive() {
try {
const unique_id = uuid()
const result = await this.execute(`echo "${unique_id}"`)
return (result.exit_code === 0 && (result.clean_out.length > 0 && result.clean_out[0] === unique_id))
} catch (e) {
return false
}
}
async get_temp_path() {
const path_string = await this.run_line_result(this._temp_path_command)
return new UniversalPath(this, path_string, UniversalPath.PATH_TYPE_DIRECTORY)
}
async get_temp_file() {
const file_string = await this.run_line_result(this._temp_file_command)
return new UniversalPath(this, file_string, UniversalPath.PATH_TYPE_FILE)
}
async get_path(local_path) {
const host_path = new UniversalPath(this, local_path)
await host_path.classify()
return host_path
}
async metrics() {
const metric = new SystemMetrics()
const cpu_percent = Number(await this.run_line_result(this._cpu_percentage_command))
const ram_percent = Number(await this.run_line_result(this._ram_percentage_command))
metric.cpu(cpu_percent)
metric.ram(ram_percent)
const mount_points = await this.get_mount_points()
for ( const point of mount_points ) {
metric.mount(point, await this.get_mountpoint_utilization(point))
}
return metric
}
async delete_path(resource_path) {
resource_path = typeof resource_path === 'string' ? resource_path : resource_path.path
await this.execute(this._file_directory_delete_command.replace('%%RESOURCE%%', resource_path))
}
async resolve_path(resource_path) {
resource_path = typeof resource_path === 'string' ? resource_path : resource_path.path
return this.run_line_result(this._resolve_path_command.replace('%%PATH%%', resource_path))
}
async get_mount_points() {
const result = await this.execute(this._list_mount_points_command)
if ( result.exit_code !== 0 ) {
throw new Error('Unable to determine mount points. Command execution error.')
}
return result.clean_out
}
async get_mountpoint_utilization(mountpoint) {
const cmd = this._mount_point_percentage_command.replace('%%MOUNTPOINT%%', mountpoint)
const result = await this.execute(cmd)
if ( result.exit_code !== 0 ) {
throw new Error('Unable to determine mount utilization. Command execution error.')
}
return Number(result.clean_out[0].replace('%', ''))/100
}
async run_line_result(command) {
const result = await this.execute(command)
if ( result.exit_code !== 0 || result.clean_out.length < 1 ) {
throw new Error('Unable to get line output from command: '+command)
}
return this.utility.infer(result.clean_out[0].trim())
}
async run(command) {
const result = await this.execute(command)
if ( result.exit_code !== 0 ) {
throw new Error('Unable to run command: '+command)
}
return result
}
async list_files_in_directory(local_path) {
throw new ImplementationError()
}
async _cleanup() {}
async reboot() {
await this.run_line_result(this._reboot_command)
}
}
module.exports = exports = Host