InPanel 1.2.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) hide show
  1. inpanel/__init__.py +29 -0
  2. inpanel/acme.py +289 -0
  3. inpanel/aliyuncs.py +269 -0
  4. inpanel/app.py +514 -0
  5. inpanel/apt.py +223 -0
  6. inpanel/base.py +200 -0
  7. inpanel/config.py +139 -0
  8. inpanel/data/config.ini +29 -0
  9. inpanel/data/history +5 -0
  10. inpanel/data/runlogs.ini +12 -0
  11. inpanel/data/update_info.ini +4 -0
  12. inpanel/dnf.py +225 -0
  13. inpanel/lib/__init__.py +9 -0
  14. inpanel/lib/async_process.py +98 -0
  15. inpanel/lib/filelock.py +82 -0
  16. inpanel/lib/magic.py +233 -0
  17. inpanel/lib/pxssh.py +310 -0
  18. inpanel/lib/pyDes.py +867 -0
  19. inpanel/mod/__init__.py +0 -0
  20. inpanel/mod/apt.py +316 -0
  21. inpanel/mod/certificate.py +268 -0
  22. inpanel/mod/config.py +372 -0
  23. inpanel/mod/cron.py +315 -0
  24. inpanel/mod/disk.py +322 -0
  25. inpanel/mod/dnf.py +239 -0
  26. inpanel/mod/file.py +722 -0
  27. inpanel/mod/firewall.py +199 -0
  28. inpanel/mod/firewall_base.py +137 -0
  29. inpanel/mod/firewall_firewalld.py +170 -0
  30. inpanel/mod/firewall_iptables.py +176 -0
  31. inpanel/mod/firewall_macos.py +213 -0
  32. inpanel/mod/firewall_ufw.py +128 -0
  33. inpanel/mod/ftp.py +231 -0
  34. inpanel/mod/httpd.py +1205 -0
  35. inpanel/mod/lighttpd.py +26 -0
  36. inpanel/mod/login.py +98 -0
  37. inpanel/mod/mysql.py +577 -0
  38. inpanel/mod/named.py +26 -0
  39. inpanel/mod/nginx.py +2327 -0
  40. inpanel/mod/package.py +33 -0
  41. inpanel/mod/package_apt.py +62 -0
  42. inpanel/mod/package_base.py +77 -0
  43. inpanel/mod/package_dnf.py +62 -0
  44. inpanel/mod/package_map.py +366 -0
  45. inpanel/mod/package_yum.py +64 -0
  46. inpanel/mod/php.py +289 -0
  47. inpanel/mod/process.py +291 -0
  48. inpanel/mod/proftpd.py +26 -0
  49. inpanel/mod/pureftpd.py +26 -0
  50. inpanel/mod/query.py +108 -0
  51. inpanel/mod/server.py +1319 -0
  52. inpanel/mod/service.py +262 -0
  53. inpanel/mod/setting.py +228 -0
  54. inpanel/mod/shell.py +78 -0
  55. inpanel/mod/ssh.py +280 -0
  56. inpanel/mod/system.py +220 -0
  57. inpanel/mod/task.py +1337 -0
  58. inpanel/mod/ufw.py +14 -0
  59. inpanel/mod/user.py +306 -0
  60. inpanel/mod/vsftpd.py +67 -0
  61. inpanel/mod/yum.py +243 -0
  62. inpanel/plugins/__init__.py +10 -0
  63. inpanel/plugins/__pycache__/__init__.cpython-313.pyc +0 -0
  64. inpanel/plugins/acme/static/index.html +10 -0
  65. inpanel/plugins/acme/static/index.js +13 -0
  66. inpanel/plugins/shadowsocks-libev/__pycache__/info.cpython-313.pyc +0 -0
  67. inpanel/plugins/shadowsocks-libev/info.py +73 -0
  68. inpanel/plugins/shadowsocks-libev/static/index.html +70 -0
  69. inpanel/plugins/shadowsocks-libev/static/index.js +18 -0
  70. inpanel/public/css/global.css +138 -0
  71. inpanel/public/favicon.ico +0 -0
  72. inpanel/public/images/alipay.jpg +0 -0
  73. inpanel/public/images/loading.gif +0 -0
  74. inpanel/public/images/weixin.jpg +0 -0
  75. inpanel/public/index.html +94 -0
  76. inpanel/public/js/controllers/controllers.js +566 -0
  77. inpanel/public/js/controllers/database.js +590 -0
  78. inpanel/public/js/controllers/ecs.js +624 -0
  79. inpanel/public/js/controllers/file.js +940 -0
  80. inpanel/public/js/controllers/plugins.js +105 -0
  81. inpanel/public/js/controllers/service.js +1460 -0
  82. inpanel/public/js/controllers/site.js +1241 -0
  83. inpanel/public/js/controllers/utils.js +2319 -0
  84. inpanel/public/js/core.js +221 -0
  85. inpanel/public/js/directives.js +784 -0
  86. inpanel/public/js/filters.js +395 -0
  87. inpanel/public/js/services.js +257 -0
  88. inpanel/public/lib/angular/1.0.2/angular-resource.min.js +10 -0
  89. inpanel/public/lib/angular/1.0.2/angular.min.js +158 -0
  90. inpanel/public/lib/bootstrap/css/bootstrap-theme.css +587 -0
  91. inpanel/public/lib/bootstrap/css/bootstrap-theme.css.map +1 -0
  92. inpanel/public/lib/bootstrap/css/bootstrap-theme.min.css +6 -0
  93. inpanel/public/lib/bootstrap/css/bootstrap-theme.min.css.map +1 -0
  94. inpanel/public/lib/bootstrap/css/bootstrap.css +6757 -0
  95. inpanel/public/lib/bootstrap/css/bootstrap.css.map +1 -0
  96. inpanel/public/lib/bootstrap/css/bootstrap.min.css +6 -0
  97. inpanel/public/lib/bootstrap/css/bootstrap.min.css.map +1 -0
  98. inpanel/public/lib/bootstrap/fonts/glyphicons-halflings-regular.eot +0 -0
  99. inpanel/public/lib/bootstrap/fonts/glyphicons-halflings-regular.svg +288 -0
  100. inpanel/public/lib/bootstrap/fonts/glyphicons-halflings-regular.ttf +0 -0
  101. inpanel/public/lib/bootstrap/fonts/glyphicons-halflings-regular.woff +0 -0
  102. inpanel/public/lib/bootstrap/fonts/glyphicons-halflings-regular.woff2 +0 -0
  103. inpanel/public/lib/bootstrap/img/glyphicons-halflings-white.png +0 -0
  104. inpanel/public/lib/bootstrap/img/glyphicons-halflings.png +0 -0
  105. inpanel/public/lib/bootstrap/js/bootstrap.js +2377 -0
  106. inpanel/public/lib/bootstrap/js/bootstrap.min.js +7 -0
  107. inpanel/public/lib/bootstrap/js/npm.js +13 -0
  108. inpanel/public/lib/codemirror/codemirror-compressed.js +1 -0
  109. inpanel/public/lib/codemirror/codemirror.css +173 -0
  110. inpanel/public/lib/jquery/jquery-1.12.4.min.js +5 -0
  111. inpanel/public/lib/md5/md5.js +379 -0
  112. inpanel/public/lib/md5/md5.min.js +1 -0
  113. inpanel/public/partials/database/index.html +172 -0
  114. inpanel/public/partials/database/mysql/dbedit.html +462 -0
  115. inpanel/public/partials/database/mysql/dbnew.html +348 -0
  116. inpanel/public/partials/database/mysql/useredit.html +310 -0
  117. inpanel/public/partials/database/mysql/usernew.html +97 -0
  118. inpanel/public/partials/directives/message.html +20 -0
  119. inpanel/public/partials/directives/navbar.html +25 -0
  120. inpanel/public/partials/directives/selector.html +57 -0
  121. inpanel/public/partials/directives/srvbase.html +72 -0
  122. inpanel/public/partials/directives/srvext.html +34 -0
  123. inpanel/public/partials/directives/srvfile.html +23 -0
  124. inpanel/public/partials/directives/srvinstall.html +34 -0
  125. inpanel/public/partials/directives/srvlog.html +23 -0
  126. inpanel/public/partials/directives/srvminiop.html +28 -0
  127. inpanel/public/partials/directives/srvuninstall.html +38 -0
  128. inpanel/public/partials/directives/srvupdate.html +30 -0
  129. inpanel/public/partials/ecs/account.html +156 -0
  130. inpanel/public/partials/ecs/ecs.html +198 -0
  131. inpanel/public/partials/ecs/index.html +40 -0
  132. inpanel/public/partials/ecs/setings.html +459 -0
  133. inpanel/public/partials/file/file.html +501 -0
  134. inpanel/public/partials/file/trash.html +95 -0
  135. inpanel/public/partials/ftp.html +36 -0
  136. inpanel/public/partials/log.html +83 -0
  137. inpanel/public/partials/login.html +79 -0
  138. inpanel/public/partials/logout.html +22 -0
  139. inpanel/public/partials/main.html +534 -0
  140. inpanel/public/partials/plugins/index.html +55 -0
  141. inpanel/public/partials/plugins/plugins.html +13 -0
  142. inpanel/public/partials/secure.html +13 -0
  143. inpanel/public/partials/service/apache.html +147 -0
  144. inpanel/public/partials/service/cron.html +71 -0
  145. inpanel/public/partials/service/index.html +293 -0
  146. inpanel/public/partials/service/iptables.html +40 -0
  147. inpanel/public/partials/service/lighttpd.html +63 -0
  148. inpanel/public/partials/service/mariadb.html +113 -0
  149. inpanel/public/partials/service/memcache.html +36 -0
  150. inpanel/public/partials/service/minio.html +44 -0
  151. inpanel/public/partials/service/mongodb.html +44 -0
  152. inpanel/public/partials/service/mysql.html +113 -0
  153. inpanel/public/partials/service/named.html +61 -0
  154. inpanel/public/partials/service/nginx.html +296 -0
  155. inpanel/public/partials/service/ntp.html +40 -0
  156. inpanel/public/partials/service/php.html +250 -0
  157. inpanel/public/partials/service/proftpd.html +59 -0
  158. inpanel/public/partials/service/pureftpd.html +59 -0
  159. inpanel/public/partials/service/redis.html +40 -0
  160. inpanel/public/partials/service/samba.html +58 -0
  161. inpanel/public/partials/service/sendmail.html +40 -0
  162. inpanel/public/partials/service/ssh.html +186 -0
  163. inpanel/public/partials/service/tomcat.html +65 -0
  164. inpanel/public/partials/service/vsftpd.html +195 -0
  165. inpanel/public/partials/setting.html +299 -0
  166. inpanel/public/partials/site/apache/site.html +277 -0
  167. inpanel/public/partials/site/index.html +344 -0
  168. inpanel/public/partials/site/nginx/site.html +558 -0
  169. inpanel/public/partials/sorry.html +19 -0
  170. inpanel/public/partials/storage/autofm.html +103 -0
  171. inpanel/public/partials/storage/backup.html +42 -0
  172. inpanel/public/partials/storage/index.html +360 -0
  173. inpanel/public/partials/storage/migrate.html +93 -0
  174. inpanel/public/partials/storage/movedata.html +98 -0
  175. inpanel/public/partials/storage/remote.html +77 -0
  176. inpanel/public/partials/utils/cron.html +486 -0
  177. inpanel/public/partials/utils/firewall.html +266 -0
  178. inpanel/public/partials/utils/index.html +193 -0
  179. inpanel/public/partials/utils/network.html +118 -0
  180. inpanel/public/partials/utils/process.html +239 -0
  181. inpanel/public/partials/utils/repository.html +373 -0
  182. inpanel/public/partials/utils/shell.html +28 -0
  183. inpanel/public/partials/utils/ssl.html +319 -0
  184. inpanel/public/partials/utils/time.html +109 -0
  185. inpanel/public/partials/utils/user.html +359 -0
  186. inpanel/public/robots.txt +2 -0
  187. inpanel/remote.py +109 -0
  188. inpanel/templates/file/preview.html +34 -0
  189. inpanel/templates/index.html +93 -0
  190. inpanel/utils.py +282 -0
  191. inpanel/web.py +1811 -0
  192. inpanel/yum.py +756 -0
  193. inpanel-1.2.1.dist-info/METADATA +399 -0
  194. inpanel-1.2.1.dist-info/RECORD +198 -0
  195. inpanel-1.2.1.dist-info/WHEEL +5 -0
  196. inpanel-1.2.1.dist-info/entry_points.txt +2 -0
  197. inpanel-1.2.1.dist-info/licenses/LICENSE +30 -0
  198. inpanel-1.2.1.dist-info/top_level.txt +1 -0
inpanel/mod/package.py ADDED
@@ -0,0 +1,33 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (c) 2020-2026 Jackson Dou
4
+ # All rights reserved.
5
+ #
6
+ # InPanel is distributed under the terms of The New BSD License.
7
+ # The full license can be found in 'LICENSE'.
8
+ '''Module for Package Manager Integration'''
9
+
10
+ from typing import Optional
11
+
12
+ from .package_base import PackageManager
13
+ from .package_yum import YumPM
14
+ from .package_dnf import DnfPM
15
+ from .package_apt import AptPM
16
+ from .package_map import (
17
+ PACKAGE_MAP,
18
+ resolve_package_names,
19
+ is_installed,
20
+ install_if_not_exists,
21
+ parse_search_output,
22
+ parse_list_installed_output,
23
+ parse_info_output
24
+ )
25
+
26
+
27
+ def get_package_manager() -> Optional[PackageManager]:
28
+ """工厂函数:根据系统返回对应的包管理器实例"""
29
+ managers = [DnfPM(), YumPM(), AptPM()]
30
+ for mgr in managers:
31
+ if mgr.detect():
32
+ return mgr
33
+ return None
@@ -0,0 +1,62 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (c) 2019-2026 Jackson Dou
4
+ # All rights reserved.
5
+ #
6
+ # InPanel is distributed under the terms of The New BSD License.
7
+ # The full license can be found in 'LICENSE'.
8
+
9
+ '''Module for APT(Advanced Packaging Tool) Management'''
10
+
11
+ import shutil
12
+ from typing import List, Tuple
13
+
14
+ from .package_base import PackageManager
15
+ from .system import is_debian_family
16
+
17
+
18
+ class AptPM(PackageManager):
19
+ """Debian 9-13 / Ubuntu 18.04+ / Linux Mint:apt"""
20
+
21
+ def detect(self) -> bool:
22
+ if not shutil.which("apt"):
23
+ return False
24
+ return is_debian_family()
25
+
26
+ def install(self, packages: List[str], assume_yes: bool = True) -> Tuple[bool, str]:
27
+ cmd = ["apt"]
28
+ if assume_yes:
29
+ cmd.append("-y")
30
+ cmd.extend(["install"] + packages)
31
+ return self._run_cmd(cmd)
32
+
33
+ def remove(self, packages: List[str], assume_yes: bool = True) -> Tuple[bool, str]:
34
+ cmd = ["apt"]
35
+ if assume_yes:
36
+ cmd.append("-y")
37
+ cmd.extend(["remove"] + packages)
38
+ return self._run_cmd(cmd)
39
+
40
+ def refresh(self) -> Tuple[bool, str]:
41
+ return self._run_cmd(["apt", "update"])
42
+
43
+ def search(self, pattern: str) -> Tuple[bool, str]:
44
+ return self._run_cmd(["apt", "search", pattern])
45
+
46
+ def list_installed(self) -> Tuple[bool, str]:
47
+ return self._run_cmd(["dpkg", "-l"])
48
+
49
+ def update(self) -> Tuple[bool, str]:
50
+ return self._run_cmd(["apt", "-y", "upgrade"])
51
+
52
+ def upgrade(self) -> Tuple[bool, str]:
53
+ return self._run_cmd(["apt", "-y", "full-upgrade"])
54
+
55
+ def info(self, package: str) -> Tuple[bool, str]:
56
+ return self._run_cmd(["apt", "show", package])
57
+
58
+ def clean(self) -> Tuple[bool, str]:
59
+ return self._run_cmd(["apt", "clean"])
60
+
61
+ def get_os_type(self) -> str:
62
+ return "debian"
@@ -0,0 +1,77 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (c) 2020-2026 Jackson Dou
4
+ # All rights reserved.
5
+ #
6
+ # InPanel is distributed under the terms of The New BSD License.
7
+ # The full license can be found in 'LICENSE'.
8
+ '''Module for Package Manager Base Class'''
9
+
10
+ import subprocess
11
+ from abc import ABC, abstractmethod
12
+ from typing import List, Tuple
13
+
14
+ from .system import (
15
+ get_os_family,
16
+ get_os_id,
17
+ get_os_version_major,
18
+ is_rhel_family,
19
+ is_debian_family,
20
+ )
21
+
22
+
23
+ class PackageManager(ABC):
24
+ """包管理器抽象基类"""
25
+
26
+ @abstractmethod
27
+ def detect(self) -> bool:
28
+ """检测当前系统是否匹配该包管理器"""
29
+ pass
30
+
31
+ @abstractmethod
32
+ def install(self, packages: List[str], assume_yes: bool = True) -> Tuple[bool, str]:
33
+ """
34
+ 安装包
35
+ :param packages: 包名列表(内部统一用小写)
36
+ :param assume_yes: 是否自动确认(yum/dnf/apt 的 -y 参数)
37
+ :return: (成功?, 输出日志)
38
+ """
39
+ pass
40
+
41
+ @abstractmethod
42
+ def remove(self, packages: List[str], assume_yes: bool = True) -> Tuple[bool, str]:
43
+ """卸载包"""
44
+ pass
45
+
46
+ @abstractmethod
47
+ def refresh(self) -> Tuple[bool, str]:
48
+ """更新包缓存(apt update / yum makecache / dnf makecache)"""
49
+ pass
50
+
51
+ def search(self, pattern: str) -> Tuple[bool, str]:
52
+ """搜索包"""
53
+ return (False, "Not implemented")
54
+
55
+ def list_installed(self) -> Tuple[bool, str]:
56
+ """列出已安装包"""
57
+ return (False, "Not implemented")
58
+
59
+ def get_os_type(self) -> str:
60
+ """返回操作系统类型:rhel 或 debian"""
61
+ return get_os_family()
62
+
63
+ @staticmethod
64
+ def _run_cmd(cmd: List[str]) -> Tuple[bool, str]:
65
+ """执行 shell 命令并返回结果"""
66
+ try:
67
+ result = subprocess.run(
68
+ cmd,
69
+ stdout=subprocess.PIPE,
70
+ stderr=subprocess.PIPE,
71
+ text=True,
72
+ check=False
73
+ )
74
+ output = result.stdout + result.stderr
75
+ return (result.returncode == 0, output.strip())
76
+ except Exception as e:
77
+ return (False, str(e))
@@ -0,0 +1,62 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (c) 2020-2026 Jackson Dou
4
+ # All rights reserved.
5
+ #
6
+ # InPanel is distributed under the terms of The New BSD License.
7
+ # The full license can be found in 'LICENSE'.
8
+ '''Module for DNF Package Manager'''
9
+
10
+ import shutil
11
+ from typing import List, Tuple
12
+
13
+ from .package_yum import YumPM
14
+ from .system import get_os_id, get_os_version_major
15
+
16
+
17
+ class DnfPM(YumPM):
18
+ """Alma 8-10 / Rocky 8-10 / CentOS 8+ / RHEL 8+ / Fedora:dnf"""
19
+
20
+ def detect(self) -> bool:
21
+ if not shutil.which("dnf"):
22
+ return False
23
+ os_id = get_os_id()
24
+ if os_id == "fedora":
25
+ return True
26
+ version_major = get_os_version_major()
27
+ return version_major >= 8
28
+
29
+ def install(self, packages: List[str], assume_yes: bool = True) -> Tuple[bool, str]:
30
+ cmd = ["dnf"]
31
+ if assume_yes:
32
+ cmd.append("-y")
33
+ cmd.extend(["install"] + packages)
34
+ return self._run_cmd(cmd)
35
+
36
+ def remove(self, packages: List[str], assume_yes: bool = True) -> Tuple[bool, str]:
37
+ cmd = ["dnf"]
38
+ if assume_yes:
39
+ cmd.append("-y")
40
+ cmd.extend(["remove"] + packages)
41
+ return self._run_cmd(cmd)
42
+
43
+ def refresh(self) -> Tuple[bool, str]:
44
+ return self._run_cmd(["dnf", "makecache"])
45
+
46
+ def search(self, pattern: str) -> Tuple[bool, str]:
47
+ return self._run_cmd(["dnf", "search", pattern])
48
+
49
+ def list_installed(self) -> Tuple[bool, str]:
50
+ return self._run_cmd(["dnf", "list", "installed"])
51
+
52
+ def update(self) -> Tuple[bool, str]:
53
+ return self._run_cmd(["dnf", "-y", "update"])
54
+
55
+ def upgrade(self) -> Tuple[bool, str]:
56
+ return self._run_cmd(["dnf", "-y", "upgrade"])
57
+
58
+ def info(self, package: str) -> Tuple[bool, str]:
59
+ return self._run_cmd(["dnf", "info", package])
60
+
61
+ def clean(self) -> Tuple[bool, str]:
62
+ return self._run_cmd(["dnf", "clean", "all"])
@@ -0,0 +1,366 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (c) 2020-2026 Jackson Dou
4
+ # All rights reserved.
5
+ #
6
+ # InPanel is distributed under the terms of The New BSD License.
7
+ # The full license can be found in 'LICENSE'.
8
+ '''Module for Package Name Mapping'''
9
+
10
+ from typing import List, Tuple, Dict
11
+
12
+ PACKAGE_MAP = {
13
+ "nginx": {
14
+ "rhel": "nginx",
15
+ "debian": "nginx"
16
+ },
17
+ "mariadb": {
18
+ "rhel": "mariadb-server",
19
+ "debian": "mariadb-server"
20
+ },
21
+ "mysql": {
22
+ "rhel": "mariadb-server",
23
+ "debian": "default-mysql-server"
24
+ },
25
+ "mysql-community": {
26
+ "rhel": "mysql-community-server",
27
+ "debian": "mysql-server"
28
+ },
29
+ "php": {
30
+ "rhel": "php",
31
+ "debian": "php"
32
+ },
33
+ "php-fpm": {
34
+ "rhel": "php-fpm",
35
+ "debian": "php-fpm"
36
+ },
37
+ "php-cli": {
38
+ "rhel": "php-cli",
39
+ "debian": "php-cli"
40
+ },
41
+ "php-mysql": {
42
+ "rhel": "php-mysqlnd",
43
+ "debian": "php-mysql"
44
+ },
45
+ "php-pdo": {
46
+ "rhel": "php-pdo",
47
+ "debian": "php-pdo"
48
+ },
49
+ "php-mbstring": {
50
+ "rhel": "php-mbstring",
51
+ "debian": "php-mbstring"
52
+ },
53
+ "php-xml": {
54
+ "rhel": "php-xml",
55
+ "debian": "php-xml"
56
+ },
57
+ "php-gd": {
58
+ "rhel": "php-gd",
59
+ "debian": "php-gd"
60
+ },
61
+ "php-curl": {
62
+ "rhel": "php-curl",
63
+ "debian": "php-curl"
64
+ },
65
+ "php-zip": {
66
+ "rhel": "php-zip",
67
+ "debian": "php-zip"
68
+ },
69
+ "php-intl": {
70
+ "rhel": "php-intl",
71
+ "debian": "php-intl"
72
+ },
73
+ "php-redis": {
74
+ "rhel": "php-pecl-redis",
75
+ "debian": "php-redis"
76
+ },
77
+ "php-memcached": {
78
+ "rhel": "php-pecl-memcached",
79
+ "debian": "php-memcached"
80
+ },
81
+ "git": {
82
+ "rhel": "git",
83
+ "debian": "git"
84
+ },
85
+ "wget": {
86
+ "rhel": "wget",
87
+ "debian": "wget"
88
+ },
89
+ "curl": {
90
+ "rhel": "curl",
91
+ "debian": "curl"
92
+ },
93
+ "vim": {
94
+ "rhel": "vim-enhanced",
95
+ "debian": "vim"
96
+ },
97
+ "rsync": {
98
+ "rhel": "rsync",
99
+ "debian": "rsync"
100
+ },
101
+ "net-tools": {
102
+ "rhel": "net-tools",
103
+ "debian": "net-tools"
104
+ },
105
+ "epel-release": {
106
+ "rhel": "epel-release",
107
+ "debian": ""
108
+ },
109
+ "remi-release": {
110
+ "rhel": "remi-release",
111
+ "debian": ""
112
+ },
113
+ "sury-php": {
114
+ "rhel": "",
115
+ "debian": "ca-certificates apt-transport-https software-properties-common"
116
+ },
117
+ "python3": {
118
+ "rhel": "python3",
119
+ "debian": "python3"
120
+ },
121
+ "python3-pip": {
122
+ "rhel": "python3-pip",
123
+ "debian": "python3-pip"
124
+ },
125
+ "python3-devel": {
126
+ "rhel": "python3-devel",
127
+ "debian": "python3-dev"
128
+ },
129
+ "gcc": {
130
+ "rhel": "gcc",
131
+ "debian": "gcc"
132
+ },
133
+ "make": {
134
+ "rhel": "make",
135
+ "debian": "make"
136
+ },
137
+ "cmake": {
138
+ "rhel": "cmake",
139
+ "debian": "cmake"
140
+ },
141
+ "autoconf": {
142
+ "rhel": "autoconf",
143
+ "debian": "autoconf"
144
+ },
145
+ "automake": {
146
+ "rhel": "automake",
147
+ "debian": "automake"
148
+ },
149
+ "libtool": {
150
+ "rhel": "libtool",
151
+ "debian": "libtool"
152
+ },
153
+ "libxslt": {
154
+ "rhel": "libxslt-devel",
155
+ "debian": "libxslt1-dev"
156
+ },
157
+ "libxml2": {
158
+ "rhel": "libxml2-devel",
159
+ "debian": "libxml2-dev"
160
+ },
161
+ "libcurl": {
162
+ "rhel": "libcurl-devel",
163
+ "debian": "libcurl4-openssl-dev"
164
+ },
165
+ "openssl": {
166
+ "rhel": "openssl-devel",
167
+ "debian": "libssl-dev"
168
+ },
169
+ "zlib": {
170
+ "rhel": "zlib-devel",
171
+ "debian": "zlib1g-dev"
172
+ },
173
+ "bzip2": {
174
+ "rhel": "bzip2-devel",
175
+ "debian": "libbz2-dev"
176
+ },
177
+ "libpng": {
178
+ "rhel": "libpng-devel",
179
+ "debian": "libpng-dev"
180
+ },
181
+ "libjpeg": {
182
+ "rhel": "libjpeg-turbo-devel",
183
+ "debian": "libjpeg-dev"
184
+ },
185
+ "freetype": {
186
+ "rhel": "freetype-devel",
187
+ "debian": "libfreetype6-dev"
188
+ },
189
+ "GeoIP": {
190
+ "rhel": "GeoIP-devel",
191
+ "debian": "libgeoip-dev"
192
+ },
193
+ "gd": {
194
+ "rhel": "gd-devel",
195
+ "debian": "libgd-dev"
196
+ },
197
+ "icu": {
198
+ "rhel": "icu-devel",
199
+ "debian": "libicu-dev"
200
+ },
201
+ "sqlite": {
202
+ "rhel": "sqlite-devel",
203
+ "debian": "libsqlite3-dev"
204
+ },
205
+ "postgresql": {
206
+ "rhel": "postgresql-server",
207
+ "debian": "postgresql"
208
+ },
209
+ "mongodb": {
210
+ "rhel": "mongodb-server",
211
+ "debian": "mongodb"
212
+ },
213
+ "redis": {
214
+ "rhel": "redis",
215
+ "debian": "redis-server"
216
+ },
217
+ "memcached": {
218
+ "rhel": "memcached",
219
+ "debian": "memcached"
220
+ },
221
+ "nodejs": {
222
+ "rhel": "nodejs",
223
+ "debian": "nodejs"
224
+ },
225
+ "npm": {
226
+ "rhel": "npm",
227
+ "debian": "npm"
228
+ },
229
+ "certbot": {
230
+ "rhel": "certbot",
231
+ "debian": "certbot"
232
+ },
233
+ "fail2ban": {
234
+ "rhel": "fail2ban",
235
+ "debian": "fail2ban"
236
+ },
237
+ "htop": {
238
+ "rhel": "htop",
239
+ "debian": "htop"
240
+ },
241
+ "ncdu": {
242
+ "rhel": "ncdu",
243
+ "debian": "ncdu"
244
+ },
245
+ "screen": {
246
+ "rhel": "screen",
247
+ "debian": "screen"
248
+ },
249
+ "tmux": {
250
+ "rhel": "tmux",
251
+ "debian": "tmux"
252
+ },
253
+ "ntp": {
254
+ "rhel": "chrony",
255
+ "debian": "chrony"
256
+ },
257
+ "firewalld": {
258
+ "rhel": "firewalld",
259
+ "debian": "ufw"
260
+ },
261
+ "iptables": {
262
+ "rhel": "iptables-services",
263
+ "debian": "iptables"
264
+ },
265
+ "logrotate": {
266
+ "rhel": "logrotate",
267
+ "debian": "logrotate"
268
+ },
269
+ "cron": {
270
+ "rhel": "cronie",
271
+ "debian": "cron"
272
+ },
273
+ "openssh": {
274
+ "rhel": "openssh-server",
275
+ "debian": "openssh-server"
276
+ },
277
+ "sshd": {
278
+ "rhel": "openssh-server",
279
+ "debian": "openssh-server"
280
+ }
281
+ }
282
+
283
+
284
+ def resolve_package_names(pm, base_names: List[str]) -> List[str]:
285
+ """根据包管理器类型解析实际包名"""
286
+ os_type = pm.get_os_type()
287
+ resolved = []
288
+ for name in base_names:
289
+ if name in PACKAGE_MAP and os_type in PACKAGE_MAP[name]:
290
+ pkg_name = PACKAGE_MAP[name][os_type]
291
+ if pkg_name:
292
+ resolved.append(pkg_name)
293
+ else:
294
+ resolved.append(name)
295
+ return resolved
296
+
297
+
298
+ def is_installed(pm, package: str) -> bool:
299
+ """检查包是否已安装"""
300
+ success, output = pm.list_installed()
301
+ if not success:
302
+ return False
303
+ package = package.lower()
304
+ for line in output.split('\n'):
305
+ if package in line.lower():
306
+ return True
307
+ return False
308
+
309
+
310
+ def install_if_not_exists(pm, packages: List[str]) -> Tuple[bool, str]:
311
+ """只安装未安装的包"""
312
+ resolved = resolve_package_names(pm, packages)
313
+ to_install = []
314
+ for pkg in resolved:
315
+ if not is_installed(pm, pkg):
316
+ to_install.append(pkg)
317
+ if not to_install:
318
+ return (True, "All packages already installed")
319
+ return pm.install(to_install)
320
+
321
+
322
+ def parse_search_output(output: str) -> List[Dict]:
323
+ """解析搜索命令输出,返回包列表"""
324
+ packages = []
325
+ lines = output.split('\n')
326
+ for line in lines:
327
+ if not line.strip():
328
+ continue
329
+ parts = line.split()
330
+ if len(parts) >= 2:
331
+ pkg_name = parts[0]
332
+ description = ' '.join(parts[1:]) if len(parts) > 1 else ''
333
+ packages.append({'name': pkg_name, 'description': description})
334
+ return packages
335
+
336
+
337
+ def parse_list_installed_output(output: str) -> List[Dict]:
338
+ """解析已安装包列表输出"""
339
+ packages = []
340
+ lines = output.split('\n')
341
+ for line in lines:
342
+ if not line.strip():
343
+ continue
344
+ if line.startswith('Desired=') or line.startswith('+++') or line.startswith('ii ') or line.startswith('Installed'):
345
+ parts = line.split()
346
+ if len(parts) >= 2:
347
+ if line.startswith('ii '):
348
+ pkg_name = parts[1]
349
+ version = parts[2] if len(parts) > 2 else ''
350
+ elif line.startswith('Installed'):
351
+ continue
352
+ else:
353
+ continue
354
+ packages.append({'name': pkg_name, 'version': version})
355
+ return packages
356
+
357
+
358
+ def parse_info_output(output: str) -> dict:
359
+ """解析包信息输出"""
360
+ info = {}
361
+ lines = output.split('\n')
362
+ for line in lines:
363
+ if ':' in line:
364
+ key, value = line.split(':', 1)
365
+ info[key.strip()] = value.strip()
366
+ return info
@@ -0,0 +1,64 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (c) 2020-2026 Jackson Dou
4
+ # All rights reserved.
5
+ #
6
+ # InPanel is distributed under the terms of The New BSD License.
7
+ # The full license can be found in 'LICENSE'.
8
+ '''Module for YUM Package Manager'''
9
+
10
+ import shutil
11
+ from typing import List, Tuple
12
+
13
+ from .package_base import PackageManager
14
+ from .system import is_rhel_family, get_os_version_major
15
+
16
+
17
+ class YumPM(PackageManager):
18
+ """CentOS 7 及以下 / RHEL 7 及以下:yum"""
19
+
20
+ def detect(self) -> bool:
21
+ if not shutil.which("yum"):
22
+ return False
23
+ if not is_rhel_family():
24
+ return False
25
+ if shutil.which("dnf"):
26
+ version_major = get_os_version_major()
27
+ return version_major == 7
28
+ version_major = get_os_version_major()
29
+ return version_major in (5, 6, 7) or version_major == 0
30
+
31
+ def install(self, packages: List[str], assume_yes: bool = True) -> Tuple[bool, str]:
32
+ cmd = ["yum"]
33
+ if assume_yes:
34
+ cmd.append("-y")
35
+ cmd.extend(["install"] + packages)
36
+ return self._run_cmd(cmd)
37
+
38
+ def remove(self, packages: List[str], assume_yes: bool = True) -> Tuple[bool, str]:
39
+ cmd = ["yum"]
40
+ if assume_yes:
41
+ cmd.append("-y")
42
+ cmd.extend(["remove"] + packages)
43
+ return self._run_cmd(cmd)
44
+
45
+ def refresh(self) -> Tuple[bool, str]:
46
+ return self._run_cmd(["yum", "makecache"])
47
+
48
+ def search(self, pattern: str) -> Tuple[bool, str]:
49
+ return self._run_cmd(["yum", "search", pattern])
50
+
51
+ def list_installed(self) -> Tuple[bool, str]:
52
+ return self._run_cmd(["yum", "list", "installed"])
53
+
54
+ def update(self) -> Tuple[bool, str]:
55
+ return self._run_cmd(["yum", "-y", "update"])
56
+
57
+ def upgrade(self) -> Tuple[bool, str]:
58
+ return self._run_cmd(["yum", "-y", "upgrade"])
59
+
60
+ def info(self, package: str) -> Tuple[bool, str]:
61
+ return self._run_cmd(["yum", "info", package])
62
+
63
+ def clean(self) -> Tuple[bool, str]:
64
+ return self._run_cmd(["yum", "clean", "all"])