cube-studio/myapp/views/view_workflow.py

337 lines
11 KiB
Python
Raw Normal View History

2021-08-17 17:00:34 +08:00
from flask import render_template,redirect
from flask_appbuilder.models.sqla.interface import SQLAInterface
from flask_babel import gettext as __
2022-08-11 10:47:08 +08:00
2021-08-17 17:00:34 +08:00
from myapp.models.model_job import Repository,Images,Job_Template,Task,Pipeline,Workflow,Tfjob,Xgbjob,RunHistory,Pytorchjob
from myapp.models.model_team import Project,Project_User
from flask_appbuilder.actions import action
2021-10-14 17:35:48 +08:00
from myapp.project import push_message,push_admin
2021-08-17 17:00:34 +08:00
from myapp import app, appbuilder,db,event_logger
from sqlalchemy import and_, or_, select
from myapp.utils.py import py_k8s
from .baseApi import (
MyappModelRestApi
)
from flask import (
current_app,
abort,
flash,
g,
Markup,
make_response,
redirect,
render_template,
request,
send_from_directory,
Response,
url_for,
)
from .base import (
api,
BaseMyappView,
check_ownership,
data_payload_response,
DeleteMixin,
generate_download_headers,
get_error_msg,
get_user_roles,
handle_api_exception,
json_error_response,
json_success,
MyappFilter,
MyappModelView,
)
from flask_appbuilder import CompactCRUDMixin, expose
import pysnooper,datetime,time,json
conf = app.config
logging = app.logger
class CRD_Filter(MyappFilter):
# @pysnooper.snoop()
def apply(self, query, func):
user_roles = [role.name.lower() for role in list(self.get_user_roles())]
if "admin" in user_roles:
return query.order_by(self.model.create_time.desc())
return query.filter(
or_(
self.model.labels.contains('"%s"'%g.user.username),
)
).order_by(self.model.create_time.desc())
class Crd_ModelView_Base():
list_columns = ['name','namespace_url','create_time','status','username','stop']
show_columns = ['name','namespace','create_time','status','annotations_html','labels_html','spec_html','status_more_html','info_json_html']
2021-09-07 18:09:47 +08:00
order_columns = ['id']
2022-09-09 21:17:20 +08:00
base_permissions = ['can_show', 'can_list', 'can_delete']
2021-08-17 17:00:34 +08:00
# base_permissions = ['list','delete','show']
# label_columns = {
# "annotations_html": _("Annotations"),
# "labels_html": _("Labels"),
# "name": _("名称"),
# "spec_html": _("Spec"),
# "status_more_html": _("Status"),
# "namespace_url":_("命名空间"),
# "create_time":_("创建时间"),
# "status": _("状态"),
# "username": _("关联用户"),
# "log": _("日志"),
# }
2021-11-25 18:07:40 +08:00
crd_name = ''
2021-08-17 17:00:34 +08:00
base_order = ('create_time', 'desc')
2022-08-11 10:47:08 +08:00
base_filters = [["id", CRD_Filter, lambda: []]]
2021-08-17 17:00:34 +08:00
# list
def base_list(self):
k8s_client = py_k8s.K8s()
crd_info = conf.get("CRD_INFO", {}).get(self.crd_name, {})
if crd_info:
crds = k8s_client.get_crd_all_namespaces(group=crd_info['group'],
version=crd_info['version'],
plural=crd_info['plural'])
# 删除所有注意最好id从0开始
db.session.query(self.datamodel.obj).delete()
# db.engine.execute("alter table %s auto_increment =0"%self.datamodel.pbj.__tablename__)
# 添加记录
for crd in crds:
try:
labels = json.loads(crd['labels'])
if 'run-rtx' in labels:
crd['username'] = labels['run-rtx']
elif 'upload-rtx' in labels:
crd['username'] = labels['upload-rtx']
except Exception as e:
logging.error(e)
crd_model = self.datamodel.obj(**crd)
db.session.add(crd_model)
db.session.commit()
# 基础批量删除
# @pysnooper.snoop()
def base_muldelete(self,items):
if not items:
abort(404)
for item in items:
if item:
try:
labels = json.loads(item.labels) if item.labels else {}
kubeconfig=None
if 'pipeline-id' in labels:
pipeline = db.session.query(Pipeline).filter_by(id=int(labels['pipeline-id'])).first()
if pipeline:
2022-06-05 20:38:37 +08:00
kubeconfig=pipeline.project.cluster.get('KUBECONFIG','')
2021-08-17 17:00:34 +08:00
k8s_client = py_k8s.K8s(kubeconfig)
crd_info = conf.get("CRD_INFO", {}).get(self.crd_name, {})
if crd_info:
crd_names = k8s_client.delete_crd(group=crd_info['group'],version=crd_info['version'],plural=crd_info['plural'],namespace=item.namespace,name=item.name)
# db_crds = db.session.query(self.datamodel.obj).filter(self.datamodel.obj.name.in_(crd_names)).all()
# for db_crd in db_crds:
# db_crd.status = 'Deleted'
# db.session.commit()
item.status='Deleted'
2021-09-07 18:09:47 +08:00
item.change_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
2021-08-17 17:00:34 +08:00
db.session.commit()
2021-10-14 17:35:48 +08:00
push_message(conf.get('ADMIN_USER', '').split(','), '手动触发stop %s %s' % (crd_info['plural'],item.name))
2021-08-17 17:00:34 +08:00
except Exception as e:
flash(str(e), "danger")
def pre_delete(self,item):
self.base_muldelete([item])
@expose("/stop/<crd_id>")
def stop(self, crd_id):
crd = db.session.query(self.datamodel.obj).filter_by(id=crd_id).first()
self.base_muldelete([crd])
2022-09-11 11:29:29 +08:00
flash('清理完成','success')
2021-08-17 17:00:34 +08:00
self.update_redirect()
return redirect(self.get_redirect())
@action(
"stop_all", __("Stop"), __("Stop all Really?"), "fa-trash", single=False
)
def stop_all(self, items):
self.base_muldelete(items)
self.update_redirect()
return redirect(self.get_redirect())
# @event_logger.log_this
# @expose("/list/")
# @has_access
# def list(self):
# self.base_list()
# widgets = self._list()
# res = self.render_template(
# self.list_template, title=self.list_title, widgets=widgets
# )
# return res
@action(
"muldelete", __("Delete"), __("Delete all Really?"), "fa-trash", single=False
)
def muldelete(self, items):
self.base_muldelete(items)
for item in items:
if item:
self._delete(item.id)
self.update_redirect()
return redirect(self.get_redirect())
class Workflow_Filter(MyappFilter):
# @pysnooper.snoop()
def apply(self, query, func):
user_roles = [role.name.lower() for role in list(self.get_user_roles())]
if "admin" in user_roles:
return query.order_by(self.model.create_time.desc())
return query.filter(
or_(
self.model.labels.contains('"%s"'%g.user.username),
)
).order_by(self.model.create_time.desc())
# list正在运行的workflow
class Workflow_ModelView_Base(Crd_ModelView_Base):
2021-08-17 17:00:34 +08:00
2022-08-11 10:47:08 +08:00
base_filters = [["id", Workflow_Filter, lambda: []]]
2021-08-17 17:00:34 +08:00
# 删除之前的 workflow和相关容器
# @pysnooper.snoop()
2021-08-17 17:00:34 +08:00
def delete_workflow(self, workflow):
try:
k8s_client = py_k8s.K8s(workflow.pipeline.project.cluster.get('KUBECONFIG',''))
2021-08-17 17:00:34 +08:00
k8s_client.delete_workflow(
all_crd_info=conf.get("CRD_INFO", {}),
namespace=workflow.namespace,
run_id=json.loads(workflow.labels).get("run-id",'')
)
workflow.status='Deleted'
2021-09-07 18:09:47 +08:00
workflow.change_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
2021-08-17 17:00:34 +08:00
db.session.commit()
except Exception as e:
print(e)
@expose("/stop/<crd_id>")
def stop(self, crd_id):
workflow = db.session.query(self.datamodel.obj).filter_by(id=crd_id).first()
self.delete_workflow(workflow)
2022-09-11 11:29:29 +08:00
flash('清理完成','success')
url = conf.get('MODEL_URLS',{}).get('workflow','')
return redirect(url)
2021-08-17 17:00:34 +08:00
label_title = '运行实例'
datamodel = SQLAInterface(Workflow)
2021-11-25 18:07:40 +08:00
list_columns = ['project','pipeline_url', 'create_time','change_time','elapsed_time', 'final_status','status', 'username', 'log','stop']
2022-08-18 15:17:44 +08:00
search_columns = ['status','labels','name','annotations','spec','status_more','username','create_time']
cols_width = {
"project": {"type": "ellip2", "width": 200},
"pipeline_url": {"type": "ellip2", "width": 400},
"create_time": {"type": "ellip2", "width": 200},
"change_time": {"type": "ellip2", "width": 200}
}
2021-11-25 18:07:40 +08:00
show_columns = ['name', 'namespace', 'create_time', 'status','task_status', 'annotations_html', 'labels_html', 'spec_html','status_more_html', 'info_json_html']
2021-08-17 17:00:34 +08:00
crd_name = 'workflow'
class Workflow_ModelView(Workflow_ModelView_Base,MyappModelView,DeleteMixin):
datamodel = SQLAInterface(Workflow)
2021-08-17 17:00:34 +08:00
2022-08-28 20:24:10 +08:00
appbuilder.add_view_no_menu(Workflow_ModelView)
2021-08-17 17:00:34 +08:00
# 添加api
class Workflow_ModelView_Api(Workflow_ModelView_Base,MyappModelRestApi):
2021-08-17 17:00:34 +08:00
datamodel = SQLAInterface(Workflow)
route_base = '/workflow_modelview/api'
appbuilder.add_api(Workflow_ModelView_Api)
2022-02-26 22:36:57 +08:00
#
#
# # list正在运行的tfjob
# class Tfjob_ModelView(Crd_ModelView_Base,MyappModelView,DeleteMixin):
# label_title = 'tf分布式任务'
# datamodel = SQLAInterface(Tfjob)
# crd_name = 'tfjob'
# list_columns = ['name','pipeline_url','run_instance','namespace_url','create_time','status','username','stop']
#
#
# appbuilder.add_view(Tfjob_ModelView,"TFjob",href="/tfjob_modelview/list/?_flt_2_name=",icon = 'fa-tasks',category = '训练')
# # 添加api
# class Tfjob_ModelView_Api(Crd_ModelView_Base,MyappModelRestApi):
# label_title = 'tf分布式任务'
# datamodel = SQLAInterface(Tfjob)
# route_base = '/tfjob_modelview/api'
# crd_name = 'tfjob'
#
# appbuilder.add_api(Tfjob_ModelView_Api)
#
#
# # list正在运行的xgb
# class Xgbjob_ModelView(Crd_ModelView_Base,MyappModelView,DeleteMixin):
# label_title = 'xgb分布式任务'
# datamodel = SQLAInterface(Xgbjob)
# crd_name = 'xgbjob'
#
# appbuilder.add_view(Xgbjob_ModelView,"XGBjob",href="/xgbjob_modelview/list/?_flt_2_name=",icon = 'fa-tasks',category = '训练')
#
#
# # 添加api
# class Xgbjob_ModelView_Api(Crd_ModelView_Base,MyappModelRestApi):
# label_title = 'xgb分布式任务'
# datamodel = SQLAInterface(Xgbjob)
# route_base = '/xgbjob_modelview/api'
# crd_name = 'xgbjob'
#
# appbuilder.add_api(Xgbjob_ModelView_Api)
#
#
# # list正在运行的pytorch
# class Pytorchjob_ModelView(Crd_ModelView_Base,MyappModelView,DeleteMixin):
# label_title = 'pytorch分布式任务'
# datamodel = SQLAInterface(Pytorchjob)
# crd_name = 'pytorchjob'
#
# appbuilder.add_view(Pytorchjob_ModelView,"Pytorchjob",href="/pytorchjob_modelview/list/?_flt_2_name=",icon = 'fa-tasks',category = '训练')
#
#
# # 添加api
# class Pytorchjob_ModelView_Api(Crd_ModelView_Base,MyappModelRestApi):
# label_title = 'pytorch分布式任务'
# datamodel = SQLAInterface(Pytorchjob)
# route_base = '/pytorchjob_modelview/api'
# crd_name = 'pytorchjob'
#
# appbuilder.add_api(Pytorchjob_ModelView_Api)
2021-08-17 17:00:34 +08:00