diff --git a/sysom_server/sysom_diagnosis/apps/task/urls.py b/sysom_server/sysom_diagnosis/apps/task/urls.py index d11514072d5318d1464845e3875fe81e1a6382c4..c699561ae1b36fed1e0c6ce0c6d62b2b00e3c6e6 100644 --- a/sysom_server/sysom_diagnosis/apps/task/urls.py +++ b/sysom_server/sysom_diagnosis/apps/task/urls.py @@ -5,7 +5,7 @@ @Author : DM @Software: PyCharm """ -from django.urls import path, include, re_path +from django.urls import path, include from rest_framework.routers import DefaultRouter from apps.task import views @@ -17,6 +17,7 @@ urlpatterns = [ path('api/v1/tasks/task_hook/', views.TaskAPIView.as_view({'post': 'task_hook'})), path('api/v1/tasks/sbs_task_create/', views.TaskAPIView.as_view({'post': 'sbs_task_create'})), path('api/v1/tasks/sbs_task_result/', views.TaskAPIView.as_view({'post': 'sbs_task_result'})), + path('api/v1/tasks/sbs_task_result_by_tar/', views.TaskAPIView.as_view({'post': 'sbs_task_result_by_tar'})), path('api/v1/tasks/offline_import/', views.TaskAPIView.as_view({'post': 'offline_import'})), path('api/v1/tasks/health_check/', views.TaskAPIView.as_view({'get': 'health_check'})), path('api/v1/tasks/host/', views.TaskAPIView.as_view({'get': 'get_host'})), diff --git a/sysom_server/sysom_diagnosis/apps/task/views.py b/sysom_server/sysom_diagnosis/apps/task/views.py index 24a41429b1a7343afe54abae15af602b1a8e2009..a7120c4d286e2c162a6aedb4f04d64a360b9b728 100644 --- a/sysom_server/sysom_diagnosis/apps/task/views.py +++ b/sysom_server/sysom_diagnosis/apps/task/views.py @@ -2,6 +2,7 @@ import enum import base64 import requests import tempfile +import tarfile import os from clogger import logger from django_filters.rest_framework import DjangoFilterBackend @@ -240,6 +241,67 @@ class TaskAPIView( logger.exception(e) return ErrorResponse(msg=str(e)) + def sbs_task_result_by_tar(self, request, *args, **kwargs): + try: + # Step 1. Get required formdata params + obj_list = request.FILES.getlist("files") + task_id = request.data.get("task_id", None) + + # Step 2. Validate task id is exist and files list lengths le 0 + if len(obj_list) == 0: + return other_response(message=f"No result tar file", code=400) + + instance = JobModel.objects.get(task_id=task_id) + if instance is None: + return ErrorResponse(f"No such diagnosis task with id = {task_id}") + if instance.status not in ["Ready", "Running"]: + return ErrorResponse( + f"Target diganosis task is finished, current status = {instance.status}" + ) + + # Step 3. Processing uploaded compressed files in temporary folders + with tempfile.TemporaryDirectory() as t: + results_list = [] + for item in obj_list: + temp_tar_gz_dir = os.path.join(t, item.name) + with open(temp_tar_gz_dir, 'wb') as f: + for chunk in item.chunks(): + f.write(chunk) + + # Step 3.1 Decompress the compressed package and retrieve the content of the 'stdout' result file + with tarfile.open(temp_tar_gz_dir, mode='r:gz') as tar_ref: + file_name = f'./{instance.params.get("instance")}/stdout' + try: + tar_info = tar_ref.getmember(file_name) + f = tar_ref.extractfile(tar_info) + if f is not None: + stdout = f.read().decode('utf-8') + results_list.append(stdout) + except KeyError: + logger.exception(f'{file_name} is not found in the tar archive.') + + commands = instance.command.get("jobs", []) + # Step 3.2 Build diagnosis task result + job_result = DiagnosisTaskResult( + code=0, + job_results=[ + DiagnosisJobResult( + code=0, + stdout=result, + job=DiagnosisJob.from_dict(commands[idx]) + ) + for idx, result in enumerate(results_list) + ] + ) + + # Step 3.4 Invoke postprocess script + DiagnosisHelper.postprocess(instance, job_result) + response = seriaizer.JobRetrieveSerializer(instance) + return success(result=response.data) + except Exception as e: + logger.exception(e) + return ErrorResponse(msg=str(e)) + def task_hook(self, request, *args, **kwargs): """Invoke task hook diff --git a/sysom_server/sysom_diagnosis/service_scripts/wrapper/dummy.py b/sysom_server/sysom_diagnosis/service_scripts/wrapper/dummy.py index b309645f2e067ae88afcb85221489576c99b2072..47cb45a067742c410718b113117e1026c7a2cc91 100644 --- a/sysom_server/sysom_diagnosis/service_scripts/wrapper/dummy.py +++ b/sysom_server/sysom_diagnosis/service_scripts/wrapper/dummy.py @@ -1,12 +1,39 @@ +import time +from string import Template from service_scripts.base import DiagnosisTask from .base import DiagnosisPreProcessorPostWrapperBase + +CommandTmp = """\ +command -v tar >/dev/null 2>&1 && (\ +mkdir -p ./${instance} \ +&& ${resouce_cmd} | tee ./${instance}/stdout > /dev/null \ +&& tar -zcvf ${tar_package_name} ./${instance} > /dev/null\ +&& rm -rf ./${instance}\ +) \ +&& echo ""\ +&& echo "诊断结果已保存到 $(pwd)/${instance}, 可以通过以下方式回传结果:"\ +&& echo "1. 直接将 $(pwd)/${tar_package_name} 拷贝下来上传到中心端;" \ +|| echo "tar command not found"\ +""" + + class DiagnosisPreProcessorPostWrapper(DiagnosisPreProcessorPostWrapperBase): """所有命令的执行结果导出到临时文件并cat出来 Args: DiagnosisPreProcessorPostWrapperBase (_type_): _description_ """ + def __init__(self) -> None: + super().__init__() + self._cmd_tmp = Template(CommandTmp) + def process(self, task_id: str, diagnosis_task: DiagnosisTask): for job in diagnosis_task.jobs: - job.cmd = f"({job.cmd}) > /tmp/{job.instance}.txt && cat /tmp/{job.instance}.txt" \ No newline at end of file + resouce_cmd = f"({job.cmd}) > /tmp/{job.instance}.txt && cat /tmp/{job.instance}.txt" + tar_package_name = f'offline_{job.instance}_{int(time.time())}.tar.gz' + + job.cmd = self._cmd_tmp.safe_substitute( + instance=job.instance, resouce_cmd=resouce_cmd, + tar_package_name=tar_package_name + )