lrf402788946 4 роки тому
батько
коміт
bc37e4d32d

+ 38 - 0
app/controller/.qnodes.js

@@ -0,0 +1,38 @@
+module.exports = {
+  create: {
+    requestBody: [],
+  },
+  destroy: {
+    params: ["!id"],
+    service: "delete",
+  },
+  update: {
+    params: ["!id"],
+    requestBody: [],
+  },
+  show: {
+    parameters: {
+      params: ["!id"],
+    },
+    service: "fetch",
+  },
+  index: {
+    parameters: {
+      query: {
+        time: "time",
+        "create_time@start": "create_time@start",
+        "create_time@end": "create_time@end",
+      },
+      // options: {
+      //   "meta.state": 0 // 默认条件
+      // },
+    },
+    service: "query",
+    options: {
+      query: ["skip", "limit"],
+      sort: ["meta.createdAt"],
+      desc: true,
+      count: true,
+    },
+  },
+};

+ 13 - 0
app/controller/qnodes.js

@@ -0,0 +1,13 @@
+'use strict';
+const meta = require('./.qnodes.js');
+const Controller = require('egg').Controller;
+const { CrudController } = require('naf-framework-mongoose/lib/controller');
+
+// 服务器集群节点
+class QnodesController extends Controller {
+  constructor(ctx) {
+    super(ctx);
+    this.service = this.ctx.service.qnodes;
+  }
+}
+module.exports = CrudController(QnodesController, meta);

+ 7 - 1
app/controller/top.js

@@ -14,10 +14,16 @@ class TopController extends Controller {
   }
 
   async initServeNode() {
-    await this.ctx.service.creeperxtsqnode.creeper();
+    // await this.ctx.service.creeperxtsqnode.creeper();
+    // await this.ctx.service.creeperxtsqnode.sshcon();
+    // 需要真的查库里数据
     this.ctx.ok();
   }
 
+  async util() {
+    // await this.ctx.service.creeperxtsread.qnodes();
+    this.ctx.ok();
+  }
 }
 
 module.exports = CrudController(TopController, meta);

+ 51 - 0
app/model/qnodes.js

@@ -0,0 +1,51 @@
+'use strict';
+const Schema = require('mongoose').Schema;
+const moment = require('moment');
+const metaPlugin = require('naf-framework-mongoose/lib/model/meta-plugin');
+const { ObjectId } = require('mongoose').Types;
+// 集群节点表
+const qnodes = {
+  node: { type: String },
+  state: { type: String },
+  power_state: { type: String },
+  np: { type: String },
+  ntype: { type: String },
+  jobs: { type: String },
+  status: { type: String },
+  macaddr: { type: String },
+  cpuclock: { type: String },
+  varattr: { type: String },
+  energy_used: { type: String },
+  mem: { type: String },
+  vmem: { type: String },
+  walltime: { type: String },
+  session_id: { type: String },
+  size: { type: String },
+  netload: { type: String },
+  gres: { type: String },
+  loadave: { type: String },
+  ncpus: { type: String },
+  physmem: { type: String },
+  availmem: { type: String },
+  totmem: { type: String },
+  idletime: { type: String },
+  nusers: { type: String },
+  nsessions: { type: String },
+  sessions: { type: String },
+  uname: { type: String },
+  opsys: { type: String },
+  mom_service_port: { type: String },
+  mom_manager_port: { type: String },
+  time: { type: String },
+  remark: { type: String, maxLength: 200 },
+  create_time: { type: String, default: moment(new Date()).format('YYYY-MM-DD HH:mm:ss') },
+};
+const schema = new Schema(qnodes, { toJSON: { virtuals: true } });
+schema.index({ id: 1 });
+schema.index({ time: 1 });
+schema.index({ 'meta.createdAt': 1 });
+schema.plugin(metaPlugin);
+module.exports = app => {
+  const { mongoose } = app;
+  return mongoose.model('Qnodes', schema, 'qnodes');
+};

+ 3 - 1
app/router.js

@@ -72,5 +72,7 @@ module.exports = app => {
   router.resources('top', '/api/count/top', controller.top); // index、create、show、destroy
   router.post('top', '/api/count/top/update/:id', controller.top.update);
   // 集群节点初始查询
-  router.get('/api/count/servenode', controller.top.initServeNode);
+  router.get('/api/count/servenode', controller.qnodes.index);
+
+  router.get('/api/count/util', controller.top.util);
 };

+ 2 - 2
app/schedule/creeperxts.js

@@ -7,8 +7,8 @@ class Creeper extends Subscription {
   // 更改执行时间
   static get schedule() {
     return {
-      // cron: '0 0 23 * * ?', // 每天晚上23点执行任务
-      interval: '60s', // 1分钟执行一次
+      // cron: '0 30 18 * * ?', // 每天晚上23点执行任务
+      interval: '1m', // 1分钟执行一次
       type: 'worker', // 指定所有的 worker 都需要执行
     };
   }

+ 4 - 4
app/schedule/creeperxtsqnode.js

@@ -1,5 +1,5 @@
 'use strict';
-
+// 弃用,因为不能同时进行握手,所以将节点查询合并到用户查询中
 const Subscription = require('egg').Subscription;
 
 class Creeper extends Subscription {
@@ -8,7 +8,7 @@ class Creeper extends Subscription {
   static get schedule() {
     return {
       // cron: '0 6 30 * * ?', // 每天晚上23点执行任务
-      // // cron: '0 20 12 * * ?', // 每天晚上23点执行任务
+      // cron: '0 28 18 * * ?', // 每天晚上23点执行任务
       interval: '1m', // 1分钟执行一次
       type: 'worker', // 指定所有的 worker 都需要执行
     };
@@ -16,8 +16,8 @@ class Creeper extends Subscription {
 
   // subscribe 是真正定时任务执行时被运行的函数
   async subscribe() {
-    console.log('服务器集群节点查询');
-    await this.ctx.service.creeperxtsqnode.creeper();// qnodes
+    // console.log('服务器集群节点查询');
+    // await this.ctx.service.creeperxtsqnode.creeper();// qnodes
   }
 }
 module.exports = Creeper;

+ 6 - 5
app/schedule/creeperxtsread.js

@@ -1,3 +1,4 @@
+// 弃用.查询后直接redis读取
 'use strict';
 
 const Subscription = require('egg').Subscription;
@@ -7,17 +8,17 @@ class Creeper extends Subscription {
   // 更改执行时间
   static get schedule() {
     return {
-      cron: '0 2 11 * * ?', // 每天晚上23点执行任务
-      // // cron: '0 20 12 * * ?', // 每天晚上23点执行任务
-      // interval: '60s', // 1分钟执行一次
+      // cron: '0 2 11 * * ?', // 每天晚上23点执行任务
+      cron: '0 30 18 * * ?', // 每天晚上23点执行任务
+      // interval: '2m', // 1分钟执行一次
       type: 'worker', // 指定所有的 worker 都需要执行
     };
   }
 
   // subscribe 是真正定时任务执行时被运行的函数
   async subscribe() {
-    console.log('读取文件');
-    await this.ctx.service.creeperxtsread.creeper();// 读取文件
+    // console.log('读取文件');
+    // await this.ctx.service.creeperxtsread.creeper();// 读取文件
   }
 }
 module.exports = Creeper;

+ 31 - 34
app/service/creeperxts.js

@@ -1,7 +1,7 @@
 /* eslint-disable strict */
 const _ = require('lodash');
 // const fs = require('fs');
-const Client = require('ssh2').Client;
+const SSH2Shell = require('ssh2shell');
 const fs = require('fs');
 const moment = require('moment');
 const { CrudService } = require('naf-framework-mongoose/lib/service');
@@ -12,45 +12,42 @@ class CreeperxtsService extends CrudService {
     console.log('进入连接linux服务器');
     // await this.sshcon();
     await this.sshcon();
+    console.log('用户监控结束');
   }
-
   async sshcon() {
-    const nowdate = moment().locale('zh-cn').format('YYYY-MM-DD');
-    const conn = new Client();
+    const redis = this.app.redis;
+    const config = {
+      host: '192.168.10.102',
+      port: 42973,
+      userName: 'free_ly',
+      password: '1qaz2wsx',
+    };
     const pathDir = this.app.config.dataDir;
     if (!fs.existsSync(pathDir)) {
       fs.mkdirSync(pathDir);
     }
-    conn.on('ready', function() {
-      conn.exec('top -bcn 1', function(err, stream) {
-        if (err) throw err;
-        stream.on('close', function(code, signal) {
-          conn.end();
-        }).on('data', function(data) {
-          const path_ = `${pathDir}/top${nowdate}.txt`;
-          fs.access(path_, err => {
-            if (err) {
-              fs.writeFile(path_, data.toString(), function(err) {
-                if (err) throw err;
-              });
-            } else {
-              fs.appendFile(path_, data.toString(), function(err) {
-                if (err) throw err;
-              });
-            }
-          });
-        }).stderr.on('data', function(data) {
-          console.log('STDERR: ' + data);
-        });
-      });
-    }).connect({
-      host: '192.168.10.102',
-      port: 42973,
-      username: 'free_ly',
-      password: '1qaz2wsx',
-      // privateKey: require('fs').readFileSync('/home/admin/.ssh/id_dsa')
-    });
+    const host = {
+      server: config,
+      commands: [ 'top -bcn 1' ],
+      onCommandComplete: (command, response, sshObj) => {
+        console.log('command ok');
+      },
+      onEnd: async (sessionText, sshObj) => {
+        // console.log(`sessionText=>${sessionText}`);
+        // console.log(`sshObj=>${JSON.stringify(sshObj)}`);
+        const text = JSON.stringify(sshObj.sessionText);
+        const res = await redis.set('top', text);
+        if (res === 'OK') await this.ctx.service.creeperxtsread.top();
+        await this.ctx.service.creeperxtsqnode.creeper();
+      },
+    };
+    try {
+      const SSH = new SSH2Shell(host);
+      SSH.connect();
+    } catch (error) {
+      console.log(error);
+      console.log('用户监控失败');
+    }
   }
-
 }
 module.exports = CreeperxtsService;

+ 15 - 17
app/service/creeperxtsqnode.js

@@ -11,9 +11,11 @@ class CreeperxtsService extends CrudService {
     console.log('进入连接linux服务器');
     // await this.sshcon();
     await this.sshcon();
+    console.log('集群节点结束');
   }
 
   async sshcon() {
+    const redis = this.app.redis;
     const config = {
       host: '192.168.10.102',
       port: 42973,
@@ -33,28 +35,24 @@ class CreeperxtsService extends CrudService {
         // console.log(`response=>${response}`);
         // console.log(`sshObj=>${sshObj}`);
         // console.groupEnd();
+        console.log('command ok');
       },
-      onEnd: (sessionText, sshObj) => {
+      onEnd: async (sessionText, sshObj) => {
         // console.log(`sessionText=>${sessionText}`);
         // console.log(`sshObj=>${JSON.stringify(sshObj)}`);
-        const path_ = `${pathDir}/qnodes.txt`;
-        const writeRes = fs.writeFileSync(path_, sessionText);
-        this.ctx.service.creeperxtsread.qnodes();
-        // fs.access(path_, err => {
-        //   if (err) {
-        //     fs.writeFile(path_, sessionText, function(err) {
-        //       if (err) throw err;
-        //     });
-        //   } else {
-        //     fs.appendFile(path_, sessionText, function(err) {
-        //       if (err) throw err;
-        //     });
-        //   }
-        // });
+        const text = JSON.stringify(sshObj.sessionText);
+        const res = await redis.set('qnodes', text);
+        if (res === 'OK') await this.ctx.service.creeperxtsread.qnodes();
       },
     };
-    const SSH = new SSH2Shell(host);
-    SSH.connect();
+    try {
+      const SSH = new SSH2Shell(host);
+      SSH.connect();
+    } catch (error) {
+      console.log(error);
+      console.log('集群节点获取失败');
+    }
+
   }
 
 }

+ 28 - 42
app/service/creeperxtsread.js

@@ -1,10 +1,7 @@
 /* eslint-disable strict */
 const _ = require('lodash');
-const path = require('path');
 const moment = require('moment');
-const QueryLinesReader = require('query-lines-reader');
 const { CrudService } = require('naf-framework-mongoose/lib/service');
-const fs = require('fs');
 class CreeperxtsreadService extends CrudService {
 
   async creeper() {
@@ -13,42 +10,41 @@ class CreeperxtsreadService extends CrudService {
     // await this.sshcon();
     await this.top();
     await this.qnodes();
+    console.log('读取取回的文本文件结束');
   }
 
   async top() {
-    const nowdate = moment().locale('zh-cn').format('YYYY-MM-DD');
-    const pathDir = this.app.config.dataDir;
-    const pathread = `${pathDir}/top${nowdate}.txt`;
-    const res = await this.readFileToArr(pathread);
-    if (res) {
-      for (const rl of res.lineList) {
-        const strsplit = rl.split(' ');
-        const strs = _.pull(strsplit, '');
-        const newdata = {};
-        newdata.pid = strs[0];
-        newdata.user = strs[1];
-        newdata.pr = strs[2];
-        newdata.ni = strs[3];
-        newdata.virt = strs[4];
-        newdata.res = strs[5];
-        newdata.shr = strs[6];
-        newdata.s = strs[7];
-        newdata.cpu = strs[8];
-        newdata.mem = strs[9];
-        newdata.time = strs[10];
-        newdata.command = strs[11];
-        if (newdata.pid && newdata.pid !== '0' && newdata.user && newdata.user !== '0') {
-          await this.ctx.model.Top.create(newdata);
-        }
+    const redis = this.app.redis;
+    const text = await redis.get('top');
+    const arr = text.split('\\r\\n');
+    for (const rl of arr) {
+      const strsplit = rl.split(' ');
+      const strs = _.pull(strsplit, '');
+      if (_.isNaN(parseInt(strs[0]))) continue;
+      const newdata = {};
+      newdata.pid = strs[0];
+      newdata.user = strs[1];
+      newdata.pr = strs[2];
+      newdata.ni = strs[3];
+      newdata.virt = strs[4];
+      newdata.res = strs[5];
+      newdata.shr = strs[6];
+      newdata.s = strs[7];
+      newdata.cpu = strs[8];
+      newdata.mem = strs[9];
+      newdata.time = strs[10];
+      newdata.command = strs[11];
+      if (newdata.pid && newdata.pid !== '0' && newdata.user && newdata.user !== '0') {
+        await this.ctx.model.Top.create(newdata);
       }
     }
   }
 
   async qnodes() {
-    const nowdate = moment().locale('zh-cn').format('YYYY-MM-DD HH:mm:ss');
-    const pathDir = this.app.config.dataDir;
-    const pathread = `${pathDir}/qnodes.txt`;
-    let { lineList } = await this.readFileToArr(pathread);
+    const nowdate = moment().format('YYYY-MM-DD');
+    const redis = this.app.redis;
+    const text = await redis.get('qnodes');
+    let lineList = text.split('\\r\\n');
     // res,去掉前两行和最后一行
     lineList = _.drop(lineList, 2);
     lineList = _.dropRight(lineList, 1);
@@ -78,20 +74,10 @@ class CreeperxtsreadService extends CrudService {
         }
       }
     }
-    console.log(`data length=>${arr.length}`);
+    await this.ctx.model.Qnodes.insertMany(arr);
     await this.toMq(arr);
-    // await fs.unlinkSync(`${pathread}`);
   }
 
-  async readFileToArr(path_) {
-    const options = { start: 0, end: 1, reverse: false };
-    const toGetTotal = new QueryLinesReader(path.resolve(__dirname, path_), options);
-    const total = (await toGetTotal.getTotal()) || 0;
-    options.end = total;
-    const queryLinesReader = new QueryLinesReader(path.resolve(__dirname, path_), options);
-    const lineObj = await queryLinesReader.queryLines();
-    return lineObj;
-  }
 
   async toMq(data) {
     if (this.ctx.mq) {

+ 15 - 0
app/service/qnodes.js

@@ -0,0 +1,15 @@
+'use strict';
+const { CrudService } = require('naf-framework-mongoose/lib/service');
+const { BusinessError, ErrorCode } = require('naf-core').Error;
+const _ = require('lodash');
+const assert = require('assert');
+
+// 服务器集群节点
+class QnodesService extends CrudService {
+  constructor(ctx) {
+    super(ctx, 'qnodes');
+    this.model = this.ctx.model.Qnodes;
+  }
+}
+
+module.exports = QnodesService;

+ 9 - 0
config/config.default.js

@@ -64,6 +64,15 @@ module.exports = appInfo => {
     issuer: 'count',
   };
 
+  config.redis = {
+    client: {
+      port: 6379, // Redis port
+      host: '127.0.0.1', // Redis host
+      password: '',
+      db: 2,
+    },
+  };
+
   return {
     ...config,
     ...userConfig,

+ 5 - 0
config/plugin.js

@@ -3,3 +3,8 @@ exports.amqp = {
   enable: true,
   package: 'egg-naf-amqp',
 };
+
+exports.redis = {
+  enable: true,
+  package: 'egg-redis',
+};

+ 1 - 3
package.json

@@ -9,14 +9,12 @@
   "dependencies": {
     "egg": "^2.15.1",
     "egg-naf-amqp": "0.0.13",
+    "egg-redis": "^2.4.0",
     "egg-scripts": "^2.11.0",
     "jsonwebtoken": "^8.5.1",
     "lodash": "^4.17.15",
     "moment": "^2.29.1",
     "naf-framework-mongoose": "^0.6.12",
-    "query-lines-reader": "^0.2.3",
-    "readline": "^1.3.0",
-    "ssh2": "^0.8.9",
     "ssh2shell": "^1.9.4"
   },
   "devDependencies": {