def do_rollback(self, id, log, record_id): ''' 回滚 ''' sequence = 1 with open(log, 'a') as f: f.write('[INFO]------正在执行回滚[%s]------\n' % (sequence)) record = DeployRecord.objects.filter(id=int(id)).values() server_ids = record[0]['server_ids'].split(',') name = '回滚_' + str(id) + '_' + record_id for sid in server_ids: try: auth_info, auth_key = auth_init(sid) connect = Shell(auth_info, connect_timeout=5, connect_kwargs=auth_key) version_file = '%s/%s' % (record[0]['target_root'], record[0]['alias'] + '_version.txt') # 判断回滚版本是否存在 command = '[ -d %s/%s ] || echo "false"' % (record[0]['target_releases'], record[0]['prev_record']) self.result = connect.run(command, write=log) if not self.result.stdout.strip() == 'false': # 删除目标软链 command = 'find %s -type l -delete' % (record[0]['target_root']) self.result = connect.run(command, write=log) # 创建需回滚版本软链到webroot command = 'ln -sfn %s/%s/* %s' % ( record[0]['target_releases'], record[0]['prev_record'], record[0]['target_root']) if self.result.exited == 0: self.result = connect.run(command, write=log) command = 'echo %s > %s' % (record[0]['prev_record'], version_file) if self.result.exited == 0: self.result = connect.run(command, write=log) connect.close() except Exception as e: error_logger.error(e) # 处理完记录入库 defaults = { 'name': name, 'record_id': record[0]['prev_record'], 'alias': record[0]['alias'], 'project_id': record[0]['project_id'], 'server_ids': record[0]['server_ids'], 'target_root': record[0]['target_root'], 'target_releases': record[0]['target_releases'], 'prev_record': record[0]['record_id'], 'is_rollback':True, 'status': 'Succeed' } if self.result.exited != 0 or self.result.stdout.strip() == 'false': defaults['status'] = 'Failed' defaults['is_rollback'] = False DeployRecord.objects.create(**defaults) Project.objects.filter(id=record[0]['project_id']).update(last_task_status='Failed') with open(log, 'a') as f: f.write('[ERROR]------回滚失败------\n') f.write('[ERROR]回滚的版本文件可能已删除!\n') else: DeployRecord.objects.create(**defaults) Project.objects.filter(id=record[0]['project_id']).update(last_task_status='Succeed') sequence = 6 with open(log, 'a') as f: f.write('[INFO]------回滚完成,请重启应用[%s]------\n' % (sequence))
def post(self, request, format=None): if request.data['excu'] == 'list': try: app_log_path = request.data['app_log_path'] host = request.data['host'] auth_info, auth_key = auth_init(host) connect = Shell(auth_info, connect_timeout=5, connect_kwargs=auth_key) commands = "find %s -name '*.log'" % (app_log_path) result = connect.run(commands).stdout res = [] for i in result.split(): res.append(i) res = filter(None, res) connect.close() http_status = OK except Exception as e: http_status = BAD res = '执行错误:' + str(e) return XopsResponse(res, status=http_status) elif request.data['excu'] == 'filedown': file_path = request.data['file_path'] host = request.data['host'] file_name = os.path.basename(file_path) dir_name = os.path.dirname(file_path) old_file_name = os.path.splitext(file_name) if old_file_name[1] == '.log': new_file_name = old_file_name[0] + '.tar.gz' auth_info, auth_key = auth_init(host) connect = Shell(auth_info, connect_timeout=5, connect_kwargs=auth_key) commands = 'mkdir -p /tmp/remote/ && tar czf /tmp/remote/%s -C %s %s' % ( new_file_name, dir_name, file_name) connect.run(commands) connect.get('/tmp/remote/' + new_file_name, '/tmp/' + new_file_name) response = FileResponse(open('/tmp/' + new_file_name, 'rb')) response['Content-Type'] = 'application/octet-stream' response[ 'Content-Disposition'] = 'attachment;filename="%s"' % old_file_name[ 0] commands = 'rm -f /tmp/remote/%s' % (new_file_name) connect.run(commands) connect.close() os.remove('/tmp/' + new_file_name) return response else: return XopsResponse('请求文件格式不对!', status=BAD)
def get(self, request, format=None): file_path = request.query_params['file'] host = request.query_params['sid'] file_name = os.path.basename(file_path) new_file_name = os.path.splitext(file_name)[0] + '.tar.gz' auth_info, auth_key = auth_init(host) connect = Shell(auth_info, connect_timeout=5, connect_kwargs=auth_key) commands = 'mkdir -p /tmp/remote/ && tar czf /tmp/remote/%s %s' % ( new_file_name, file_path) connect.run(commands) connect.get('/tmp/remote/' + new_file_name, '/tmp/' + new_file_name) response = FileResponse(open('/tmp/' + new_file_name, 'rb')) response['Content-Type'] = 'application/octet-stream' response[ 'Content-Disposition'] = 'attachment;filename="%s"' % new_file_name commands = 'rm -f /tmp/remote/%s' % (new_file_name) connect.run(commands) connect.close() os.remove('/tmp/' + new_file_name) return response
def scan_execution(): scan_settings_load = ScanSettingsLoad() start_time = time.time() auth_type = scan_settings_load.get_conf_content('hosts', 'auth_type') hosts = scan_settings_load.os_scan() login_hosts = [] for host in hosts: if host['open'] == 'open': login_hosts.append(host) elif host['os'] == 'unknown': DeviceScanInfo.objects.update_or_create(hostname=host['host'], defaults={ 'os_version': host['os'], 'os_type': 'Other' }) if login_hosts: # 从配置文件中获取登陆认证信息和认证类型 for host in login_hosts: kwargs = { 'hostname': host['host'], 'username': scan_settings_load.get_conf_content('hosts', 'ssh_username'), 'port': scan_settings_load.get_conf_content('hosts', 'ssh_port'), 'commands': scan_settings_load.get_conf_content('hosts', 'commands') } if auth_type == 'password': kwargs['password'] = scan_settings_load.get_conf_content( 'hosts', 'ssh_password') else: kwargs['password'] = scan_settings_load.get_conf_content( 'hosts', 'ssh_private_key') # 将登陆执行结果数据复制给defaults kwargs['auth_type'] = auth_type kwargs['os_type'] = 'Linux' # 构建连接信息 auth_info = '{user}@{host}:{port}'.format(user=kwargs['username'], host=kwargs['hostname'], port=kwargs['port']) auth_key = {auth_type: kwargs['password']} connect = Shell(auth_info, connect_timeout=5, connect_kwargs=auth_key) commands = kwargs['commands'] kwargs['error_message'] = [] for key, value in commands.items(): result = connect.run(value) if hasattr(result, 'stdout'): if result.failed: kwargs['status'] = 'Failed' kwargs['error_message'].append( str(result.stderr) + '\n') else: kwargs[key] = result.stdout kwargs['status'] = 'Succeed' kwargs['error_message'] = '' continue else: kwargs['status'] = 'Failed' kwargs['error_message'] = str(result) break connect.close() defaults = kwargs defaults.pop('commands') DeviceScanInfo.objects.update_or_create(hostname=host['host'], defaults=defaults) end_time = time.time() msg = '扫描任务已完成, 执行时间:%(time)s秒, 共%(num)s台主机.' % { 'time': end_time - start_time, 'num': len(hosts) } info_logger.info(msg)
def post(self, request, format=None): if request.data['excu'] == 'init': # 项目初始化 id = request.data['id'] result = self.repo_init(id) if result.exited == 0: Project.objects.filter(id=id).update(status='Succeed') info_logger.info('初始化项目:' + str(id) + ',执行成功!') http_status = OK msg = '初始化成功!' else: error_logger.error('初始化项目:%s 执行失败! 错误信息:%s' % (str(id), result.stderr)) http_status = BAD msg = '初始化项目:%s 执行失败! 错误信息:%s' % (str(id), result.stderr) return XopsResponse(msg, status=http_status) elif request.data['excu'] == 'deploy': # 部署操作 id = request.data['id'] webuser = request.user.username alias = request.data['alias'] self.start_time = time.strftime("%Y%m%d%H%M%S", time.localtime()) record_id = str(alias) + '_' + str(self.start_time) name = '部署_' + record_id DeployRecord.objects.create(name=name, alias=alias, status='Failed', project_id=int(id)) Project.objects.filter(id=id).update(last_task_status='Failed') local_log_path = self._path.rstrip('/') + '/' + str( id) + '_' + str(request.data['alias']) + '/logs' log = local_log_path + '/' + record_id + '.log' version = request.data['version'].strip() serverid = request.data['server_ids'] # 调用celery异步任务 deploy.delay(id, log, version, serverid, record_id, webuser, self.start_time) return XopsResponse(record_id) elif request.data['excu'] == 'rollback': # 回滚 id = request.data['id'] project_id = request.data['project_id'] alias = request.data['alias'] self.start_time = time.strftime("%Y%m%d%H%M%S", time.localtime()) record_id = str(alias) + '_' + str(self.start_time) log = self._path.rstrip('/') + '/' + str(project_id) + '_' + str( alias) + '/logs/' + record_id + '.log' self.do_rollback(id, log, record_id) return XopsResponse(record_id) elif request.data['excu'] == 'deploymsg': # 部署控制台消息读取 try: id = request.data['id'] alias = request.data['alias'] record = request.data['record'] scenario = int(request.data['scenario']) logfile = self._path.rstrip('/') + '/' + str(id) + '_' + str( alias) + '/logs/' + record + '.log' webuser = request.user.username if scenario == 0: local_tailf.delay(logfile, webuser, id) http_status = OK request_status = '执行成功!' except Exception as e: http_status = BAD request_status = str(e) return XopsResponse(request_status, status=http_status) elif request.data['excu'] == 'readlog' and request.data[ 'scenario'] == 1: # 读取部署日志 try: id = request.data['id'] alias = request.data['alias'] record = request.data['record'] logfile = self._path.rstrip('/') + '/' + str(id) + '_' + str( alias) + '/logs/' + record + '.log' response = FileResponse(open(logfile, 'rb')) response['Content-Type'] = 'text/plain' return response except Exception: http_status = BAD request_status = '执行错误:文件不存在!' return XopsResponse(request_status, status=http_status) elif request.data['excu'] == 'app_start': # 项目启动 try: app_start = request.data['app_start'] host = request.data['host'] webuser = request.user.username auth_info, auth_key = auth_init(host) connect = Shell(auth_info, connect_timeout=5, connect_kwargs=auth_key) app_start = app_start.strip().replace('&&', '').replace('||', '') connect.run(app_start, ws=True, webuser=webuser) connect.close() http_status = OK request_status = '执行成功!' except Exception as e: http_status = BAD request_status = '执行错误:' + str(e) return XopsResponse(request_status, status=http_status) elif request.data['excu'] == 'app_stop': # 项目停止 try: app_stop = request.data['app_stop'] host = request.data['host'] webuser = request.user.username auth_info, auth_key = auth_init(host) connect = Shell(auth_info, connect_timeout=5, connect_kwargs=auth_key) app_stop = app_stop.strip().replace('&&', '').replace('||', '') connect.run(app_stop, ws=True, webuser=webuser) connect.close() http_status = OK request_status = '执行成功!' except Exception as e: http_status = BAD request_status = '执行错误:' + str(e) return XopsResponse(request_status, status=http_status) elif request.data['excu'] == 'tail_start': # 日志监控 try: filter_text = str(request.data['filter']) app_log_file = request.data['app_log_file'] host = request.data['host'] webuser = request.user.username device_info = DeviceInfo.objects.filter(id=int(host)).values() host = device_info[0]['hostname'] auth_type = device_info[0]['auth_type'] connect_info = ConnectionInfo.objects.filter( hostname=host, auth_type=auth_type).values() user = connect_info[0]['username'] passwd = connect_info[0]['password'] port = connect_info[0]['port'] tail = Tailf() tail.remote_tail(host, port, user, passwd, app_log_file, webuser, filter_text=filter_text) http_status = OK request_status = '执行成功!' except Exception as e: http_status = BAD request_status = str(e) return XopsResponse(request_status, status=http_status) elif request.data['excu'] == 'tail_stop': # 日志监控停止 try: webuser = request.user.username redis = RedisObj() redis.set('remote_tail_' + str(webuser), '1') http_status = OK request_status = '执行成功!' except Exception as e: http_status = BAD request_status = str(e) return XopsResponse(request_status, status=http_status)
def post(self, request, format=None): if request.data['excu'] == 'init': # 项目初始化 id = request.data['id'] result = self.repo_init(id) if result.exited == 0: Project.objects.filter(id=id).update(status='Succeed') info_logger.info('初始化项目:' + str(id) + ',执行成功!') http_status = OK msg = '初始化成功!' else: error_logger.error('初始化项目:%s 执行失败! 错误信息:%s' % (str(id), result.stderr)) http_status = BAD msg = '初始化项目:%s 执行失败! 错误信息:%s' % (str(id), result.stderr) return XopsResponse(msg, status=http_status) elif request.data['excu'] == 'deploy': # 部署操作 id = request.data['id'] webuser = request.user.username alias = request.data['alias'] self.start_time = time.strftime("%Y%m%d%H%M%S", time.localtime()) record_id = str(alias) + '_' + str(self.start_time) name = '部署_' + record_id DeployRecord.objects.create(name=name, alias=alias, status='Failed', project_id=int(id)) Project.objects.filter(id=id).update(last_task_status='Failed') local_log_path = self._path.rstrip('/') + '/' + str( id) + '_' + str(request.data['alias']) + '/logs' log = local_log_path + '/' + record_id + '.log' version = request.data['version'].strip() serverid = request.data['server_ids'] deploy = DeployExcu(webuser, record_id, id) deploy.start(log, version, serverid, record_id, webuser) return XopsResponse(record_id) elif request.data['excu'] == 'rollback': # 回滚 id = request.data['id'] project_id = request.data['project_id'] alias = request.data['alias'] self.start_time = time.strftime("%Y%m%d%H%M%S", time.localtime()) record_id = str(alias) + '_' + str(self.start_time) log = self._path.rstrip('/') + '/' + str(project_id) + '_' + str( alias) + '/logs/' + record_id + '.log' self.do_rollback(id, log, record_id) return XopsResponse(record_id) elif request.data['excu'] == 'deploymsg': # 部署控制台消息读取 try: id = request.data['id'] alias = request.data['alias'] record = request.data['record'] scenario = int(request.data['scenario']) logfile = self._path.rstrip('/') + '/' + str(id) + '_' + str( alias) + '/logs/' + record + '.log' webuser = request.user.username msg = Tailf() if scenario == 0: msg.local_tail(logfile, webuser) else: msg.read_file(logfile, webuser) http_status = OK request_status = '执行成功!' except Exception: http_status = BAD request_status = '执行错误:文件不存在!' return XopsResponse(request_status, status=http_status) elif request.data['excu'] == 'app_start': # 项目启动 try: app_start = request.data['app_start'] host = request.data['host'] webuser = request.user.username auth_info, auth_key = auth_init(host) connect = Shell(auth_info, connect_timeout=5, connect_kwargs=auth_key) app_start = app_start.strip().replace('&&', '').replace('||', '') commands = '/bin/bash -e %s' % (app_start) connect.run(commands, ws=True, webuser=webuser) connect.close() http_status = OK request_status = '执行成功!' except Exception as e: http_status = BAD request_status = '执行错误:' + str(e) return XopsResponse(request_status, status=http_status) elif request.data['excu'] == 'app_stop': # 项目停止 try: app_stop = request.data['app_stop'] host = request.data['host'] webuser = request.user.username auth_info, auth_key = auth_init(host) connect = Shell(auth_info, connect_timeout=5, connect_kwargs=auth_key) app_stop = app_stop.strip().replace('&&', '').replace('||', '') commands = '/bin/bash -e %s' % (app_stop) connect.run(commands, ws=True, webuser=webuser) connect.close() http_status = OK request_status = '执行成功!' except Exception as e: http_status = BAD request_status = '执行错误:' + str(e) return XopsResponse(request_status, status=http_status) elif request.data['excu'] == 'tail_start': # 日志监控 try: filter_text = str(request.data['filter']) app_log_file = request.data['app_log_file'] host = request.data['host'] webuser = request.user.username device_info = DeviceInfo.objects.filter(id=int(host)).values() host = device_info[0]['hostname'] auth_type = device_info[0]['auth_type'] connect_info = ConnectionInfo.objects.filter( hostname=host, auth_type=auth_type).values() user = connect_info[0]['username'] passwd = connect_info[0]['password'] port = connect_info[0]['port'] tail = Tailf() tail.remote_tail(host, port, user, passwd, app_log_file, webuser, filter_text=filter_text) http_status = OK request_status = '执行成功!' except Exception as e: http_status = BAD request_status = str(e) return XopsResponse(request_status, status=http_status) elif request.data['excu'] == 'tail_stop': # 日志监控停止 try: webuser = request.user.username if hasattr(gl, '_global_dict'): tail_key = 'tail_' + str(webuser) if tail_key in gl._global_dict.keys(): client = gl.get_value('tail_' + str(webuser)) client.close() http_status = OK request_status = '执行成功!' except Exception as e: http_status = BAD request_status = str(e) return XopsResponse(request_status, status=http_status)