v2.1: HLDP新增@串联/@广播,引擎集群互相通话,一条指令全网执行
This commit is contained in:
parent
614a8c789e
commit
1218d21112
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
/* ═══════════════════════════════════════
|
/* ═══════════════════════════════════════
|
||||||
光湖驱动引擎 v2.0 · Guanghu Drive Engine
|
光湖驱动引擎 v2.1 · Guanghu Drive Engine
|
||||||
HLDP万能语言接口 — HLDP进,指令出
|
HLDP万能语言接口 + 集群串联 — 一条指令,全网执行
|
||||||
═══════════════════════════════════════ */
|
═══════════════════════════════════════ */
|
||||||
|
|
||||||
const http=require('http'),fs=require('fs'),path=require('path'),crypto=require('crypto'),{exec}=require('child_process'),os=require('os');
|
const http=require('http'),fs=require('fs'),path=require('path'),crypto=require('crypto'),{exec}=require('child_process'),os=require('os');
|
||||||
@ -82,53 +82,112 @@ function fmtBytes(b){if(b===0)return'0 B';const k=1024,sizes=['B','KB','MB','GB'
|
|||||||
|
|
||||||
|
|
||||||
/* ═══════════════════════════════════════
|
/* ═══════════════════════════════════════
|
||||||
HLDP 翻译层 v1.0 — 光湖驱动引擎 v2.0
|
HLDP 翻译层 v2.0 — 光湖驱动引擎 v2.1
|
||||||
|
新增 @串联 @广播 — 引擎之间互相通话
|
||||||
═══════════════════════════════════════ */
|
═══════════════════════════════════════ */
|
||||||
|
|
||||||
|
const NODES={
|
||||||
|
'BS-GZ-006':{url:'http://43.139.217.141:3910',key:'zy_gtw_4a155446b7acc09fe46a2a29972c0ca5d9954da19c35dc23'},
|
||||||
|
'BS-SG-001':{url:'http://43.156.237.110:3911',key:'zy_gtw_c38be341d65043eee0ba51a214a267832a9ae46dd73e423c'},
|
||||||
|
'BS-SG-002':{url:'http://43.134.16.246:3910',key:'zy_gtw_ceb06d8a70d0cd38678239b3a1a9b2ba5cba77a3fbe5ebbf'},
|
||||||
|
'BS-SG-003':{url:'http://43.153.193.169:3910',key:'zy_gtw_d7c033d8ae992ffc9dd3e0dd5fe332dace0b644c0ae7c847'},
|
||||||
|
'ZY-SG-006':{url:'http://43.153.203.105:3910',key:'zy_gtw_fff861a2fe40cbdc366ee21f218023be8b1c182f66c852d3'},
|
||||||
|
'BS-SH-005':{url:'http://124.223.10.33:3910',key:'zy_gtw_b1045de5ddfd7832e3c53349d9c896f054b85a4a9ece22f9'},
|
||||||
|
};
|
||||||
|
|
||||||
|
function parseOpLine(t){
|
||||||
|
if(t.startsWith('@执行:')){
|
||||||
|
const cmd=t.replace('@执行:','').trim();
|
||||||
|
const parts=cmd.split(/\s+/);
|
||||||
|
if(parts[0]==='shell')return{type:'shell',cmd:parts.slice(1).join(' ')};
|
||||||
|
if(parts[0]==='python')return{type:'python',cmd:parts.slice(1).join(' ')};
|
||||||
|
return{type:'shell',cmd:cmd};
|
||||||
|
}
|
||||||
|
if(t.startsWith('@部署:')){
|
||||||
|
const action=t.replace('@部署:','').trim();
|
||||||
|
const parts=action.split(/\s+/);
|
||||||
|
if(parts[0]==='写入')return{type:'write',path:parts[1]};
|
||||||
|
if(parts[0]==='命令')return{type:'shell',cmd:parts.slice(1).join(' ')};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
function parseHLDP(text){
|
function parseHLDP(text){
|
||||||
const lines=text.split('\n').filter(l=>l.trim());
|
const lines=text.split('\n');
|
||||||
const ops=[];
|
const groups=[];
|
||||||
|
let relay=null;
|
||||||
for(const line of lines){
|
for(const line of lines){
|
||||||
const t=line.trim();
|
const t=line.trim();
|
||||||
if(t.startsWith('@执行:')){
|
if(!t)continue;
|
||||||
const cmd=t.replace('@执行:','').trim();
|
if(t.startsWith('@串联:')){relay=t.replace('@串联:','').trim();continue;}
|
||||||
const parts=cmd.split(/\s+/);
|
if(t==='@广播'){relay='BROADCAST';continue;}
|
||||||
if(parts[0]==='shell'){ops.push({type:'shell',cmd:parts.slice(1).join(' ')});}
|
const op=parseOpLine(t);
|
||||||
else if(parts[0]==='python'){ops.push({type:'python',cmd:parts.slice(1).join(' ')});}
|
if(!op)continue;
|
||||||
else{ops.push({type:'shell',cmd:cmd});}
|
if(!groups.length||groups[groups.length-1].relay!==relay){
|
||||||
}else if(t.startsWith('@部署:')){
|
groups.push({relay:relay,ops:[]});
|
||||||
const action=t.replace('@部署:','').trim();
|
|
||||||
const parts=action.split(/\s+/);
|
|
||||||
if(parts[0]==='写入'){
|
|
||||||
const filepath=parts[1];
|
|
||||||
ops.push({type:'write',path:filepath});
|
|
||||||
}else if(parts[0]==='命令'){
|
|
||||||
ops.push({type:'shell',cmd:parts.slice(1).join(' ')});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
groups[groups.length-1].ops.push(op);
|
||||||
}
|
}
|
||||||
return ops;
|
return groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function relayHLDP(target,hldpText){
|
||||||
|
const node=NODES[target];
|
||||||
|
if(!node)return{target:target,ok:false,error:'未知节点: '+target};
|
||||||
|
return new Promise(r=>{
|
||||||
|
const body=JSON.stringify({hlpd:hldpText});
|
||||||
|
const opts={hostname:node.url.replace(/https?:\/\//,'').split(':')[0],
|
||||||
|
port:parseInt(node.url.split(':').pop()||'3910',10),
|
||||||
|
path:'/hlpd',method:'POST',
|
||||||
|
headers:{'Content-Type':'application/json','Authorization':'Bearer '+node.key,'Content-Length':Buffer.byteLength(body)}};
|
||||||
|
const req=http.request(opts,res=>{let d='';res.on('data',c=>d+=c);res.on('end',()=>{try{r({target:target,ok:true,result:JSON.parse(d)})}catch(e){r({target:target,ok:false,error:d.slice(0,200)})}})});
|
||||||
|
req.on('error',e=>r({target:target,ok:false,error:e.message}));
|
||||||
|
req.write(body);req.end();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function hldpTextFromOps(ops){
|
||||||
|
return ops.map(o=>{
|
||||||
|
if(o.type==='shell')return '@执行: shell '+o.cmd;
|
||||||
|
if(o.type==='python')return '@执行: python '+o.cmd;
|
||||||
|
if(o.type==='write')return '@部署: 写入 '+o.path;
|
||||||
|
return '';
|
||||||
|
}).filter(l=>l).join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
async function runHLDP(hlpdText){
|
async function runHLDP(hlpdText){
|
||||||
const ops=parseHLDP(hlpdText);
|
const groups=parseHLDP(hlpdText);
|
||||||
const results=[];
|
const allResults=[];
|
||||||
for(const op of ops){
|
for(const g of groups){
|
||||||
if(op.type==='shell'){
|
if(!g.relay){
|
||||||
const r=await execCmd(op.cmd);
|
for(const op of g.ops){
|
||||||
results.push({type:'shell',cmd:op.cmd,...r});
|
if(op.type==='shell'){
|
||||||
}else if(op.type==='write'){
|
const r=await execCmd(op.cmd);
|
||||||
try{
|
allResults.push({type:'shell',cmd:op.cmd,...r});
|
||||||
const dir=path.dirname(op.path);
|
}else if(op.type==='write'){
|
||||||
if(!fs.existsSync(dir))fs.mkdirSync(dir,{recursive:true});
|
try{
|
||||||
results.push({type:'write',path:op.path,ok:true});
|
const dir=path.dirname(op.path);
|
||||||
}catch(e){results.push({type:'write',path:op.path,ok:false,error:e.message});}
|
if(!fs.existsSync(dir))fs.mkdirSync(dir,{recursive:true});
|
||||||
}else if(op.type==='python'){
|
allResults.push({type:'write',path:op.path,ok:true});
|
||||||
const r=await execCmd('python3 -c "'+op.cmd.replace(/"/g,'\\"')+'"');
|
}catch(e){allResults.push({type:'write',path:op.path,ok:false,error:e.message});}
|
||||||
results.push({type:'python',cmd:op.cmd,...r});
|
}else if(op.type==='python'){
|
||||||
|
const r=await execCmd('python3 -c "'+op.cmd.replace(/"/g,'\\"')+'"');
|
||||||
|
allResults.push({type:'python',cmd:op.cmd,...r});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else if(g.relay==='BROADCAST'){
|
||||||
|
const hldp=hldpTextFromOps(g.ops);
|
||||||
|
const targets=Object.keys(NODES);
|
||||||
|
const promises=targets.map(t=>relayHLDP(t,hldp));
|
||||||
|
const results=await Promise.all(promises);
|
||||||
|
allResults.push({type:'broadcast',targets:targets.length,results:results});
|
||||||
|
}else{
|
||||||
|
const hldp=hldpTextFromOps(g.ops);
|
||||||
|
const r=await relayHLDP(g.relay,hldp);
|
||||||
|
allResults.push({type:'relay',target:g.relay,...r});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return{parsed:ops.length,results:results};
|
return{groups:groups.length,results:allResults};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -158,11 +217,11 @@ const server=http.createServer(async(req,res)=>{
|
|||||||
log('INFO','exec_result','exit='+r.code);
|
log('INFO','exec_result','exit='+r.code);
|
||||||
jr(res,200,{ok:r.code===0,stdout:r.stdout,stderr:r.stderr,exitCode:r.code});
|
jr(res,200,{ok:r.code===0,stdout:r.stdout,stderr:r.stderr,exitCode:r.code});
|
||||||
}else if(route==='/health'){
|
}else if(route==='/health'){
|
||||||
jr(res,200,{ok:true,service:'guanghu-engine',version:'2.0.0',uptime:process.uptime().toFixed(0)+'s',timestamp:new Date().toISOString()});
|
jr(res,200,{ok:true,service:'guanghu-engine',version:'2.1.0',uptime:process.uptime().toFixed(0)+'s',timestamp:new Date().toISOString()});
|
||||||
}else if(route==='/status'){
|
}else if(route==='/status'){
|
||||||
log('INFO','status','');
|
log('INFO','status','');
|
||||||
const total=os.totalmem(),free=os.freemem();
|
const total=os.totalmem(),free=os.freemem();
|
||||||
jr(res,200,{ok:true,hostname:os.hostname(),platform:os.platform(),arch:os.arch(),cpus:os.cpus().length,uptime:os.uptime(),uptime_str:fmtUptime(os.uptime()),memory:{total:fmtBytes(total),free:fmtBytes(free),used:fmtBytes(total-free),usage:((total-free)/total*100).toFixed(1)+'%'},load:os.loadavg().map(n=>+n.toFixed(2)),engine:{version:'2.0.0',port:PORT,uptime:process.uptime().toFixed(0)+'s'}});
|
jr(res,200,{ok:true,hostname:os.hostname(),platform:os.platform(),arch:os.arch(),cpus:os.cpus().length,uptime:os.uptime(),uptime_str:fmtUptime(os.uptime()),memory:{total:fmtBytes(total),free:fmtBytes(free),used:fmtBytes(total-free),usage:((total-free)/total*100).toFixed(1)+'%'},load:os.loadavg().map(n=>+n.toFixed(2)),engine:{version:'2.1.0',port:PORT,uptime:process.uptime().toFixed(0)+'s'}});
|
||||||
}else if(route==='/hlpd'){
|
}else if(route==='/hlpd'){
|
||||||
const b=await parseBody(req);
|
const b=await parseBody(req);
|
||||||
if(!b||!b.hlpd){jr(res,400,{error:'缺少 hlpd 参数'});return;}
|
if(!b||!b.hlpd){jr(res,400,{error:'缺少 hlpd 参数'});return;}
|
||||||
@ -221,8 +280,8 @@ server.on('error',(e)=>{
|
|||||||
|
|
||||||
server.listen(PORT,'0.0.0.0',()=>{
|
server.listen(PORT,'0.0.0.0',()=>{
|
||||||
const h=os.hostname();
|
const h=os.hostname();
|
||||||
log('INFO','startup','host='+h+' port='+PORT+' v2.0');
|
log('INFO','startup','host='+h+' port='+PORT+' v2.1');
|
||||||
console.log(' ⚔️ 光湖驱动引擎 v2.0 · HLDP 已就绪');
|
console.log(' ⚔️ 光湖驱动引擎 v2.1 · HLDP + 集群串联');
|
||||||
console.log(' 主机名: '+h+' 端口: '+PORT);
|
console.log(' 主机名: '+h+' 端口: '+PORT);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user