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}
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)
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
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)
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
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)
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)
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
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'])
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, })
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'])
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)
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()
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)
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, })
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)
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)
def logs(self): return RecordModel().fetch(task_id=self.task_id)
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)
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
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