Exemple #1
0
    def walle_rollback(self):
        self.start()

        try:
            is_all_servers_success = True
            for server_info in self.servers:
                host = server_info['host']
                try:
                    waller = Waller(host=host, user=server_info['user'], port=server_info['port'], inline_ssh_env=True)
                    waller.init_env(env=self.custom_global_env)

                    self.connections[self.task_id] = waller
                    self.prev_release_custom(self.connections[self.task_id])
                    self.release(self.connections[self.task_id])
                    self.post_release(self.connections[self.task_id])
                    RecordModel().save_record(stage=RecordModel.stage_end, sequence=0, user_id=current_user.id,
                                              task_id=self.task_id, status=RecordModel.status_success, host=host,
                                              user=server_info['user'], command='')
                    emit('success', {'event': 'finish', 'data': {'host': host, 'message': host + ' 部署完成!'}}, room=self.task_id)
                except Exception as e:
                    is_all_servers_success = False
                    current_app.logger.exception(e)
                    self.errors[host] = e.message
                    RecordModel().save_record(stage=RecordModel.stage_end, sequence=0, user_id=current_user.id,
                                              task_id=self.task_id, status=RecordModel.status_fail, host=host,
                                              user=server_info['user'], command='')
                    emit('fail', {'event': 'finish', 'data': {'host': host, 'message': host + Code.code_msg[Code.deploy_fail]}}, room=self.task_id)
            self.end(is_all_servers_success)

        except Exception as e:
            self.end(False)

        return {'success': self.success, 'errors': self.errors}
Exemple #2
0
 def logs(self, task):
     emit('console', {
         'event': 'console',
         'data': {
             'task': task
         }
     },
          room=task)
     logs = RecordModel().fetch(task_id=task)
     for log in logs:
         log = RecordModel.logs(**log)
         emit('console', {'event': 'console', 'data': log}, room=self.room)
Exemple #3
0
    def __init__(self, task_id=None, project_id=None, console=False):
        self.local_codebase = current_app.config.get('CODE_BASE')
        self.localhost = Waller(host='127.0.0.1')
        self.TaskRecord = RecordModel()

        if task_id:
            self.task_id = task_id
            # task start
            current_app.logger.info(self.task_id)
            self.taskMdl = TaskModel().item(self.task_id)
            self.user_id = self.taskMdl.get('user_id')
            self.servers = self.taskMdl.get('servers_info')
            self.project_info = self.taskMdl.get('project_info')

        if project_id:
            self.project_id = project_id
            self.project_info = ProjectModel(id=project_id).item()
            self.servers = self.project_info['servers_info']

        self.project_name = self.project_info['id']
        self.dir_codebase_project = self.local_codebase + str(self.project_name)

        # self.init_repo()

        # start to deploy
        self.console = console
Exemple #4
0
    def log(self, wenv):
        '''

        @param wenv:

            @param stage:
            @param sequence:
            @param user_id:
            @param task_id:
            @param status:
            @param host:
            @param user:
            @param command:
            @param success:
            @param error:

        @return:
        '''
        RecordModel().save_record(stage=wenv['stage'],
                                  sequence=wenv['sequence'],
                                  user_id=wenv['user_id'],
                                  task_id=wenv['task_id'],
                                  status=exitcode,
                                  host='127.0.0.1',
                                  user=getpass.getuser(),
                                  command=result.command,
                                  success=stdout,
                                  error=stderr)
Exemple #5
0
    def __init__(self, task_id=None, project_id=None, console=False):
        self.local_codebase = current_app.config.get('CODE_BASE')
        self.local = Waller(
            host=current_app.config.get('LOCAL_SERVER_HOST'),
            user=current_app.config.get('LOCAL_SERVER_USER'),
            port=current_app.config.get('LOCAL_SERVER_PORT'),
        )
        self.TaskRecord = RecordModel()

        if task_id:
            self.task_id = task_id
            # task start
            current_app.logger.info(self.task_id)
            self.taskMdl = TaskModel().item(self.task_id)
            self.user_id = self.taskMdl.get('user_id')
            self.servers = self.taskMdl.get('servers_info')
            self.task = self.taskMdl.get('target_user')
            self.project_info = self.taskMdl.get('project_info')

        if project_id:
            self.project_id = project_id
            self.project_info = ProjectModel(id=project_id).item()

        self.project_name = self.project_info['id']
        self.dir_codebase_project = self.local_codebase + str(
            self.project_name)

        self.init_repo()

        # start to deploy
        self.console = console
Exemple #6
0
    def logs(self, task):
        task_info = TaskModel().get_by_id(self.task_id)
        if task_info.status not in [
                TaskModel.status_doing, TaskModel.status_success,
                TaskModel.status_fail
        ]:
            emit('console', {'event': 'console', 'data': ''}, room=self.room)
            return True

        deployer = Deployer(task_id=self.room)
        for log in deployer.logs():
            log = RecordModel.logs(**log)
            if log['stage'] == RecordModel.stage_end:
                cmd = 'success' if log[
                    'status'] == RecordModel.status_success else 'fail'
                msg = log['host'] + ' 部署完成!' if log[
                    'status'] == RecordModel.status_success else log[
                        'host'] + Code.code_msg[Code.deploy_fail]
                emit(cmd, {
                    'event': 'finish',
                    'data': {
                        'host': log['host'],
                        'message': msg
                    }
                },
                     room=self.room)
            else:
                emit('console', {
                    'event': 'console',
                    'data': log
                },
                     room=self.room)

        deployer.end(success=task_info.status == TaskModel.status_success,
                     update_status=False)
Exemple #7
0
    def logs(self, task):
        deployer = Deployer(task_id=self.room)
        for log in deployer.logs():
            log = RecordModel.logs(**log)
            emit('console', {'event': 'console', 'data': log}, room=self.room)

        task_info = TaskModel().get_by_id(self.task_id)
        deployer.end(success=task_info.status == TaskModel.status_success, update_status=False)
Exemple #8
0
    def __init__(self, task_id=None, project_id=None, console=False):
        self.local_codebase = current_app.config.get('CODE_BASE').rstrip('/') + '/'
        self.localhost = Waller(host='127.0.0.1')
        self.TaskRecord = RecordModel()

        if task_id:
            self.task_id = task_id
            # task start
            current_app.logger.info(self.task_id)
            self.taskMdl = TaskModel().item(self.task_id)
            self.user_id = self.taskMdl.get('user_id')
            self.servers = self.taskMdl.get('servers_info')
            self.project_info = self.taskMdl.get('project_info')

            # copy to a local version
            self.release_version = '{project_id}_{task_id}_{timestamp}'.format(
                project_id=self.project_info['id'],
                task_id=self.task_id,
                timestamp=time.strftime('%Y%m%d_%H%M%S', time.localtime(time.time())),
            )
            current_app.logger.info(self.taskMdl)

            self.custom_global_env = {
                'WEBROOT': str(self.project_info['target_root']),
                'VERSION': str(self.release_version),
                'CURRENT_RELEASE': str(self.project_info['target_releases']),
                'BRANCH': str(self.taskMdl.get('branch')),
                'TAG': str(self.taskMdl.get('tag')),
                'COMMIT_ID': str(self.taskMdl.get('commit_id')),
                'PROJECT_NAME': str(self.project_info['name']).replace('"', '').replace("'", '').replace(" ", '_'),
                'PROJECT_ID': str(self.project_info['id']),
                'TASK_NAME': str(self.taskMdl.get('name')).replace('"', '').replace("'", '').replace(" ", '_'),
                'TASK_ID': str(self.task_id),
                'DEPLOY_USER': str(self.taskMdl.get('user_name')),
                'DEPLOY_TIME': str(time.strftime('%Y%m%d-%H:%M:%S', time.localtime(time.time()))),
            }
            if self.project_info['task_vars']:
                task_vars = [i.strip() for i in self.project_info['task_vars'].split('\n') if i.strip() and not i.strip().startswith('#')]
                for var in task_vars:
                    var_list = var.split('=', 1)
                    if len(var_list) != 2:
                        continue
                    self.custom_global_env[var_list[0]] = var_list[1]

            self.localhost.init_env(env=self.custom_global_env)

        if project_id:
            self.project_id = project_id
            self.project_info = ProjectModel(id=project_id).item()
            self.servers = self.project_info['servers_info']

        self.project_name = self.project_info['id']
        self.dir_codebase_project = self.local_codebase + str(self.project_name)

        # self.init_repo()

        # start to deploy
        self.console = console
Exemple #9
0
    def sync(self, wtype, remote=None, local=None, wenv=None):
        command = 'scp %s %s@%s:%s' % (local, self.user, self.host, remote) if wtype == 'put' \
            else 'scp %s@%s:%s %s' % (self.user, self.host, remote, local)
        message = 'deploying task_id=%s [%s@%s]$ %s ' % (wenv['task_id'], self.user, self.host, command)
        current_app.logger.info(message)

        try:
            if wtype == 'put':
                result = super(Waller, self).put(local=local, remote=remote)
                current_app.logger.info('put: local %s, remote %s', local, remote)
                op_user = current_app.config.get('LOCAL_SERVER_USER')
                op_host = current_app.config.get('LOCAL_SERVER_HOST')

            else:
                result = super(Waller, self).get(remote=remote, local=local)
                current_app.logger.info('get: local %s, remote %s', local, remote)
                current_app.logger.info('get: orig_local %s, local %s', result.orig_local, result.local)
                op_user = self.user
                op_host = self.host

            current_app.logger.info('put: %s, %s', result, dir(result))
            # TODO 可能会有非22端口的问题
            RecordModel().save_record(stage=wenv['stage'], sequence=wenv['sequence'], user_id=wenv['user_id'],
                                      task_id=wenv['task_id'], status=0, host=self.host, user=self.user,
                                      command=command, )

            # TODO
            ws_dict = {
                'user': op_user,
                'host': op_host,
                'cmd': command,
                'status': 1,
                'stage': wenv['stage'],
                'sequence': wenv['sequence'],
                'success': '',
                'error': '',
            }
            if wenv['console']:
                emit('console', {'event': 'task:console', 'data': ws_dict}, room=wenv['task_id'])

            return result
        except Exception as e:
            # TODO 收尾下
            current_app.logger.info('put: %s, %s', e, dir(e))

            # TODO command
            ws_dict = {
                'user': self.user,
                'host': self.host,
                'cmd': command,
                'status': 1,
                'stage': wenv['stage'],
                'sequence': wenv['sequence'],
                'success': '',
                'error': e.message,
            }
            if wenv['console']:
                emit('console', {'event': 'task:console', 'data': ws_dict}, room=wenv['task_id'])
Exemple #10
0
 def websocket(self, task_id=None):
     task_id = 12
     wi = Deployer(task_id)
     ret = wi.walle_deploy()
     record = RecordModel().fetch(task_id)
     return self.render_json(data={
         'command': ret,
         'record': record,
     })
Exemple #11
0
    def sync(self, wtype, remote=None, local=None, wenv=None):
        try:
            if wtype == 'put':
                result = super(Waller, self).put(local=local, remote=remote)
                command = 'put: scp %s %s@%s:%s' % (result.local, self.user, self.host, result.remote)
                current_app.logger.info('put: local %s, remote %s', local, remote)

            else:
                result = super(Waller, self).get(remote=remote, local=local)
                command = 'get: scp %s@%s:%s %s' % (self.user, self.host, result.remote, result.local)
                current_app.logger.info('get: local %s, remote %s', local, remote)
                current_app.logger.info('get: orig_local %s, local %s', result.orig_local, result.local)

            current_app.logger.info('put: %s, %s', result, dir(result))
            # TODO 可能会有非22端口的问题
            RecordModel().save_record(stage=wenv['stage'], sequence=wenv['sequence'], user_id=wenv['user_id'],
                                          task_id=wenv['task_id'], status=0, host=self.host, user=self.user,
                                          command=command, )
            message = 'task_id=%d, host:%s command:%s status:0, success:, error:' % (
            wenv['task_id'], self.host, command)
            current_app.logger.info(message)

            # TODO
            ws_dict = {
                'host': self.host,
                'cmd': command,
                'status': 1,
                'stage': wenv['stage'],
                'sequence': wenv['sequence'],
                'success': '',
                'error': result.stderr.strip(),
            }
            if wenv['console']:
                emit('console', {'event': 'task:console', 'data': ws_dict}, room=wenv['task_id'])

            return result
        except Exception as e:
            # TODO 收尾下
            current_app.logger.info('put: %s, %s', e, dir(e))

            # TODO command
            ws_dict = {
                'host': self.host,
                'cmd': 'command',
                'status': 1,
                'stage': wenv['stage'],
                'sequence': wenv['sequence'],
                'success': '',
                'error': e.message,
            }
            if wenv['console']:
                emit('console', {'event': 'task:console', 'data': ws_dict}, room=wenv['task_id'])
Exemple #12
0
    def logs(self, task):
        task_info = TaskModel().get_by_id(self.task_id)
        if task_info.status not in [
                TaskModel.status_doing, TaskModel.status_success,
                TaskModel.status_fail
        ]:
            emit('console', {'event': 'console', 'data': ''}, room=self.room)
            return True

        deployer = Deployer(task_id=self.room)
        for log in deployer.logs():
            log = RecordModel.logs(**log)
            emit('console', {'event': 'console', 'data': log}, room=self.room)

        deployer.end(success=task_info.status == TaskModel.status_success,
                     update_status=False)
Exemple #13
0
    def __init__(self, task_id=None, project_id=None, console=False):
        self.local = Waller(host=current_app.config.get('LOCAL_SERVER_HOST'),
                            user=current_app.config.get('LOCAL_SERVER_USER'),
                            port=current_app.config.get('LOCAL_SERVER_PORT'))
        self.TaskRecord = RecordModel()

        if task_id:
            self.task_id = task_id
            self.taskMdl = TaskModel().item(self.task_id)
            self.user_id = self.taskMdl.get('user_id')
            self.servers = self.taskMdl.get('servers_info')
            self.task = self.taskMdl.get('target_user')
            self.project_info = self.taskMdl.get('project_info')
        if project_id:
            self.project_id = project_id
            self.project_info = ProjectModel(id=project_id).item()
Exemple #14
0
    def logs(self, task):
        task_info = TaskModel().get_by_id(self.task_id)
        if task_info.status not in [TaskModel.status_doing, TaskModel.status_success, TaskModel.status_fail]:
            emit('console', {'event': 'console', 'data': ''}, room=self.room)
            return True

        deployer = Deployer(task_id=self.room)
        for log in deployer.logs():
            log = RecordModel.logs(**log)
            if log['stage'] == RecordModel.stage_end:
                cmd = 'success' if log['status'] == RecordModel.status_success else 'fail'
                msg = log['host'] + ' 部署完成!' if log['status'] == RecordModel.status_success else log['host'] + Code.code_msg[Code.deploy_fail]
                emit(cmd, {'event': 'finish', 'data': {'host': log['host'], 'message': msg}}, room=self.room)
            else:
                emit('console', {'event': 'console', 'data': log}, room=self.room)

        deployer.end(success=task_info.status == TaskModel.status_success, update_status=False)
Exemple #15
0
    def post(self):
        """
        fetch role list or one role

        :return:
        """
        super(DeployAPI, self).post()

        task_id = request.form['task_id']
        if not task_id or not task_id.isdigit():
            return self.render_json(code=-1)
        wi = Deployer(task_id)
        ret = wi.walle_deploy()
        record = RecordModel().fetch(task_id)
        return self.render_json(data={
            'command': '',
            'record': record,
        })
Exemple #16
0
    def __init__(self, task_id=None, project_id=None, console=False):
        self.local = Waller(host=current_app.config.get('LOCAL_SERVER_HOST'),
                            user=current_app.config.get('LOCAL_SERVER_USER'),
                            port=current_app.config.get('LOCAL_SERVER_PORT'))
        self.TaskRecord = RecordModel()

        if task_id:
            self.task_id = task_id
            # task start
            TaskModel(id=self.task_id).update(status=TaskModel.status_doing)

            self.taskMdl = TaskModel().item(self.task_id)
            self.user_id = self.taskMdl.get('user_id')
            self.servers = self.taskMdl.get('servers_info')
            self.task = self.taskMdl.get('target_user')
            self.project_info = self.taskMdl.get('project_info')

        if project_id:
            self.project_id = project_id
            self.project_info = ProjectModel(id=project_id).item()

        self.project_name = self.project_info['id']
        self.dir_codebase_project = self.dir_codebase + str(self.project_name)
Exemple #17
0
    def run(self,
            command,
            wenv=None,
            sudo=False,
            pty=True,
            exception=True,
            **kwargs):
        '''
        pty=True/False是直接影响到输出.False较适合在获取文本,True更适合websocket

        :param command:
        :param wenv:
        :param sudo:      False/True default False
        :param exception: False/True default True
                          False return Result(exited=xx, stderr=xx, stdout=xx) for process to raise custom exception by exited code
                          True raise Exception
        :param kwargs:
        :return:
        '''
        message = 'deploying task_id=%s [%s@%s]$ %s ' % (
            wenv['task_id'], self.user, self.host, command)
        current_app.logger.info(message)
        try:
            if sudo:
                result = super(Waller, self).sudo(command, pty=pty, **kwargs)
            else:
                result = super(Waller, self).run(command,
                                                 pty=pty,
                                                 warn=True,
                                                 watchers=[say_yes()],
                                                 **kwargs)

            if result.failed:
                exitcode, stdout, stderr = result.exited, '', result.stdout
                if exception:
                    raise Exception(stderr)
            else:
                exitcode, stdout, stderr = 0, result.stdout, ''

            message = 'task_id=%s, user:%s host:%s command:%s status:%s, success:%s, error:%s' % (
                wenv['task_id'], self.user, self.host, command, exitcode,
                stdout, stderr)
            # TODO
            ws_dict = {
                'user': self.user,
                'host': self.host,
                'cmd': command,
                'status': exitcode,
                'stage': wenv['stage'],
                'sequence': wenv['sequence'],
                'success': stdout,
                'error': stderr,
            }
            if wenv['console']:
                emit('console', {
                    'event': 'task:console',
                    'data': ws_dict
                },
                     room=wenv['task_id'])

            RecordModel().save_record(stage=wenv['stage'],
                                      sequence=wenv['sequence'],
                                      user_id=wenv['user_id'],
                                      task_id=wenv['task_id'],
                                      status=exitcode,
                                      host=self.host,
                                      user=self.user,
                                      command=result.command,
                                      success=stdout,
                                      error=stderr)
            current_app.logger.info(result)
            if exitcode != Code.Ok:
                current_app.logger.error(message, exc_info=1)
                current_app.logger.exception(result.stdout.strip(), exc_info=1)
                return result
            return result

        except Exception as e:
            current_app.logger.exception(e)

            # TODO 貌似可能的异常有很多种,需要分层才能完美解决 something wrong without e.result
            error = e.result if 'result' in e else e.message
            RecordModel().save_record(stage=wenv['stage'],
                                      sequence=wenv['sequence'],
                                      user_id=wenv['user_id'],
                                      task_id=wenv['task_id'],
                                      status=1,
                                      host=self.host,
                                      user=self.user,
                                      command=command,
                                      success='',
                                      error=error)
            if hasattr(e, 'reason') and hasattr(e, 'result'):
                message = 'task_id=%s, user:%s host:%s command:%s, status=1, reason:%s, result:%s exception:%s' % (
                    wenv['task_id'], self.user, self.host, command, e.reason,
                    error, e.message)
            else:
                message = 'task_id=%s, user:%s host:%s command:%s, status=1, message:%s' % (
                    wenv['task_id'], self.user, self.host, command, e.message)
            current_app.logger.error(message, exc_info=1)

            # TODO
            ws_dict = {
                'user': self.user,
                'host': self.host,
                'cmd': command,
                'status': 1,
                'stage': wenv['stage'],
                'sequence': wenv['sequence'],
                'success': '',
                'error': error,
            }
            if wenv['console']:
                emit('console', {
                    'event': 'console',
                    'data': ws_dict
                },
                     room=wenv['task_id'])

            if exception:
                raise e
            return Result(exited=-1, stderr=error, stdout=error)
Exemple #18
0
 def logs(self):
     return RecordModel().fetch(task_id=self.task_id)
Exemple #19
0
 def start(self):
     RecordModel().query.filter_by(task_id=self.task_id).delete()
     TaskModel().get_by_id(self.task_id).update({'status': TaskModel.status_doing})
     self.taskMdl = TaskModel().item(self.task_id)
Exemple #20
0
    def run(self, command, wenv=None, sudo=False, **kwargs):
        '''
        # TODO
        pty=True/False是直接影响到输出.False较适合在获取文本,True更适合websocket

        :param command:
        :param wenv:
        :param sudo:
        :param kwargs:
        :return:
        '''
        try:
            message = 'task_id=%s, host:%s command:%s' % (wenv['task_id'],
                                                          self.host, command)
            current_app.logger.info(message)
            if sudo:
                result = super(Waller, self).sudo(command, pty=False, **kwargs)
            else:
                result = super(Waller, self).run(command, pty=False, **kwargs)

            message = 'task_id=%s, host:%s command:%s status:%s, success:%s, error:%s' % (
                wenv['task_id'], self.host, command, result.exited,
                result.stdout.strip(), result.stderr.strip())

            # TODO
            ws_dict = {
                'host': self.host,
                'cmd': command,
                'status': result.exited,
                'stage': wenv['stage'],
                'sequence': wenv['sequence'],
                'success': result.stdout.strip(),
                'error': result.stderr.strip(),
            }
            if wenv['console']:
                emit('console', {
                    'event': 'task:console',
                    'data': ws_dict
                },
                     room=wenv['task_id'])

            RecordModel().save_record(stage=wenv['stage'],
                                      sequence=wenv['sequence'],
                                      user_id=wenv['user_id'],
                                      task_id=wenv['task_id'],
                                      status=result.exited,
                                      host=self.host,
                                      user=self.user,
                                      command=result.command,
                                      success=result.stdout.strip(),
                                      error=result.stderr.strip())
            current_app.logger.info(message)
            return result

        except Exception, e:
            #current_app.logger.exception(e)
            #return None
            # TODO 貌似可能的异常有很多种,需要分层才能完美解决 something wrong without e.result
            RecordModel().save_record(stage=wenv['stage'],
                                      sequence=wenv['sequence'],
                                      user_id=wenv['user_id'],
                                      task_id=wenv['task_id'],
                                      status=1,
                                      host=self.host,
                                      user=self.user,
                                      command=command,
                                      success='',
                                      error='e.result')
            if hasattr(e, 'resean') and hasattr(e, 'result'):
                message = 'task_id=%s, host:%s command:%s, status=1, reason:%s, result:%s' % (
                    wenv['task_id'], self.host, command, e.reason, e.result)
            else:
                message = 'task_id=%s, host:%s command:%s, status=1, message:%s' % (
                    wenv['task_id'], self.host, command, e.message)

            # TODO

            ws_dict = {
                'host': self.host,
                'cmd': command,
                'status': 1,
                'stage': wenv['stage'],
                'sequence': wenv['sequence'],
                'success': '',
                'error': e.message,
            }
            if wenv['console']:
                emit('console', {
                    'event': 'task:console',
                    'data': ws_dict
                },
                     room=wenv['task_id'])
            current_app.logger.error(message)

            return False
Exemple #21
0
    def run(self, command, wenv=None, sudo=False, **kwargs):
        '''
        # TODO
        pty=True/False是直接影响到输出.False较适合在获取文本,True更适合websocket

        :param command:
        :param wenv:
        :param sudo:
        :param kwargs:
        :return:
        '''
        message = 'deploying task_id=%s [%s@%s]$ %s ' % (
            wenv['task_id'], self.user, self.host, command)
        current_app.logger.info(message)
        try:
            if sudo:
                result = super(Waller, self).sudo(command, pty=False, **kwargs)
            else:
                result = super(Waller, self).run(command,
                                                 pty=True,
                                                 warn=True,
                                                 **kwargs)

            if result.failed:
                exitcode, stdout, stderr = result.exited, '', result.stdout
            else:
                exitcode, stdout, stderr = 0, result.stdout, ''

            message = 'task_id=%s, host:%s command:%s status:%s, success:%s, error:%s' % (
                wenv['task_id'], self.host, command, exitcode, stdout, stderr)
            current_app.logger.error(result.stdout.strip())
            # TODO
            ws_dict = {
                'user': self.user,
                'host': self.host,
                'cmd': command,
                'status': exitcode,
                'stage': wenv['stage'],
                'sequence': wenv['sequence'],
                'success': stdout,
                'error': stderr,
            }
            if wenv['console']:
                emit('console', {
                    'event': 'task:console',
                    'data': ws_dict
                },
                     room=wenv['task_id'])

            RecordModel().save_record(stage=wenv['stage'],
                                      sequence=wenv['sequence'],
                                      user_id=wenv['user_id'],
                                      task_id=wenv['task_id'],
                                      status=exitcode,
                                      host=self.host,
                                      user=self.user,
                                      command=result.command,
                                      success=stdout,
                                      error=stderr)
            current_app.logger.info(message)
            if exitcode != 0:
                # TODO
                return result
            return result

        except Exception as e:
            # current_app.logger.exception(e)
            # return None
            # TODO 貌似可能的异常有很多种,需要分层才能完美解决 something wrong without e.result
            error = e.result if 'result' in e else e.message
            current_app.logger.info(e)
            RecordModel().save_record(stage=wenv['stage'],
                                      sequence=wenv['sequence'],
                                      user_id=wenv['user_id'],
                                      task_id=wenv['task_id'],
                                      status=1,
                                      host=self.host,
                                      user=self.user,
                                      command=command,
                                      success='',
                                      error=error)
            if hasattr(e, 'reason') and hasattr(e, 'result'):
                message = 'task_id=%s, host:%s command:%s, status=1, reason:%s, result:%s exception:%s' % (
                    wenv['task_id'], self.host, command, e.reason, error,
                    e.message)
            else:
                message = 'task_id=%s, host:%s command:%s, status=1, message:%s' % (
                    wenv['task_id'], self.host, command, e.message)

            # TODO
            ws_dict = {
                'user': self.user,
                'host': self.host,
                'cmd': command,
                'status': 1,
                'stage': wenv['stage'],
                'sequence': wenv['sequence'],
                'success': '',
                'error': e.message,
            }
            if wenv['console']:
                emit('console', {
                    'event': 'task:console',
                    'data': ws_dict
                },
                     room=wenv['task_id'])
            current_app.logger.error(message)

            return False