boidcmd
Version:
<a href="https://www.boid.com/"><img src="https://raw.githubusercontent.com/Boid-John/eos-airdrops/master/logos/BoidLogo-lg.png" title="Boid" alt="Boid"></a>
541 lines (474 loc) • 16.6 kB
JavaScript
var cmd = require('node-cmd')
var convert = require('xml-js')
var fs = require('fs')
var client = require("./api.js")
const minimist = require('minimist')
const ora = require('ora')
const spinner = ora()
const readline = require('readline')
const { spawn } = require('child_process')
const exec = require('child_process').exec
var form = {
email: '',
password: '',
invitedById: null,
device: null
}
var projectObject = {
deviceId: '',
wcgid: ''
}
module.exports = () => {
const args = minimist(process.argv.slice(2))
var boidcmd = args._[0]
var value = args._[1]
if(args.version || args.v) {
boidcmd = 'version'
}
if(args.help || args.h || args._[0] == undefined) {
boidcmd = 'help'
}
switch (boidcmd) {
case 'setCPU':
setCPU(value)
break
case 'devices':
checkDevices(value)
break
case 'workunits':
getWorkUnits()
break
case 'setup':
setupBoid()
break
case 'install':
installBoid()
break
case 'run':
runBoid()
break
case 'quit':
quitBoid()
break
case 'resume':
resume()
break
case 'suspend':
suspend()
break
case 'status':
statusBoid()
break
case 'help':
require('./help')
break
case 'version':
require('./version')
break
default:
console.error(`"${boidcmd}" is not a valid command!`)
process.exit(1)
break
}
}
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
function isProcessRunning(processName){
const cmd = `ps -A`
return new Promise(function(resolve,reject){
exec(cmd, function(err,stdout,stderr) {
//console.log(stdout.indexOf('boinc'))
resolve(stdout.toLowerCase().indexOf(processName.toLowerCase()) > -1)
})
})
}
async function verifyBoinc(){
let status = await isProcessRunning('boinc')
if(!status){
console.log("boinc process is not running, please run systemctl start boinc-client")
process.exit(-1)
}
}
async function setupBoid(){
await verifyBoinc()
var form = {}
rl.stdoutMuted = false
rl.question('Boid Account Email:', (email) => {
form.email = email
rl.question('Boid Account Password: ', (password) => {
form.password = password
client.send(form,client.endPoint.authenticateUser,function(response){
response = JSON.parse(response)
if (response.invalid){
console.log()
console.log(response.invalid)
return setupBoid()
}
client.setUserData(response)
rl.close()
setupBoinc()
})
})
rl.stdoutMuted = true
})
rl._writeToOutput = function _writeToOutput(stringToWrite) {
if (rl.stdoutMuted)
rl.output.write("*")
else
rl.output.write(stringToWrite)
}
}
async function checkDevices(value){
var form = {}
rl.stdoutMuted = false
rl.question('Boid Account Email:', (email) => {
form.email = email
rl.question('Boid Account Password: ', (password) => {
form.password = password
client.send(form,client.endPoint.authenticateUser,function(response){
response = JSON.parse(response)
if (response.invalid){
console.log()
console.log(response.invalid)
return checkDevices(value)
}
client.setUserData(response)
rl.close()
client.send({"id":response.id},client.endPoint.getUser,function(obj){
//console.log(obj)
var json = JSON.parse(obj)
if(value == "csv"){
console.log("\nUsername: ", json.username )
console.log("User Boid Power: ", json.dPower)
console.log("Registered devices (CSV format):")
console.log("ID,STATUS,TYPE,POWER,PENDING,NAME")
for(count in json.devices){
console.log(json.devices[count].id+","+json.devices[count].status+","+json.devices[count].type+","+json.devices[count].power+","+json.devices[count].pending+","+json.devices[count].name)
}
}
else {
console.log(json)
}
})
})
})
rl.stdoutMuted = true
// rl.history = rl.history.slice(1)
})
rl._writeToOutput = function _writeToOutput(stringToWrite) {
if (rl.stdoutMuted)
rl.output.write("*")
else
rl.output.write(stringToWrite)
}
}
async function getWorkUnits(){
var form = {}
rl.stdoutMuted = false
rl.question('Boid Account Email:', (email) => {
form.email = email
rl.question('Boid Account Password: ', (password) => {
form.password = password
client.send(form,client.endPoint.authenticateUser,function(response){
response = JSON.parse(response)
if (response.invalid){
console.log()
console.log(response.invalid)
return getWorkUnits()
}
client.setUserData(response)
rl.close()
// Find out the local hostId (world grid community host id)
fs.readFile( '/var/lib/boinc-client/client_state.xml', function(err, data) {
var result1 = convert.xml2json(data, {compact: true, spaces: 4});
var object = JSON.parse(result1);
var project = object.client_state.project
if (project == undefined){
console.error("ERROR: you have no project attached, the boinc daemon is likely not installed or running.")
process.exit(-1)
}
if (project.length > 1){
console.error("ERROR: you have more than 1 project already configured, boidcmd requires you to only be attached to www.worldcommunitygrid.org")
process.exit(-1)
}
var wcgid = project.hostid._text
console.log("\nquerying boid for workunits for hostid: "+wcgid)
client.send({"wcgid": wcgid, "valid": true},client.endPoint.getWorkUnits,function(obj){
//console.log(obj)
var json = JSON.parse(obj)
if (json.length > 0){
console.log(json)
}
else console.log("this device has not submitted any workunits recently.")
})
})
})
})
rl.stdoutMuted = true
// rl.history = rl.history.slice(1)
})
rl._writeToOutput = function _writeToOutput(stringToWrite) {
if (rl.stdoutMuted)
rl.output.write("*")
else
rl.output.write(stringToWrite)
}
}
function runBoid(){
const subprocess = spawn('boinc',['--dir', '/var/lib/boinc-client/', '--daemon', '--allow_remote_gui_rpc'], {
detached: true,
stdio: 'ignore'
});
subprocess.unref();
}
function quitBoid(){
const subprocess = spawn('boinccmd',['--quit'], {
detached: true,
stdio: 'ignore'
});
subprocess.unref();
console.log("boinc stopped..")
process.exit(0)
}
async function installBoid() {
await verifyBoinc()
cmd.get(
`
boinccmd --project_attach http://www.worldcommunitygrid.org/ 1061556_a0c611b081f8692b7ef0c11d39e6105c
`,
function(err, data, stderr){
if (!err) {
console.log("\nwaiting for project information")
spinner.start()
setTimeout(projectCheck,3000)
} else {
console.log('error', err)
}
}
);
}
function projectCheck(){
fs.readFile( '/var/lib/boinc-client/client_state.xml', function(err, data) {
var result1 = convert.xml2json(data, {compact: true, spaces: 4});
var object = JSON.parse(result1);
var hostInfo = object.client_state.host_info
var project = object.client_state.project
var name = hostInfo.domain_name._text
var cpid = hostInfo.host_cpid._text
var threads = hostInfo.p_ncpus._text
var model = hostInfo.p_model._text
if (project == undefined){
console.error("ERROR: you have no project attached, the boinc daemon is likely not installed or running.")
process.exit(-1)
}
if (project.length > 1){
console.error("ERROR: you have more than 1 project already configured, boidcmd requires you to only be attached to www.worldcommunitygrid.org")
process.exit(-1)
}
var wcgid = project.hostid._text
if(wcgid == "0"){
setTimeout(projectCheck,3000)
console.log("Timeout while checking project status.")
}else{
spinner.stop()
console.log("Success!")
}
});
}
function valBetween(v, min, max) {
return Math.min(max, Math.max(min, v))
}
async function setCPU(value){
await verifyBoinc()
fs.readFile( '/var/lib/boinc-client/global_prefs_override.xml', function(err, data) {
var result1 = convert.xml2json(data, {compact: true, spaces: 4});
var object = JSON.parse(result1);
object.global_preferences.cpu_usage_limit = valBetween(value,0,100)
var options = {compact:true, ignoreComment:true, spaces:4};
var xmlResult = convert.json2xml(object,options);
console.log(object)
console.log(xmlResult)
fs.writeFile('/var/lib/boinc-client/global_prefs_override.xml',xmlResult,function(err){
if (err) throw err;
readGlobalPrefsOverride()
})
});
}
async function readGlobalPrefsOverride(){
await verifyBoinc()
isProcessRunning("boinc", (status) => {
if(!status){
console.log("boinc process is not running, please run systemctl start boinc-client")
process.exit(-1)
}
})
spinner.start()
cmd.get(
`
boinccmd --read_global_prefs_override
`,
function(err, data, stderr){
if (!err) {
console.log("Sucessfully set cpu limit")
spinner.stop()
console.log(data)
console.log(stderr)
process.exit(0);
} else {
console.log('error', err)
}
}
);
}
async function setupBoinc(){
await verifyBoinc()
cmd.get(
`
boinccmd --project_attach http://www.worldcommunitygrid.org/ 1061556_a0c611b081f8692b7ef0c11d39e6105c
`,
function(err, data, stderr){
if (!err) {
console.log("\nwaiting for project information")
spinner.start()
setTimeout(readFiles,3000)
} else {
// if (error.search(''))
console.log('error', err)
setTimeout(readFiles,3000)
}
}
);
}
async function resume() {
await verifyBoinc()
cmd.get(
`
boinccmd --project http://www.worldcommunitygrid.org/ resume
`,
function(err, data, stderr){
if (!err) {
console.log(data)
console.log(stderr)
process.exit(0);
} else {
console.log('error', err)
}
}
);
}
async function suspend() {
await verifyBoinc()
cmd.get(
`
boinccmd --project http://www.worldcommunitygrid.org/ suspend
`,
function(err, data, stderr){
if (!err) {
console.log(data)
console.log(stderr)
process.exit(0);
} else {
console.log('error', err)
}
}
);
}
async function statusBoid() {
await verifyBoinc()
var pass = "n/a"
fs.readFile('/var/lib/boinc-client/gui_rpc_auth.cfg', function(err, data) {
console.log(data)
pass = data
console.log(err)
})
console.log(pass)
cmd.get(
`
boinccmd --get_simple_gui_info
`,
function(err, data, stderr){
if (!err) {
console.log(data)
console.log(stderr)
process.exit(0);
} else {
console.log('error', err)
}
}
);
}
function readFiles(callback) {
fs.readFile( '/var/lib/boinc-client/client_state.xml', function(err, data) {
var result1 = convert.xml2json(data, {compact: true, spaces: 4});
var object = JSON.parse(result1);
var hostInfo = object.client_state.host_info
var name = hostInfo.domain_name._text
var cpid = hostInfo.host_cpid._text
var threads = hostInfo.p_ncpus._text
var model = hostInfo.p_model._text
var project = object.client_state.project
if (project == undefined){
console.error("ERROR: you have no project attached, the boinc daemon is likely not installed or running.")
process.exit(-1)
}
if (project.length > 1){
console.error("ERROR: you have more than 1 project already configured, boidcmd requires you to only be attached to www.worldcommunitygrid.org")
process.exit(-1)
}
var wcgid = project.hostid._text
if(wcgid == "0"){
setTimeout(readFiles,3000)
}else{
spinner.stop()
projectObject.wcgid = wcgid
var device = {
cpid:cpid,
//cpid:makeid(),
name:name,
type:"LINUX"
}
console.log("Adding device to boid account")
client.send(device,client.endPoint.addDevice,function(obj){
var json = JSON.parse(obj)
if(json.error != undefined) {
console.log("error adding Device")
}else{
console.log("Added device to boid account")
var deviceId = json.id
client.send({"id":deviceId},client.endPoint.getDevice,function(obj){
var json = JSON.parse(obj)
console.log(json)
projectObject.deviceId = json.id
client.send(projectObject,client.endPoint.updateDevice,function(obj){
var json = JSON.parse(obj)
console.log(json)
console.log("Setting up project")
if (json.error == undefined) {
//console.log(json.error)
}else{
client.send({"id":projectObject.deviceId},client.endPoint.getDevice,function(obj){
var json = JSON.parse(obj)
if(json.wcgid != null){
if(projectObject.wcgid == json.wcgid){
console.log("Project setup Success!")
}else {
console.log(" Device is using a different wcgid wcgid:"+json.wcgid)
}
}else{
//some other issue caused a problem
}
console.log('Setup complete. Run "boidcmd status" to view project status')
process.exit(0);
})
}
})
})
}
})
}
});
}
// sudo aptitude install boinc-client
// sudo aptitude purge boinc-client