def k8s_pod_delete(context=None, dm_name=None): if context and dm_name: Scheduler = produce.SchedulerPublish() Scheduler = Scheduler.Scheduler_mem(k8s_resource.api_delete_pod, [context, dm_name]) Scheduler.start() return jsonify({'result': 'ok'})
def m_image_update(): try: tools.Async_log(g.user, request.url) reload(MyForm) form = MyForm.FormK8sUpdate() if form.submit.data: deployment = form.deployment.data version = form.version.data context = form.contexts.data if version: new_image = "%s/%s:%s" % (docker_registry, deployment, version) new_replicas = form.replicas.data redis_key = 'op_k8s_update_%s' % time.strftime( '%Y%m%d%H%M%S', time.localtime()) Scheduler = produce.SchedulerPublish() Scheduler = Scheduler.Scheduler_mem( k8s_resource.object_update, [ context, new_image, new_replicas, version, redis_key, 'web' ]) Scheduler.start() return render_template('mobile/m_deploy_show.html', redis_key=redis_key) except Exception as e: logging.error(e) return render_template('mobile/m_k8s_update.html', form=form)
def image_update(): try: tools.Async_log(g.user, request.url) reload(MyForm) form = MyForm.FormK8sUpdate() if form.submit.data: rollback = False deployment = form.deployment.data version = form.version.data context = form.contexts.data rollback_image = form.images.data if version or rollback_image: new_image = "%s/%s:%s" % (docker_registry, deployment, version) if rollback_image: rollback = True new_image = rollback_image redis_key = 'op_k8s_update_%s' % time.strftime( '%Y%m%d%H%M%S', time.localtime()) Scheduler = produce.SchedulerPublish() Scheduler = Scheduler.Scheduler_mem( k8s_resource.object_update, [context, new_image, version, rollback, redis_key, 'web']) Scheduler.start() return render_template('deploy_show.html', redis_key=redis_key) except Exception as e: logging.error(e) return redirect(url_for('error')) return render_template('k8s_update.html', form=form)
def image_update(): try: tools.Async_log(g.user, request.url) reload(MyForm) form = MyForm.FormK8sUpdate() db_deploy = db_op.k8s_deploy rollback = False if form.submit.data: deployment = form.deployment.data version = form.version.data context = form.contexts.data action = form.action.data if version: image = "%s/%s:%s" % (docker_registry[context], deployment, version) if action == 'rollback': rollback = True val = db_deploy.query.filter( db_deploy.image == image).all() if not val: flash('%s版本镜像不存在!' % version) return render_template('Message.html') redis_key = 'op_k8s_update_%s' % time.strftime( '%Y%m%d%H%M%S', time.localtime()) Scheduler = produce.SchedulerPublish() Scheduler = Scheduler.Scheduler_mem( k8s_resource.object_update, [context, image, version, rollback, redis_key, 'web']) Scheduler.start() return render_template('deploy_show.html', redis_key=redis_key) except Exception as e: logging.error(e) return redirect(url_for('error')) return render_template('k8s_update.html', form=form)
def k8s_project_update(): db_token = db_op.platform_token params = request.get_json() new_replicas = None msg = None project = None version = None try: if params: if 'project' in params and 'version' in params and 'access_token' in params and 'context' in params: token = params['access_token'] project = params['project'] version = params['version'] context = params['context'] new_image = "%s/%s:%s" % (docker_registry[context], project.split('.')[0], version) if 'replicas' in params: new_replicas = params['replicas'] # 验证token是否有效 vals = db_token.query.filter( and_( db_token.token == token, db_token.expire > time.strftime( '%Y-%m-%d', time.localtime()))).all() if vals: redis_key = 'op_k8s_update_%s' % time.strftime( '%Y%m%d%H%M%S', time.localtime()) Scheduler = produce.SchedulerPublish() Scheduler = Scheduler.Scheduler_mem( k8s_resource.object_update, [ context, new_image, new_replicas, version, redis_key, 'api' ]) Scheduler.start() else: msg = '授权验证不通过!' else: msg = '传递参数错误!' else: msg = '传递参数不能为空!' except Exception as e: msg = e finally: if msg: ops_token = app.config.get('OPS_TOKEN') text = [ '**容器平台自动上线:**', "项目:%s" % project, "版本:%s" % version, "Error:%s" % msg, '**请确认请求正确!**' ] tools.dingding_msg(text, ops_token) return jsonify({'result': 'ok'})
def Publish_center(args): try: INFOS, Msg_Key, secret_key = args server_lists_counts = 0 #获取上线操作参数 execute = INFOS['execute'] channel = INFOS['channel'] flow_number = INFOS['timestamp'] _flow_log(flow_number, 'Publish center(%s) start work ......' % os.getpid()) _flow_log(flow_number, INFOS) _console_out(channel, Msg_Key, '-' * 100) _console_out(channel, Msg_Key, "初始化代码分发参数及检测部署环境,检测进行中......") #页面回滚操作需要将部分参数回写 if execute == 'rollback' and channel == 'web': project = INFOS['project'] version = INFOS['version'] vals = db_publish.query.with_entities( db_publish.package_url, db_publish.package_md5, db_publish.package_type, db_publish.publish_type, db_publish.restart, db_publish.check_url, db_publish.gray).filter( and_(db_publish.project == project, db_publish.version == version, db_publish.result == 'Success')).order_by( desc(db_publish.date)).all() if vals: package_url, package_md5, package_type, publish_type, restart, check_url, gray = vals[ 0] INFOS['package_url'] = package_url INFOS['package_md5'] = package_md5 INFOS['package_type'] = package_type INFOS['publish_type'] = publish_type INFOS['restart'] = restart INFOS['check_url'] = check_url INFOS['gray'] = int(gray) else: _Msg = "project:%s version:%s --->not relevant data Fail !" % ( project, version) _flow_log(flow_number, _Msg) raise _console_out(channel, Msg_Key, _Msg) project = INFOS['project'] package_url = INFOS['package_url'] package_md5 = INFOS['package_md5'] package_type = INFOS['package_type'] publish_type = INFOS['publish_type'] gray = INFOS['gray'] web_path = '/opt/tomcat-%s/webapps/' % project #判断代码包类型 Package_name = package_url.split('/')[-1] os.system("/bin/mkdir -p %s" % web_path) os.system("/bin/mkdir -p %s" % bak_path) package_path = "%s%s" % (bak_path, Package_name) package_name = Package_name.replace('.zip', '') s_files = "%s%s" % (web_path, package_name) #验证包规则 if project == '-'.join(package_name.split('-')[:-1]): if package_name.endswith('.war'): package_name = '%s.war' % project else: package_name = project else: _Msg = "%s package format Fail" % Package_name _flow_log(flow_number, _Msg) raise _console_out(channel, Msg_Key, _Msg) if package_name.endswith('.war') and package_type == 'part': _Msg = "%s package not allow part publish" % Package_name _flow_log(flow_number, _Msg) raise _console_out(channel, Msg_Key, _Msg) d_files = "%s%s" % (web_path, package_name) #删除旧包 if os.path.exists(package_path): os.remove(package_path) #获取代码压缩包 try: urlretrieve(package_url, package_path) except Exception as e: msg = "package_url:%s --->check package url Fail !" % package_url _flow_log(flow_number, 'Error:%s' % str(e)) _flow_log(flow_number, msg) raise _console_out(channel, Msg_Key, msg) #对压缩包进行md5对比 _flow_log(flow_number, "package_md5:%s" % Md5.Md5_file(package_path)) if package_md5 == Md5.Md5_file(package_path): #解压缩代码包 try: zip_file = zipfile.ZipFile(package_path) if os.path.exists('%s%s' % (web_path, package_name)): try: shutil.rmtree('%s%s' % (web_path, package_name)) except: os.remove('%s%s' % (web_path, package_name)) zip_file.extractall(web_path) except Exception as e: msg = "package:%s --->check unzip package Fail !" % package_name _flow_log(flow_number, 'Error:%s' % str(e)) _flow_log(flow_number, msg) raise _console_out(channel, Msg_Key, msg) else: _Msg = "package:%s --->check package md5 Fail !" % package_name _flow_log(flow_number, _Msg) raise _console_out(channel, Msg_Key, _Msg) if os.path.exists(s_files): shutil.move(s_files, d_files) if os.path.exists(d_files): #获取应用部署列表 vals = db_project.query.with_entities( db_project.ip, db_project.ssh_port, db_project.app_port).filter( db_project.project == project).all() if vals: server_lists = [list(val) for val in vals] #判断是否为灰度上线,并尝试获取服务器灰度标识 if int(gray) == 1: gray_vals = db_project.query.with_entities( db_project.ip, db_project.ssh_port, db_project.app_port).filter( and_(db_project.project == project, db_project.gray == 1)).all() if gray_vals: server_lists = [list(val) for val in gray_vals] else: server_lists = [list(val) for val in vals][0] server_lists_counts = len(server_lists) #服务器和应用服务连通性检测 for infos in server_lists: ip, ssh_port, app_port = infos try: try: ssh = paramiko.SSHClient() ssh_key = paramiko.RSAKey.from_private_key_file( key_file) ssh.set_missing_host_key_policy( paramiko.AutoAddPolicy()) ssh.connect(ip, int(ssh_port), username, pkey=ssh_key, timeout=30) except: _Msg = "ip:%s ssh_port:%s --->check sshd Fail !" % ( ip, ssh_port) _flow_log(flow_number, _Msg) raise _console_out(channel, Msg_Key, _Msg) else: #检测线上代码包路径是否存在 cmd = "[ -d %s ] && echo ok" % web_path stdin, stdout, stderr = ssh.exec_command(cmd) result = str(stdout.read().strip(), encoding='utf8') if result != 'ok': _Msg = "ip:%s ssh_port:%s web_path:%s --->check app path Fail !" % ( ip, ssh_port, web_path) _flow_log(flow_number, _Msg) raise _console_out(channel, Msg_Key, _Msg) #创建备份目录 if package_name.endswith('.war'): cmd = "/bin/mkdir -p %s" % bak_path else: cmd = "/bin/mkdir -p %s/%s" % (bak_path, package_name) stdin, stdout, stderr = ssh.exec_command(cmd) result = stderr.read() if result: _Msg = "ip:%s ssh_port:%s bak_path:%s --->make bak path Fail !" % ( ip, ssh_port, bak_path) _flow_log(flow_number, "Error:%s" % result) _flow_log(flow_number, _Msg) raise _console_out(channel, Msg_Key, _Msg) ssh.close() except: raise else: if not tcpping(host=ip, port=app_port, timeout=3): _Msg = "ip:%s app_port:%s --->check app port Fail !" % ( ip, app_port) _flow_log(flow_number, _Msg) raise _console_out(channel, Msg_Key, _Msg) #部署列表写入redis队列 server_lists_key = '%s_server_lists_key' % secret_key for info in server_lists: Redis.sadd(server_lists_key, info) #启动多个子控制中心并发执行 _console_out(channel, Msg_Key, "代码分发相关参数及运行环境检测全部通过!") _console_out(channel, Msg_Key, "启动代码分发模块,开始部署%s,执行过程稍后输出......" % package_name) _console_out(channel, Msg_Key, '-' * 100) for i in range(Publish_types[publish_type]): Scheduler = produce.SchedulerPublish() Scheduler = Scheduler.Scheduler_mem( Publish_agent, [ server_lists_key, server_lists_counts, d_files, project, package_name, package_path, Msg_Key, secret_key, INFOS ]) Scheduler.start() time.sleep(1) else: _Msg = "Error:not find app service lists!" _flow_log(flow_number, _Msg) raise _console_out(channel, Msg_Key, _Msg) else: _Msg = "package:%s --->move package Fail !" % package_name _flow_log(flow_number, _Msg) raise _console_out(channel, Msg_Key, _Msg) except Exception as e: if 'old-style' not in str(e): _flow_log(flow_number, 'Error:%s' % str(e)) result = "代码分发环境检测到错误,不执行代码分发操作!" _console_out(channel, Msg_Key, result) _console_out(channel, Msg_Key, '-' * 100) _console_out( channel, Msg_Key, "_End_:0,0,0,%i,%i:%s" % (server_lists_counts, server_lists_counts, flow_number)) #汇总结果后回调接口 _result_handle(result, server_lists_counts, INFOS) Redis.expire(Msg_Key, 15) finally: db_op.DB.session.remove()
def deployment_create(): tools.Async_log(g.user, request.url) reload(MyForm) form = MyForm.FormK8sDeploy() mounts = defaultdict() if form.submit.data: context = form.contexts.data project = form.projects.data version = form.version.data object = form.object.data container_port = form.container_port.data ingress_port = form.ingress_port.data replicas = form.replicas.data request_cpu = form.request_cpu.data limit_cpu = form.limit_cpu.data request_mem = form.request_mem.data limit_mem = form.limit_mem.data domain = form.domain.data healthcheck = form.healthcheck.data mount_path2 = form.mount_path2.data mount_name2 = form.mount_name2.data sidecar = form.sidecar.data run_args = form.run_args.data run_args = run_args.splitlines() re_requests = {} re_limits = {} if mount_path2: mounts[mount_path2] = mount_name2 try: if object and version and container_port and replicas: if object.endswith('.war') or object.endswith( '.tar.gz') or object.endswith('.jar'): dm_name = object.split('.')[0] image = "%s/%s:%s" % (docker_registry, dm_name, version) docker_file = "%s/%s" % (dockerfile_path, dm_name) if os.path.exists(docker_file): container_port = [ int(port) for port in container_port.split(',') ] if request_cpu and limit_cpu and request_mem and limit_mem: if float(request_cpu) > float(limit_cpu) or float( request_mem) > float(limit_mem): raise flash('限制资源不能小于请求资源!') else: re_requests = { 'cpu': request_cpu, 'memory': '%sG' % request_mem } re_limits = { 'cpu': limit_cpu, 'memory': '%sG' % limit_mem } if domain and not ingress_port: raise flash('域名配置后还需配置容器对外服务端口!') redis_key = 'op_k8s_create_%s' % time.strftime( '%Y%m%d%H%M%S', time.localtime()) Scheduler = produce.SchedulerPublish() Scheduler = Scheduler.Scheduler_mem( k8s_resource.object_deploy, [ context, project, object, version, image, run_args, container_port, ingress_port, replicas, domain, re_requests, mounts, healthcheck, sidecar, re_limits, redis_key ]) Scheduler.start() return render_template('deploy_show.html', redis_key=redis_key) else: flash("%s文件路径不存在!" % docker_file) else: flash("%s包名应以.war或者.tar.gz结尾或者.jar结尾!" % object) else: flash('必填项参数不完整!') return render_template('Message.html') except Exception as e: logging.error(e) return redirect(url_for('error')) return render_template('k8s_deploy.html', form=form)
def publish(): try: tools.Async_log(g.user, request.url) importlib.reload(MyForm) secret_key = tools.Produce(length=12, chars=string.digits) Msg_Key = 'op_publish_msg_%s' % secret_key form = MyForm.MyFormPublish() if form.submit.data: try: if Redis.exists(Msg_Key): raise flash('上线操作过于频繁,请稍等%s秒......' % Redis.ttl(Msg_Key)) package_url = form.package_url.data describe = form.describe.data package_md5 = form.package_md5.data package_type = form.package_type.data publish_type = form.publish_type.data check_url = form.check_url.data restart = form.restart.data execute = form.execute.data rb_project = form.project.data rb_version = form.version.data gray = form.gray.data if execute == 'rollback': if not rb_project and not rb_version: raise logging.error("choice can not be empty!") if execute == 'publish': if not package_url or not package_md5 or not check_url or not describe: raise logging.error("input can not be empty!") Package_name = package_url.split('/')[-1] package_name = Package_name.replace('.zip', '') rb_project = '-'.join(package_name.split('-')[:-1]) INFOS = { 'package_url': package_url, 'package_md5': package_md5, 'package_type': package_type, 'publish_type': publish_type, 'user': g.user, 'describe': describe.replace('"', '').replace("'", ''), 'gray': int(gray), 'restart': restart, 'execute': execute, 'check_url': check_url.replace('https', 'http'), 'project': rb_project, 'version': rb_version, 'channel': 'web', 'callback_url': 'None', 'token': 'None', 'timestamp': int(time.time()) } #启动代码分发控制中心 Scheduler = produce.SchedulerPublish() Scheduler = Scheduler.Scheduler_mem( task_publish.Publish_center, [INFOS, Msg_Key, secret_key]) Scheduler.start() return render_template('publish_show.html', secret_key=secret_key) except Exception as e: if 'old-style' not in str(e): logging.error(e) except Exception as e: logging.error(e) return redirect(url_for('error')) return render_template('publish.html', form=form)