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/disk.py ADDED
@@ -0,0 +1,322 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ #
4
+ # Copyright (c) 2017-2026 Jackson Dou
5
+ # All rights reserved.
6
+ #
7
+ # InPanel is distributed under the terms of the (new) BSD License.
8
+ # The full license can be found in 'LICENSE'.
9
+
10
+ '''Module for disk Management'''
11
+
12
+ import os
13
+ from pathlib import Path
14
+ from shlex import split
15
+
16
+ import pexpect
17
+
18
+ from .config import readconfig, writeconfig
19
+ from . import server
20
+
21
+
22
+ def add(disk, size=''):
23
+ """Add a new partition on a disk.
24
+
25
+ If the size exceed the max available space the disk left, then the
26
+ new partition will be created with the left space.
27
+
28
+ A disk can have 4 partitions at max.
29
+
30
+ True will return if create successfully, or else False will return.
31
+
32
+ Example:
33
+ fdisk.add('/dev/sdb') # use all of the space
34
+ fdisk.add('/dev/sdb', '5G') # create a partition with at most 5G space
35
+ """
36
+ try:
37
+ cmd = split('fdisk \'%s\'' % disk)
38
+ except:
39
+ return False
40
+
41
+ child = pexpect.spawn(cmd[0], cmd[1:])
42
+ i = child.expect(['(m for help)', 'Unable to open'])
43
+ if i == 1:
44
+ if child.isalive():
45
+ child.wait()
46
+ return False
47
+
48
+ rt = True
49
+ partno_found = False
50
+ partno = 1
51
+ while not partno_found:
52
+ child.sendline('n')
53
+ i = child.expect(
54
+ ['primary partition', 'You must delete some partition'])
55
+ if i == 1:
56
+ break
57
+ child.sendline('p')
58
+
59
+ i = child.expect(['Partition number', 'Selected partition'])
60
+ if i == 0:
61
+ child.sendline('%d' % partno)
62
+
63
+ i = child.expect(['First cylinder', '(m for help)'])
64
+ if i == 0:
65
+ partno_found = True
66
+ partno += 1
67
+ if partno > 4:
68
+ break
69
+
70
+ if not partno_found:
71
+ rt = False
72
+
73
+ if rt:
74
+ child.sendline('')
75
+ child.expect('Last cylinder')
76
+ child.sendline('+%s' % size)
77
+ i = child.expect(
78
+ ['(m for help)', 'Value out of range', 'Last cylinder'])
79
+ if i == 1:
80
+ child.sendline('')
81
+ child.expect('(m for help)')
82
+ elif i == 2: # wrong size input
83
+ child.sendline('')
84
+ child.expect('(m for help)')
85
+ rt = False
86
+
87
+ if rt:
88
+ child.sendline('w')
89
+ else:
90
+ child.sendline('q')
91
+
92
+ if child.isalive():
93
+ child.wait()
94
+ return rt
95
+
96
+
97
+ def delete(partition):
98
+ """Delete a partition.
99
+
100
+ True will return if delete successfully, or else False will return.
101
+
102
+ Example:
103
+ fdisk.delete('/dev/sdb1')
104
+ """
105
+ disk = partition[:-1]
106
+ partno = partition[-1:]
107
+ try:
108
+ cmd = split('fdisk \'%s\'' % disk)
109
+ except:
110
+ return False
111
+
112
+ child = pexpect.spawn(cmd[0], cmd[1:])
113
+ i = child.expect(['(m for help)', 'Unable to open'])
114
+ if i == 1:
115
+ if child.isalive():
116
+ child.wait()
117
+ return False
118
+
119
+ child.sendline('d')
120
+
121
+ rt = True
122
+ i = child.expect([
123
+ 'Partition number',
124
+ 'Selected partition %s' % partno,
125
+ 'No partition is defined yet',
126
+ pexpect.TIMEOUT
127
+ ], timeout=1)
128
+ if i == 0:
129
+ child.sendline(partno)
130
+ elif i == 2 or i == 3:
131
+ rt = False
132
+
133
+ if rt:
134
+ i = child.expect(['(m for help)', 'has empty type'])
135
+ if i == 0:
136
+ child.sendline('w')
137
+ elif i == 1:
138
+ rt = False
139
+
140
+ if not rt:
141
+ child.sendline('q')
142
+
143
+ if child.isalive():
144
+ child.wait()
145
+ return rt
146
+
147
+
148
+ def scan(disk, size=''):
149
+ """Rescan partitions on a disk.
150
+
151
+ True will return if scan successfully, or else False will return.
152
+
153
+ Example:
154
+ fdisk.scan('/dev/sdb')
155
+ """
156
+ try:
157
+ cmd = split('fdisk \'%s\'' % disk)
158
+ except:
159
+ return False
160
+
161
+ child = pexpect.spawn(cmd[0], cmd[1:])
162
+ i = child.expect(['(m for help)', 'Unable to open'])
163
+ if i == 1:
164
+ child.wait()
165
+ return False
166
+
167
+ child.sendline('w')
168
+ i = child.expect([
169
+ 'The kernel still uses the old table',
170
+ pexpect.TIMEOUT,
171
+ pexpect.EOF
172
+ ], timeout=1)
173
+ if i == 0:
174
+ rt = False
175
+ else:
176
+ rt = True
177
+
178
+ if child.isalive():
179
+ child.wait()
180
+ return rt
181
+
182
+
183
+ def handle_fdisk(action, devname, size='', unit=''):
184
+ """Handle fdisk operations.
185
+
186
+ Args:
187
+ action: 'add', 'delete', or 'scan'
188
+ devname: device name (e.g., 'sdb')
189
+ size: partition size (e.g., '5')
190
+ unit: 'M' or 'G'
191
+
192
+ Returns:
193
+ dict with 'code' and 'msg' keys
194
+ """
195
+ if action == 'add':
196
+ if unit not in ('M', 'G'):
197
+ return {'code': -1, 'msg': '错误的分区大小!'}
198
+
199
+ if size == '':
200
+ size = None # use whole left space
201
+ else:
202
+ try:
203
+ size = float(size)
204
+ except:
205
+ return {'code': -1, 'msg': '错误的分区大小!'}
206
+
207
+ if unit == 'G' and size - int(size) > 0:
208
+ size *= 1024
209
+ unit = 'M'
210
+ size = '%d%s' % (round(size), unit)
211
+
212
+ if add('/dev/%s' % devname, size):
213
+ return {'code': 0, 'msg': '在 %s 设备上创建分区成功!' % devname}
214
+ else:
215
+ return {'code': -1, 'msg': '在 %s 设备上创建分区失败!' % devname}
216
+
217
+ elif action == 'delete':
218
+ if delete('/dev/%s' % devname):
219
+ fstab(devname, {'devname': devname, 'mount': None})
220
+ return {'code': 0, 'msg': '分区 %s 删除成功!' % devname}
221
+ else:
222
+ return {'code': -1, 'msg': '分区 %s 删除失败!' % devname}
223
+
224
+ elif action == 'scan':
225
+ if scan('/dev/%s' % devname):
226
+ return {'code': 0, 'msg': '扫描设备 %s 的分区成功!' % devname}
227
+ else:
228
+ return {'code': -1, 'msg': '扫描设备 %s 的分区失败!' % devname}
229
+
230
+ else:
231
+ return {'code': -1, 'msg': '未定义的操作!'}
232
+
233
+
234
+ def _read_fstab(line, **params):
235
+ """Read fstab config for a specific device.
236
+
237
+ Args:
238
+ line: a line from /etc/fstab
239
+ params: contains 'devname' parameter
240
+
241
+ Returns:
242
+ dict with config or None
243
+ """
244
+ if not line or line.startswith('#'):
245
+ return
246
+ fields = line.split()
247
+ dev = fields[0]
248
+ config = {
249
+ 'dev': fields[0],
250
+ 'mount': fields[1],
251
+ 'fstype': fields[2],
252
+ }
253
+ if dev.startswith('/dev/'):
254
+ try:
255
+ devlink = os.readlink(dev)
256
+ dev = str(Path(devlink).parent.joinpath(dev).resolve())
257
+ except:
258
+ pass
259
+ dev = dev.replace('/dev/', '')
260
+ if dev == params['devname']:
261
+ return config
262
+ elif dev.startswith('UUID='):
263
+ uuid = dev.replace('UUID=', '')
264
+ partinfo = server.ServerInfo.partinfo(devname=params['devname'])
265
+ if partinfo['uuid'] == uuid:
266
+ return config
267
+
268
+
269
+ def _write_fstab(line, **params):
270
+ """Write fstab config for a specific device.
271
+
272
+ Args:
273
+ line: a line from /etc/fstab (None for new line)
274
+ params: contains 'devname' and 'config' parameters
275
+
276
+ Returns:
277
+ formatted line string or None to remove
278
+ """
279
+ config = params['config']
280
+ if not 'mount' in config or config['mount'] is None:
281
+ return None # remove line
282
+ if line is None: # new line
283
+ return '/dev/%s %s %s defaults 1 2' % \
284
+ (params['devname'], config['mount'], config['fstype'])
285
+ else: # update existing line
286
+ fields = line.split()
287
+ return '%s %s %s %s %s %s' % \
288
+ (fields[0], config['mount'],
289
+ 'fstype' in config and config['fstype'] or fields[2],
290
+ fields[3], fields[4], fields[5])
291
+
292
+
293
+ def fstab(devname, config=None):
294
+ """Read or write config from /etc/fstab.
295
+
296
+ Args:
297
+ devname: device name (e.g., 'sda1')
298
+ config: None for read, dict for write/remove
299
+
300
+ Returns:
301
+ config dict on read, boolean on write
302
+ """
303
+ cfgfile = '/etc/fstab'
304
+ if config is None:
305
+ # read config
306
+ return readconfig(cfgfile, _read_fstab, devname=devname)
307
+ else:
308
+ # write or remove config
309
+ return writeconfig(cfgfile, _read_fstab, _write_fstab,
310
+ devname=devname, config=config)
311
+
312
+
313
+ if __name__ == '__main__':
314
+ # !!!!!!!!!!! DANGEROUS TESTING !!!!!!!!!!!
315
+ # print('* Add partition to sdb with 5G:',)
316
+ # print(add('/dev/sdb', '5G'))
317
+
318
+ # print('* Delete partition /dev/sdb1:')
319
+ # print(delete('/dev/sdb1'))
320
+
321
+ print('* Rescan partitions of /dev/sdb:')
322
+ print(scan('/dev/sdb'))
inpanel/mod/dnf.py ADDED
@@ -0,0 +1,239 @@
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 Repository Management'''
9
+
10
+ import os
11
+ from pathlib import Path
12
+
13
+ from .. import base
14
+ from . import config
15
+ from . import file
16
+ from ..dnf import dnf_reporpms
17
+
18
+ config_path = '/etc/yum.repos.d'
19
+
20
+
21
+ def get_list():
22
+ '''get repo list'''
23
+ res = []
24
+ if base.kernel_name in ('Linux'):
25
+ d = str(Path(config_path))
26
+ if not Path(d).exists() or not Path(d).is_dir():
27
+ return None
28
+ items = sorted(os.listdir(d))
29
+ return items if len(items) > 0 else []
30
+ elif base.kernel_name in ('Darwin'):
31
+ return None
32
+ else:
33
+ return None
34
+
35
+
36
+ def item_exists(repo):
37
+ '''exists'''
38
+ return Path(str(Path(config_path) / repo)).exists()
39
+
40
+
41
+ def get_item(repo):
42
+ '''get repo config'''
43
+ if not repo:
44
+ return None
45
+ repo_file = str(Path(config_path) / repo)
46
+ if Path(repo_file).exists():
47
+ _config = config.Config(repo_file)
48
+ return _config.get_config()
49
+ return None
50
+
51
+
52
+ def set_item(repo, data):
53
+ '''set repo config'''
54
+ if not repo:
55
+ return None
56
+ if not data:
57
+ return None
58
+ repo_file = str(Path(config_path) / repo)
59
+ if Path(repo_file).exists():
60
+ _config = config.Config(repo_file, data)
61
+ return True
62
+ else:
63
+ return False
64
+
65
+
66
+ def add_item(repo, data):
67
+ '''add repo config'''
68
+ if not repo:
69
+ return None
70
+ if not data:
71
+ return None
72
+ repo_file = str(Path(config_path) / repo)
73
+ if Path(repo_file).exists():
74
+ return False
75
+ else:
76
+ _config = config.Config(repo_file, data)
77
+ return True
78
+
79
+
80
+ def del_item(repo):
81
+ '''delete repo file'''
82
+ if not repo:
83
+ return None
84
+ repo_file = str(Path(config_path) / repo)
85
+ return file.delete(repo_file)
86
+
87
+
88
+ def get_repo_release(os_versint, os_name, arch):
89
+ '''install release'''
90
+ cmds = []
91
+ if os_versint >= 8:
92
+ if os_name in ('centos', 'almalinux', 'rocky', 'rhel', 'fedora'):
93
+ cmds.append('dnf install -y %s-release' % os_name)
94
+ else:
95
+ for rpm in dnf_reporpms['base'][os_versint][arch]:
96
+ cmds.append('rpm -U %s' % rpm)
97
+ return cmds
98
+
99
+
100
+ def get_repo_epel(os_versint, os_name, arch):
101
+ '''install epel'''
102
+ cmds = []
103
+ if os_versint >= 8:
104
+ cmds.append('dnf install -y epel-release')
105
+ else:
106
+ for rpm in dnf_reporpms['epel'][os_versint][arch]:
107
+ cmds.append('rpm -U %s' % rpm)
108
+ return cmds
109
+
110
+
111
+ def get_repo_powertools(os_versint, os_name, arch):
112
+ '''install powertools/crb'''
113
+ cmds = []
114
+ if os_versint == 8:
115
+ cmds.append('dnf install -y dnf-plugins-core')
116
+ cmds.append('dnf config-manager --set-enabled powertools')
117
+ elif os_versint >= 9:
118
+ cmds.append('dnf install -y dnf-plugins-core')
119
+ cmds.append('dnf config-manager --set-enabled crb')
120
+ return cmds
121
+
122
+
123
+ def get_repo_remi(os_versint, os_name, arch):
124
+ '''install remi repository'''
125
+ cmds = []
126
+ if os_versint >= 8:
127
+ cmds.append('dnf install -y https://rpms.remirepo.net/enterprise/remi-release-%d.rpm' % os_versint)
128
+ return cmds
129
+
130
+
131
+ def web_handler(context):
132
+ '''Handle web requests for DNF repository management'''
133
+ action = context.get('action', '')
134
+ repo = context.get('repo', '')
135
+
136
+ if action == 'list':
137
+ items = get_list()
138
+ if items is None:
139
+ return {'code': -1, 'msg': '获取配置失败!'}
140
+ else:
141
+ return {'code': 0, 'msg': '', 'data': items}
142
+
143
+ elif action == 'item':
144
+ if not repo:
145
+ return {'code': -1, 'msg': '配置文件不能为空!'}
146
+ data = get_item(repo)
147
+ if data is None:
148
+ return {'code': -1, 'msg': '配置文件不存在!'}
149
+ else:
150
+ return {'code': 0, 'msg': '', 'data': data}
151
+
152
+ elif action == 'add':
153
+ if not repo:
154
+ return {'code': -1, 'msg': '配置文件不能为空!'}
155
+ serverid = context.get('serverid', '')
156
+ if not serverid:
157
+ return {'code': -1, 'msg': '仓库标识ID不能为空!'}
158
+ name = context.get('name', '')
159
+ if not name:
160
+ return {'code': -1, 'msg': '仓库名称不能为空!'}
161
+ baseurl = context.get('baseurl', '')
162
+ if not baseurl:
163
+ return {'code': -1, 'msg': '仓库路径不能为空!'}
164
+
165
+ enabled = context.get('enabled', True)
166
+ gpgcheck = context.get('gpgcheck', False)
167
+
168
+ data = {
169
+ serverid: {
170
+ 'name': name,
171
+ 'enabled': 0 if not enabled else 1,
172
+ 'baseurl': baseurl,
173
+ 'gpgcheck': 0 if not gpgcheck else 1,
174
+ 'gpgkey': ''
175
+ }
176
+ }
177
+
178
+ if item_exists(repo):
179
+ return {'code': -1, 'msg': '配置文件已存在!'}
180
+ if add_item(repo, data) is True:
181
+ return {'code': 0, 'msg': '配置添加成功!'}
182
+ else:
183
+ return {'code': -1, 'msg': '配置添加失败!'}
184
+
185
+ elif action == 'edit':
186
+ if not repo:
187
+ return {'code': -1, 'msg': '配置文件不能为空!'}
188
+ serverid = context.get('serverid', '')
189
+ if not serverid:
190
+ return {'code': -1, 'msg': '仓库标识ID不能为空!'}
191
+ name = context.get('name', '')
192
+ if not name:
193
+ return {'code': -1, 'msg': '仓库名称不能为空!'}
194
+ baseurl = context.get('baseurl', '')
195
+ if not baseurl:
196
+ return {'code': -1, 'msg': '仓库路径不能为空!'}
197
+
198
+ enabled = context.get('enabled', True)
199
+ gpgcheck = context.get('gpgcheck', False)
200
+
201
+ data = {
202
+ serverid: {
203
+ 'name': name,
204
+ 'enabled': 0 if not enabled else 1,
205
+ 'baseurl': baseurl,
206
+ 'gpgcheck': 0 if not gpgcheck else 1,
207
+ 'gpgkey': ''
208
+ }
209
+ }
210
+
211
+ if not item_exists(repo):
212
+ return {'code': -1, 'msg': '配置文件不存在!'}
213
+ if set_item(repo, data) is True:
214
+ return {'code': 0, 'msg': '配置修改成功!'}
215
+ else:
216
+ return {'code': -1, 'msg': '配置修改失败!'}
217
+
218
+ elif action == 'del':
219
+ if not repo:
220
+ return {'code': -1, 'msg': '配置文件不能为空!'}
221
+ if not item_exists(repo):
222
+ return {'code': -1, 'msg': '配置文件不存在!'}
223
+ if del_item(repo) is True:
224
+ return {'code': 0, 'msg': '配置文件已移入回收站!'}
225
+ else:
226
+ return {'code': -1, 'msg': '删除失败!'}
227
+
228
+ else:
229
+ return {'code': -1, 'msg': '未定义的操作!'}
230
+
231
+
232
+ if __name__ == '__main__':
233
+ l = get_list()
234
+ print(l)
235
+ if l:
236
+ i = l[0]
237
+ print(i)
238
+ c = get_item(i)
239
+ print(c)