delete_restart.js 3.84 KB
/**
 * 分发部署
 * 
 * @class Restart
 * @author shenzm<zhimin.shen@yoho.cn>
 * @date 2016/10/12
 */

import ssh from 'ssh2';
import path from 'path';

import ws from '../../lib/ws';
import {
    RestartInfo,
    Server
} from '../models';

class DeleteRestart {

    constructor(project) {
        this.project = project;
    }

    async deleteRestart(info) {
        let server = await Server.findByHost(info.host);
        this.server = server;
        this.info = info;
        this.sshDeleteRestart({
            host: server.host,
            username: server.username,
            password: server.password,
            port: server.port
        });
    }

    sshDeleteRestart(serverInfo) {
        console.log('ssh connecting', serverInfo);
        let conn = new ssh.Client();
        let self = this;
        conn.on('ready', async() => {
            console.log(`connected ${serverInfo.host}`);
            try {
                await self._delete(conn);
                await self._restart(conn);
                conn.end();
            } catch (e) {
                self._state('fail');
                self._log(e);
            }
        }).on('error', (err) => {
            self._state('fail');
            self._log(err);
        }).connect(serverInfo);
    }

    _delete(conn) {
        let self = this;
        let script = `pm2 delete ${self.project.name}`;
        return new Promise((resolve, reject) => {
            self._state('deleteing');
            self._log(`>>>> ${script}`);
            conn.exec(`cd ${self.remoteRunningDir} && ${script}`, (err, stream) => {
                if (err) {
                    reject(err);
                } else {
                    stream.stdout.on('data', (data) => {
                        self._log(data.toString());
                    });
                    stream.stderr.on('data', (data) => {
                        self._log(data.toString());
                    });
                    stream.on('exit', (code) => {
                        if (code === 0) {
                            self._state('deleted');
                            resolve();
                        } else {
                            reject('delete fail: ' + script);
                        }
                    });
                }
            });
        });
    }

    _restart(conn) {
        let self = this;
        let startup = this.project.scripts.start;
        return new Promise((resolve, reject) => {
            self._state('restarting');
            self._log(`>>>> ${startup}`);
            conn.exec(`cd ${self.remoteRunningDir} && ${startup}`, (err, stream) => {
                if (err) {
                    reject(err);
                } else {
                    stream.stdout.on('data', (data) => {
                        self._log(data.toString());
                    });
                    stream.stderr.on('data', (data) => {
                        self._log(data.toString());
                    });
                    stream.on('exit', (code) => {
                        if (code === 0) {
                            self._state('running');
                            resolve();
                        } else {
                            reject('restart fail');
                        }
                    });
                }
            });
        });
    }

    async _state(state) {
        ws.broadcast(`/restart/${this.project._id}`, {
            host: this.info.host,
            state: state
        });
        await RestartInfo.updateState(this.info._id, state);
    }

    _log(msg) {
        console.log("log: ", msg);
        ws.broadcast(`/restart/${this.project._id}/log`, {
            host: this.info.host,
            msg: msg
        });
    }

    get remoteRunningDir() {
        return path.join(this.server.deployDir, this.project.name, 'current', this.project.name);
    }
}

export default DeleteRestart;