restart.js 3.39 KB
/**
 * 分发部署
 * 
 * @class Restart
 * @author shenzm<zhimin.shen@yoho.cn>
 * @date 2016/10/12
 */
'use strict';
const ssh = require('ssh2');
const path = require('path');
const fs = require('fs');

const ws = require('../../lib/ws');
const {
    RestartInfo,
    DeployInfo,
    Server
} = require('../models');

class Restart {

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

    async restart(info) {
        let server = await Server.findByHost(info.host);

        this.server = server;
        this.info = info;
        this.id = await DeployInfo.insertOrUpdate(this.info);

        if (this.project.type === 'php') {
            this.sshRestart({
                host: server.host,
                username: server.username,
                password: server.password,
                port: server.port
            });
        } else {
            this.sshRestart({
                host: server.host,
                username: server.username,
                password: server.password,
                port: server.port
            });
        }
    }

    sshRestart(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._restart(conn);
                conn.end();
            } catch (e) {
                self._state('fail');
                self._log(e);
            }
        }).on('error', (err) => {
            self._state('fail');
            self._log(err);
        }).connect(serverInfo);
    }

    _restart(conn) {
        let self = this;
        let startup;

        if (this.project.type === 'php') {
            startup = 'sudo /Data/local/apache-2.4.12/bin/apachectl restart';
        } else {
            startup =  `cd ${self.remoteRunningDir} && ${this.project.scripts.start}`;
        }
        return new Promise((resolve, reject) => {
            self._state('restarting');
            self._log(`>>>> ${startup}`);
            conn.exec(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);
        await DeployInfo.updateState(this.id, state);
    }

    _log(msg) {
        console.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);
    }
}

module.exports = Restart;