diff --git a/.gitignore b/.gitignore index 3774bbbdde2d0837ee7736d9305e05289cfe45fa..3acbf3080e3ce185b73fb3f29791944198064583 100644 --- a/.gitignore +++ b/.gitignore @@ -1,24 +1,4 @@ -# Byte-compiled / optimized / DLL files -# */__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# development project config -.pydevproject .idea -*.swp -.DS_Store - -logs - +dist .temp -.pytest_cache - -rpmbuild -build - -app.ini -/tests/data.py +*.pyc diff --git a/app.ini b/app.ini new file mode 100644 index 0000000000000000000000000000000000000000..babde4ae0496fa05c203ad984d9c337f95cd2a9f --- /dev/null +++ b/app.ini @@ -0,0 +1,3 @@ +[DEFAULT] +env = dev +#env = prod \ No newline at end of file diff --git a/app/__init__.py b/app/__init__.py index 6c3b97b16bd3282981a09175d8936570c2ef617f..24c2d0e5682d2a643f98bf030a1d97a9dbc8086b 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -44,11 +44,11 @@ prompt_info = """ │ ▄██ ████ ██▄ │ tsn: {tsn}│ │ ██ │ mode: {mode}│ │ ██ │ proxy: {proxy}│ -│ ██ │ version: 1.1.0 │ +│ ██ │ version: 1.1.1 │ └──────────────────────┴────────────────────────────────────────────┘ """.format( port=str(CONFIG.APP_PORT).ljust(31), tsn=SERVICE_CONFIG.get('tsn').ljust(34), mode=SERVICE_CONFIG.get('mode').ljust(34), proxy=SERVICE_CONFIG.get('proxy').ljust(34) -) \ No newline at end of file +) diff --git a/app/api/views.py b/app/api/views.py index 789ea79780e2cebc00c1711b74769d764c09e6de..2d10d0e864e989e7ba3dcc92c699a51230dc30b0 100644 --- a/app/api/views.py +++ b/app/api/views.py @@ -29,6 +29,7 @@ async def task_view(request: Request) -> HTTPResponse: task: Task = Task(**request.json) if task.sync: res = task.execute() + Result(tid=task.tid).remove() return json( { 'SUCCESS': 'ok', diff --git a/conf/__init__.py b/conf/__init__.py index c95fa47c253f856ca6fd4e1c00d5aa3004565f3b..8b91d76ad46e28dd630293c48290a1ea7ffb4d35 100644 --- a/conf/__init__.py +++ b/conf/__init__.py @@ -26,9 +26,23 @@ def get_settings(app_env: Optional[str] = 'prod') -> Optional[BaseSettings]: settings = getattr(EnvEnum, app_env.upper()).value return settings +def mkdir_if_not_exist() -> None: + """创建系统所需目录""" + if not os.path.exists(CONFIG.BASE_DIR): + os.makedirs(CONFIG.BASE_DIR) + if not os.path.exists(CONFIG.BASE_DIR + '/conf'): + os.makedirs(CONFIG.BASE_DIR + '/conf') + if not os.path.exists(CONFIG.BASE_DIR + '/results'): + os.makedirs(CONFIG.BASE_DIR + '/results') + if not os.path.exists(CONFIG.BASE_DIR + '/scripts'): + os.makedirs(CONFIG.BASE_DIR + '/scripts') + if not os.path.isfile(CONFIG.BASE_DIR + '/conf/toneagent.config.yaml'): + with open(CONFIG.BASE_DIR + '/conf/toneagent.config.yaml', 'w') as f: + f.write(config_content) def get_service_config() -> dict: """获取service配置""" + mkdir_if_not_exist() yaml_path: Optional[str] = os.path.join(CONFIG.BASE_DIR, 'conf') with open(f'{yaml_path}/{CONFIG.AGENT_CONFIG_FILE_NAME}', 'r', encoding="utf-8") as f: data = yaml.load(f, Loader=yaml.FullLoader) @@ -42,5 +56,11 @@ try: except configparser.NoOptionError: env = 'prod' +config_content = """ +tsn: tone20000101-0001 +mode: active +proxy: https://tone-agent.openanolis.cn +""" + CONFIG: Optional[BaseSettings] = get_settings(env) SERVICE_CONFIG: Optional[dict] = get_service_config() diff --git a/conf/dev.py b/conf/dev.py index 8afebb42d19cff3c139acd96b38727f9147eddf5..73974d13087fd6421a08d1c57865f2eaa39ec6fe 100644 --- a/conf/dev.py +++ b/conf/dev.py @@ -9,8 +9,7 @@ class Settings(BaseSettings): # app DEBUG = True SECRET_KEY: str = "*5}nAn#4GyQVO'*qq_2AAOC\\fXsvi9;m0.-Q|#jAcS" - # BASE_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), '.temp') - BASE_DIR = '/Users/foo/tone/gitee/toneagent/.temp' + BASE_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), '.temp') WORKS_NUM = 1 APP_PORT = 8000 diff --git a/core/common/request.py b/core/common/request.py index 3dc02c6dfe71b4467ada5e95c74021bb536e25af..ad488089a3c5b8ec4987ecc1fe3258431f1913e3 100644 --- a/core/common/request.py +++ b/core/common/request.py @@ -35,9 +35,9 @@ def request_to_proxy(api: str, method: str, data: dict = None) -> Optional[dict] data: dict = _set_sign_param(data) try: if method.lower() == 'get': - res: Response = requests.get(api, params=data) + res: Response = requests.get(api, params=data, verify=False) else: - res: Response = requests.post(api, json=data) + res: Response = requests.post(api, json=data, verify=False) return res.json() except Exception as e: logger.error(f'request to proxy error: {api} | {data} | {traceback.format_exc()}') diff --git a/core/result.py b/core/result.py index c26533c1b8ea61d073d2486f2816f9e9db04e1a9..d8108d94cdc67cc0ee00e4ca696401e545c7e176 100644 --- a/core/result.py +++ b/core/result.py @@ -84,7 +84,7 @@ class Result(BaseObject): res: dict = request_to_proxy(link, 'post', data=data) success = res.get('SUCCESS') == 'ok' if success: - if self.status == TaskStatus.COMPLETED: + if data.get('status') == TaskStatus.COMPLETED: self.remove() else: logger.error(f'sync result to proxy failed: {self.tid} | {res}') diff --git a/core/task.py b/core/task.py index ba08263a07664645e11bb4052934e9cbed2cb88a..2f9d92f34c44342977e4bf026f4c1e3358a76327 100644 --- a/core/task.py +++ b/core/task.py @@ -1,6 +1,7 @@ # coding: utf-8 import base64 +import os import subprocess from threading import Timer from typing import Optional @@ -38,7 +39,7 @@ class Task(BaseObject): link: str = get_api_link(CONFIG.AGENT_PULL_TASK_API) data: dict = {'tsn': SERVICE_CONFIG.get('tsn')} res: dict = request_to_proxy(link, 'post', data=data) - if not res['SUCCESS']: + if not res['SUCCESS'] or res['SUCCESS'] == 'False': logger.error(f'pull task failed. result: {res}') return dict() return res['TASKS'] @@ -98,8 +99,11 @@ class Task(BaseObject): exit_code=str(p.returncode), finish_time=get_present_time() ).update() - - return Result(tid=self.tid).read() + os.remove(self.script_file) + try: + return Result(tid=self.tid).read() + except FileNotFoundError: + pass def kill(self, p: subprocess.Popen) -> None: """ diff --git a/main.py b/main.py index 9b8b3d9f6ec5de77af3c8f86c33a4955539a3188..e932683a61ca4e9bcdb53e880a9fba0baed9d59d 100644 --- a/main.py +++ b/main.py @@ -1,7 +1,8 @@ -# # coding: utf-8 - -import os +# coding: utf-8 +import urllib3 from sanic import Sanic +from urllib3.exceptions import InsecureRequestWarning + from app import init_app, prompt_info from core.common.enum import AgentMode @@ -9,20 +10,20 @@ from core.common.log import logger from conf import SERVICE_CONFIG from core.scheduler import run_scheduler_forever, run_by_threaded +# 忽略InsecureRequestWarning警告 +urllib3.disable_warnings(InsecureRequestWarning) def main(): app: Sanic = init_app() - logger.info(prompt_info) - if SERVICE_CONFIG.get('mode') == AgentMode.ACTIVE: run_by_threaded(run_scheduler_forever) - app.run( host='0.0.0.0', port=app.config.get('APP_PORT'), - workers=app.config.get('WORKS_NUM'), - auto_reload=True + # workers=app.config.get('WORKS_NUM'), + # auto_reload=True, + single_process=True ) diff --git a/toneagent-loongarch64.spec b/toneagent-loongarch64.spec new file mode 100644 index 0000000000000000000000000000000000000000..f4efaae6371cce74491fa9081aa794f0844394a1 --- /dev/null +++ b/toneagent-loongarch64.spec @@ -0,0 +1,64 @@ +%define name toneagent +%define version 1.1.1 +%define app_path /usr/local/toneagent +%define python_bin python3.10 +%define release 1 +# Resolve python conflicts +%define _build_id_links none + +Summary: toneagent +Name: %{name} +Version: %{version} +Release: %{release} +License: MulanPSLv2 +Group: Development/Libraries +Prefix: %{_prefix} +#BuildArch: noarch +Source: %{name}-%{version}.tar.gz +BuildRoot: %{_tmppath}/%{name}-%{version}-build +Vendor: foo +Url: https://gitee.com/anolis/python-tone-agent + +%description +ToneAgent[python] service + +%prep +%setup -q -n %{name}-%{version} + +%build +%define debug_package %{nil} + +%install +mkdir -p ${RPM_BUILD_ROOT}%{app_path}/{app,conf,logs,results,scripts,venv} +mkdir -p ${RPM_BUILD_ROOT}/usr/lib/systemd/system/ +cp -rf %{_builddir}/%{name}-%{version}/* ${RPM_BUILD_ROOT}%{app_path}/app/ +cp -f %{_builddir}/%{name}-%{version}/%{name}.service ${RPM_BUILD_ROOT}/usr/lib/systemd/system/ + +#yum install -y gcc python39-devel +yum install -y python310 +pip3 install --upgrade virtualenv +virtualenv -p %{python_bin} --copies ${RPM_BUILD_ROOT}%{app_path}/venv +#virtualenv -p %{python_bin} ${RPM_BUILD_ROOT}%{app_path}/venv +${RPM_BUILD_ROOT}%{app_path}/venv/bin/pip3 install -r ${RPM_BUILD_ROOT}%{app_path}/app/requirements.txt -i https://mirrors.aliyun.com/pypi/simple/ + +cd ${RPM_BUILD_ROOT}%{app_path}/venv/bin && \ +rm -f activate activate.fish activate.ps1 normalizer pip3 pip3.10 wheel3 wheel3.10 && \ +rm -f activate.csh activate.nu activate_this.py pip pip-3.10 wheel wheel-3.10 sanic + +%post +systemctl daemon-reload +systemctl enable %{name}.service +systemctl start %{name}.service + +%postun +rm -rf /usr/lib/systemd/system/toneagent.service +rm -rf /usr/local/toneagent +systemctl daemon-reload + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root) +%{app_path} +%{_prefix}/lib/systemd/system/%{name}.service \ No newline at end of file diff --git a/toneagent.service b/toneagent.service new file mode 100644 index 0000000000000000000000000000000000000000..00752f48797742a426e0e29a84b65896a5bc0760 --- /dev/null +++ b/toneagent.service @@ -0,0 +1,15 @@ +[Unit] +Description=ToneAgent Service +After=network.target + +[Service] +Type=simple +ExecStart=/usr/local/toneagent/venv/bin/python3 /usr/local/toneagent/app/main.py +PIDFile=/run/toneagent.pid +KillSignal=SIGTERM +KillMode=process +Restart=on-failure + +[Install] +WantedBy=multi-user.target + diff --git a/toneagent.spec b/toneagent.spec new file mode 100644 index 0000000000000000000000000000000000000000..9a2aa73e2e16582e463e667babc0213ad9b5c7b2 --- /dev/null +++ b/toneagent.spec @@ -0,0 +1,65 @@ +%define name toneagent +%define version 1.1.1 +%define app_path /usr/local/toneagent +%define python_bin python3.9 +%define release 1 +# Resolve python conflicts +%define _build_id_links none + +Summary: toneagent +Name: %{name} +Version: %{version} +Release: %{release} +License: MulanPSLv2 +Group: Development/Libraries +Prefix: %{_prefix} +#BuildArch: noarch +Source: %{name}-%{version}.tar.gz +BuildRoot: %{_tmppath}/%{name}-%{version}-build +Vendor: foo +Url: https://gitee.com/anolis/python-tone-agent + +%description +ToneAgent[python] service + +%prep +%setup -q -n %{name}-%{version} + +%build +%define debug_package %{nil} + +%install +mkdir -p ${RPM_BUILD_ROOT}%{app_path}/{app,conf,logs,results,scripts,venv} +mkdir -p ${RPM_BUILD_ROOT}/usr/lib/systemd/system/ +cp -rf %{_builddir}/%{name}-%{version}/* ${RPM_BUILD_ROOT}%{app_path}/app/ +cp -f %{_builddir}/%{name}-%{version}/%{name}.service ${RPM_BUILD_ROOT}/usr/lib/systemd/system/ + +yum install -y gcc python39-devel +yum install -y python39 +pip3 install --upgrade pip setuptools virtualenv +virtualenv -p %{python_bin} --copies ${RPM_BUILD_ROOT}%{app_path}/venv +#virtualenv -p %{python_bin} ${RPM_BUILD_ROOT}%{app_path}/venv +${RPM_BUILD_ROOT}%{app_path}/venv/bin/pip3 install -r ${RPM_BUILD_ROOT}%{app_path}/app/requirements.txt -i https://mirrors.aliyun.com/pypi/simple/ + +cd ${RPM_BUILD_ROOT}%{app_path}/venv/bin && \ +rm -f activate activate.fish activate.ps1 normalizer pip3 pip3.9 wheel3 wheel3.9 && \ +rm -f activate.csh activate.nu activate_this.py pip pip-3.9 wheel wheel-3.9 sanic + +%post +systemctl daemon-reload +systemctl enable %{name}.service +systemctl start %{name}.service + +%postun +rm -rf /usr/lib/systemd/system/toneagent.service +rm -rf /usr/local/toneagent +systemctl daemon-reload + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root) +%{app_path} +#%attr(0755, root, root) {app_path}/venv/bin +%{_prefix}/lib/systemd/system/%{name}.service