175 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			175 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 'use strict';
 | |
| const util = require('util');
 | |
| const exec = util.promisify(require('child_process').exec)
 | |
| 
 | |
| 
 | |
| class Local{
 | |
| 	async sysExec(command){
 | |
| 		try{
 | |
| 			return await exec(command)
 | |
| 		}catch(error){
 | |
| 			throw(error);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	async exec(...args){
 | |
| 		await this.sysExec()
 | |
| 	}
 | |
| }
 | |
| 
 | |
| class SSH extends Local{
 | |
| 	constructor(args){
 | |
| 		super()
 | |
| 		this.user = args.user;
 | |
| 		this.host = args.host;
 | |
| 		this.keyPath = args.keyPath;
 | |
| 	}
 | |
| 
 | |
| 	async sysExec(command){try{
 | |
| 		// console.log('command', command)
 | |
| 		command = new Buffer.from(command).toString('base64');
 | |
| 		command = `ssh -i "${this.keyPath}" -o StrictHostKeyChecking=no ${this.user}@${this.host} "echo ${command} | base64 --decode | bash"`;
 | |
| 		return await super.sysExec(command);
 | |
| 	}catch(error){
 | |
| 		throw error;
 | |
| 	}}
 | |
| }
 | |
| 
 | |
| class LXC{
 | |
| 	constructor(args){
 | |
| 		// console.log('lxc args', args)
 | |
| 		this.name = args.name
 | |
| 		if(args.host){
 | |
| 			this.sysExec = (new SSH(args)).sysExec.bind(args)
 | |
| 		}else{
 | |
| 			this.sysExec = (new Local()).sysExec
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	static async list(){
 | |
| 		try{
 | |
| 			let res = await this.prototype.sysExec(`lxc-ls --fancy`);
 | |
| 			let output = res.stdout.split("\n").slice(0).slice(0,-1);
 | |
| 			let keys = output.splice(0,1)[0].split(/\s+/).slice(0,-1).map(function(v){return v.toLowerCase()});
 | |
| 			let info = [];
 | |
| 
 | |
| 			for(let line of output){
 | |
| 				if(line.match(/^-/)) continue;
 | |
| 
 | |
| 				line = line.split(/\s+/).slice(0,-1);
 | |
| 
 | |
| 				let mapOut = {};
 | |
| 				line.map(function(value,idx){
 | |
| 					mapOut[keys[idx]] = value;
 | |
| 				});
 | |
| 				info.push(mapOut);
 | |
| 			}
 | |
| 
 | |
| 			return info;
 | |
| 
 | |
| 		}catch(error){
 | |
| 			throw error;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	async create(from){
 | |
| 		try{
 | |
| 			return await this.sysExec(`lxc-copy --name "${from}" --newname "${this.name}" --daemon`);
 | |
| 		}catch(error){
 | |
| 			throw error;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	async start(){
 | |
| 		try{	
 | |
| 			return await this.sysExec(`lxc-start --name "${this.name}" --daemon`);
 | |
| 		}catch(error){
 | |
| 			throw error;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	async destroy(){
 | |
| 		try{
 | |
| 			let res = await this.sysExec(`lxc-destroy --force --name ${this.name}`)
 | |
| 
 | |
| 			return !!res.stdout.match(/Destroyed container/);
 | |
| 		}catch(error){
 | |
| 			throw error;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	async stop(){
 | |
| 		try{			
 | |
| 			return await this.sysExec(`lxc-stop --name "${this.name}"`);
 | |
| 		}catch(error){
 | |
| 			throw error;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	async exec(code){
 | |
| 		try{
 | |
| 			code = new Buffer.from(code).toString('base64')
 | |
| 			return await this.sysExec(`lxc-attach -n "${this.name}" --clear-env -- bash -c 'echo "${code}" | base64 --decode | bash'`)
 | |
| 		}catch(error){
 | |
| 			throw error;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	async info(){
 | |
| 		try{
 | |
| 			let info = {};
 | |
| 			
 | |
| 			let res = await this.sysExec(`lxc-info --name "${this.name}"`);
 | |
| 			res = res.stdout;
 | |
| 
 | |
| 			if(res.match("doesn't exist")){
 | |
| 				throw new Error('ContainerDoesntExist')
 | |
| 			}
 | |
| 
 | |
| 			res = res.replace(/\suse/ig, '').replace(/\sbytes/ig, '').split("\n").slice(0,-1);
 | |
| 			for(var i in res){
 | |
| 				var temp = res[i].split(/\:\s+/);
 | |
| 				info[temp[0].toLowerCase().trim()] = temp[1].trim();
 | |
| 			}
 | |
| 			var args = [info].concat(Array.prototype.slice.call(arguments, 1));
 | |
| 			
 | |
| 			return info;
 | |
| 		}catch(error){
 | |
| 			throw error;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	async setAutoStart(name){
 | |
| 		await this.sysExec(`echo "lxc.start.auto = 1" >>  "$HOME/.local/share/lxc/${this.name}/config"`)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| module.exports = {Local, SSH, LXC};
 | |
| 
 | |
| (async function(){try{
 | |
| 
 | |
| // 	let lxc = new LXC();
 | |
| 
 | |
| // 	// console.log(await lxc.copy('hass', 'hass2'))
 | |
| 
 | |
| 	// console.log(await lxc.destroy('hass2'))
 | |
| 	// console.log(await LXC.list())
 | |
| 
 | |
| 	// let lxc = new LXC({name:'hass'})
 | |
| 	// console.log(await hass.start())
 | |
| 
 | |
| 
 | |
| 
 | |
| 	// let lxc = new LXC({user:'virt-service', host:'142.93.30.52', keyPath:'/home/william/.ssh/id_rsa_virt-service', name: 'test2'})
 | |
| 	// console.log(await lxc.exec('hostname'))
 | |
| // 	// console.log(await lxc.exec('test2', 'sleep 50'))
 | |
| 	// console.log(await lxc.info())
 | |
| // 
 | |
| 
 | |
| 
 | |
| }catch(error){
 | |
| 	console.error('IIFE error', error);
 | |
| }})()
 |