update to 6.8.37

This commit is contained in:
zhw
2024-04-29 15:35:04 +08:00
parent fa9a865beb
commit ed34994f45
474 changed files with 125711 additions and 34665 deletions
+337
View File
@@ -0,0 +1,337 @@
#coding: utf-8
#-------------------------------------------------------------------
# 宝塔Linux面板
#-------------------------------------------------------------------
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
#-------------------------------------------------------------------
# Author: zouhw <zhw@bt.cn>
#-------------------------------------------------------------------
#------------------------------
# Docker模型
#------------------------------
import public #line:13
import os #line:14
import time #line:15
import projectModel .bt_docker .dk_public as dp #line:16
import projectModel .bt_docker .dk_container as dc #line:17
import projectModel .bt_docker .dk_setup as ds #line:18
import json #line:19
class main :#line:22
compose_path ="{}/data/compose".format (public .get_panel_path ())#line:23
__O00OO0OO00O0OO000 ="/tmp/dockertmp.log"#line:24
def check_conf (O0OO0OO00OO0OOO00 ,O0OOOOOOO00O00O00 ):#line:27
OOO0OOO0OOO0000O0 ="/usr/bin/docker-compose -f {} config".format (O0OOOOOOO00O00O00 )#line:28
O0O0000OOOO0O0O0O ,OOOO00O0O00OOO0O0 =public .ExecShell (OOO0OOO0OOO0000O0 )#line:29
if OOOO00O0O00OOO0O0 :#line:30
return public .return_msg_gettext (False ,"Check failed:{}".format (OOOO00O0O00OOO0O0 ))#line:31
return public .return_msg_gettext (True ,"Passed!")#line:32
def add_template_gui (O0O0OOOOOOO00O000 ,O0000O0O0O0O00O00 ):#line:35
""#line:69
import yaml #line:70
O000000OOO0O00OO0 ="{}/template".format (O0O0OOOOOOO00O000 .compose_path )#line:71
O0O00000OO000OO0O ="{}/{}.yaml".format (O000000OOO0O00OO0 ,O0000O0O0O0O00O00 .name )#line:72
if not os .path .exists (O000000OOO0O00OO0 ):#line:73
os .makedirs (O000000OOO0O00OO0 )#line:74
O000O0O000O0OOOO0 =json .loads (O0000O0O0O0O00O00 .data )#line:75
yaml .dump (O000O0O000O0OOOO0 ,O0O00000OO000OO0O )#line:76
def get_template_kw (O0OOO0OO0OOO0000O ,OO00OO000OOOOOOOO ):#line:78
O0OO0OO0O00O0OO0O ={"version":"","services":{"server_name_str":{"build":{"context":"str","dockerfile":"str","args":[],"cache_from":[],"labels":[],"network":"str","shm_size":"str","target":"str"},"cap_add":"","cap_drop":"","cgroup_parent":"str","command":"str","configs":{"my_config_str":[]},"container_name":"str","credential_spec":{"file":"str","registry":"str"},"depends_on":[],"deploy":{"endpoint_mode":"str","labels":{"key":"value"},"mode":"str","placement":[{"key":"value"}],"max_replicas_per_node":"int","replicas":"int","resources":{"limits":{"cpus":"str","memory":"str",},"reservations":{"cpus":"str","memory":"str",},"restart_policy":{"condition":"str","delay":"str","max_attempts":"int","window":"str"}}}}}}#line:134
def add_template (OO0O00000000O00OO ,O00OOOOOO0O0O0000 ):#line:137
""#line:145
OO00O0OO0O0O0000O =OO0O00000000O00OO .template_list (O00OOOOOO0O0O0000 )['msg']['template']#line:146
for O0O00O000OO000OO0 in OO00O0OO0O0O0000O :#line:147
if O00OOOOOO0O0O0000 .name ==O0O00O000OO000OO0 ['name']:#line:148
return public .return_msg_gettext (False ,"This template name already exists!")#line:149
OO0OOOOO0OO0O0OOO ="{}/{}/template".format (OO0O00000000O00OO .compose_path ,O00OOOOOO0O0O0000 .name )#line:150
O00OOO00O0O0O0OOO ="{}/{}.yaml".format (OO0OOOOO0OO0O0OOO ,O00OOOOOO0O0O0000 .name )#line:151
if not os .path .exists (OO0OOOOO0OO0O0OOO ):#line:152
os .makedirs (OO0OOOOO0OO0O0OOO )#line:153
public .writeFile (O00OOO00O0O0O0OOO ,O00OOOOOO0O0O0000 .data )#line:154
OOO0000O000O0OO00 =OO0O00000000O00OO .check_conf (O00OOO00O0O0O0OOO )#line:155
if not OOO0000O000O0OO00 ['status']:#line:156
if os .path .exists (O00OOO00O0O0O0OOO ):#line:157
os .remove (O00OOO00O0O0O0OOO )#line:158
return OOO0000O000O0OO00 #line:160
O0O0OO0O00OO00OO0 ={"name":O00OOOOOO0O0O0000 .name ,"remark":O00OOOOOO0O0O0000 .remark ,"path":O00OOO00O0O0O0OOO }#line:165
dp .sql ("templates").insert (O0O0OO0O00OO00OO0 )#line:166
dp .write_log ("Add template [{}] successful!".format (O00OOOOOO0O0O0000 .name ))#line:167
return public .return_msg_gettext (True ,"Template added successfully!")#line:169
def edit_template (OOOO00O0OOOOO0O00 ,O00O0O0O000O0O000 ):#line:171
""#line:178
O0O00OOO00OOOO00O =dp .sql ("templates").where ("id=?",(O00O0O0O000O0O000 .id ,)).find ()#line:179
if not O0O00OOO00OOOO00O :#line:180
return public .return_msg_gettext (False ,"This template was not found!")#line:181
public .writeFile (O0O00OOO00OOOO00O ['path'],O00O0O0O000O0O000 .data )#line:182
O0OOOO0O0000OOO0O =OOOO00O0OOOOO0O00 .check_conf (O0O00OOO00OOOO00O ['path'])#line:183
if not O0OOOO0O0000OOO0O ['status']:#line:184
return O0OOOO0O0000OOO0O #line:185
OOOOO0OO00OOO000O ={"name":O0O00OOO00OOOO00O ['name'],"remark":O00O0O0O000O0O000 .remark ,"path":O0O00OOO00OOOO00O ['path']}#line:190
dp .sql ("templates").where ("id=?",(O00O0O0O000O0O000 .id ,)).update (OOOOO0OO00OOO000O )#line:191
dp .write_log ("Editing template [{}] succeeded!".format (O0O00OOO00OOOO00O ['name']))#line:192
return public .return_msg_gettext (True ,"Modify the template successfully!")#line:193
def get_template (O0O000OO00O0OO0O0 ,O0OOOO00O00O00OO0 ):#line:195
""#line:200
OOO0OO0OO0OO0000O =dp .sql ("templates").where ("id=?",(O0OOOO00O00O00OO0 .id ,)).find ()#line:201
if not OOO0OO0OO0OO0000O :#line:202
return public .return_msg_gettext (False ,"This template was not found!")#line:203
return public .return_msg_gettext (True ,public .readFile (OOO0OO0OO0OO0000O ['path']))#line:204
def template_list (OOO00OO000O0OOO0O ,O00O0O00OOO00O000 ):#line:206
""#line:211
import projectModel .bt_docker .dk_setup as ds #line:212
OOOO0OO00OOOO0O0O =ds .main ()#line:213
OOO0OO00OO0OO0O0O =dp .sql ("templates").select ()[::-1 ]#line:214
if not isinstance (OOO0OO00OO0OO0O0O ,list ):#line:215
OOO0OO00OO0OO0O0O =[]#line:216
OOOO0O000OO0OO0O0 ={"template":OOO0OO00OO0OO0O0O ,"installed":OOOO0OO00OOOO0O0O .check_docker_program (),"service_status":OOOO0OO00OOOO0O0O .get_service_status ()}#line:221
return public .return_msg_gettext (True ,OOOO0O000OO0OO0O0 )#line:222
def remove_template (O0O0O0OOOOO0O000O ,OO0OO0OO00O000OOO ):#line:224
""#line:230
O00OO00O0OOO0000O =dp .sql ("templates").where ("id=?",(OO0OO0OO00O000OOO .template_id ,)).find ()#line:231
if not O00OO00O0OOO0000O :#line:232
return public .return_msg_gettext (False ,"This template was not found!")#line:233
if os .path .exists (O00OO00O0OOO0000O ['path']):#line:234
os .remove (O00OO00O0OOO0000O ['path'])#line:235
dp .sql ("templates").delete (id =OO0OO0OO00O000OOO .template_id )#line:236
dp .write_log ("Delete template [{}] successful!".format (O00OO00O0OOO0000O ['name']))#line:237
return public .return_msg_gettext (True ,"Successfully deleted!")#line:238
def edit_project_remark (OOO0O0000OO000000 ,OO00000OO000OOOO0 ):#line:240
""#line:247
O0OOOOOO000OOO0OO =dp .sql ("stacks").where ("id=?",(OO00000OO000OOOO0 .project_id ,)).find ()#line:248
if not O0OOOOOO000OOO0OO :#line:249
return public .return_msg_gettext (False ,"The item was not found!")#line:250
OO0OOO00OO0OOO000 ={"remark":OO00000OO000OOOO0 .remark }#line:253
dp .write_log ("Modify the item[{}] remarks [{}] to [{}] success!".format (O0OOOOOO000OOO0OO ['name'],O0OOOOOO000OOO0OO ['remark'],OO00000OO000OOOO0 .remark ))#line:254
dp .sql ("stacks").where ("id=?",(OO00000OO000OOOO0 .project_id ,)).update (OO0OOO00OO0OOO000 )#line:255
def edit_template_remark (O000000OOOOO0O000 ,OOOO0OOOO0O0O0OO0 ):#line:257
""#line:264
OO0OO00OOOOO0OO00 =dp .sql ("templates").where ("id=?",(OOOO0OOOO0O0O0OO0 .templates_id ,)).find ()#line:265
if not OO0OO00OOOOO0OO00 :#line:266
return public .return_msg_gettext (False ,"The template was not found!")#line:267
OO0O0O0OO0OOOOOOO ={"remark":OOOO0OOOO0O0O0OO0 .remark }#line:270
dp .write_log ("Modify the template [{}] remarks [{}] to [{}] successful!".format (OO0OO00OOOOO0OO00 ['name'],OO0OO00OOOOO0OO00 ['remark'],OOOO0OOOO0O0O0OO0 .remark ))#line:271
dp .sql ("templates").where ("id=?",(OOOO0OOOO0O0O0OO0 .templates_id ,)).update (OO0O0O0OO0OOOOOOO )#line:272
def create_project_in_path (OO00000O0000O0O00 ,O0OO0OOOO0000OO00 ,O000O0O0O0OO00000 ):#line:274
OO000OO000O0O00O0 ="cd {} && /usr/bin/docker-compose -p {} up -d &> {}".format ("/".join (O000O0O0O0OO00000 .split ("/")[:-1 ]),O0OO0OOOO0000OO00 ,OO00000O0000O0O00 .__O00OO0OO00O0OO000 )#line:275
public .ExecShell (OO000OO000O0O00O0 )#line:276
def create_project_in_file (O00OO0O0OO0OO00OO ,O0O0O0O00O000000O ,O00000O0OOOO0OOOO ):#line:278
O0000OO0O0O000OO0 ="{}/{}".format (O00OO0O0OO0OO00OO .compose_path ,O0O0O0O00O000000O )#line:279
O000OO00OOOOO00OO ="{}/docker-compose.yaml".format (O0000OO0O0O000OO0 )#line:280
if not os .path .exists (O0000OO0O0O000OO0 ):#line:281
os .makedirs (O0000OO0O0O000OO0 )#line:282
O00OOO000O000O000 =public .readFile (O00000O0OOOO0OOOO )#line:283
public .writeFile (O000OO00OOOOO00OO ,O00OOO000O000O000 )#line:284
O000O0OOOO0OO0O0O ="/usr/bin/docker-compose -p {} -f {} up -d &> {}".format (O0O0O0O00O000000O ,O000OO00OOOOO00OO ,O00OO0O0OO0OO00OO .__O00OO0OO00O0OO000 )#line:285
public .ExecShell (O000O0OOOO0OO0O0O )#line:286
def check_project_container_name (OOOO00OO0OOOOO0OO ,OO0OOOO0O00OO0OO0 ,OOO0OO00OO0OO00OO ):#line:288
""#line:292
import re #line:293
import projectModel .bt_docker .dk_container as dc #line:294
OO00OOOOO0O0OOOOO =[]#line:295
O0OOOO000O00OOO0O =re .findall ("container_name\s*:\s*[\"\']+(.*)[\'\"]",OO0OOOO0O00OO0OO0 )#line:296
O0O0OO0O00OOO0O00 =dc .main ().get_list (OOO0OO00OO0OO00OO )#line:297
if not O0O0OO0O00OOO0O00 ["status"]:#line:298
return public .return_msg_gettext (False ,"Error getting container list!")#line:299
O0O0OO0O00OOO0O00 =O0O0OO0O00OOO0O00 ['msg']['container_list']#line:300
for O0OOO0O0OO0O0OO00 in O0O0OO0O00OOO0O00 :#line:301
if O0OOO0O0OO0O0OO00 ['name']in O0OOOO000O00OOO0O :#line:302
OO00OOOOO0O0OOOOO .append (O0OOO0O0OO0O0OO00 ['name'])#line:303
if OO00OOOOO0O0OOOOO :#line:304
return public .return_msg_gettext (False ,"The container name in the template: <br>[{}] already exists!".format (", ".join (OO00OOOOO0O0OOOOO )))#line:305
OO0000O0OO00OO0O0 ="(\d+):\d+"#line:307
O00O00OOOO0OO00O0 =re .findall (OO0000O0OO00OO0O0 ,OO0OOOO0O00OO0OO0 )#line:308
for O0OOO00O00O0OOOOO in O00O00OOOO0OO00O0 :#line:309
if dp .check_socket (O0OOO00O00O0OOOOO ):#line:310
return public .return_msg_gettext (False ,"The port [{}] in the template is already in use, please modify the server port in the template!".format (O0OOO00O00O0OOOOO ))#line:311
def create (OO0O00O0OO00O0OO0 ,O0O0O0O00OO0OOOO0 ):#line:314
""#line:321
OOO00OO0O00OOOO0O =public .md5 (O0O0O0O00OO0OOOO0 .project_name )#line:322
OO000O00O00O0000O =dp .sql ("templates").where ("id=?",(O0O0O0O00OO0OOOO0 .template_id ,)).find ()#line:323
if not os .path .exists (OO000O00O00O0000O ['path']):#line:324
return public .return_msg_gettext (False ,"Template file not found")#line:325
O00O0OOOOO0OO0OOO =OO0O00O0OO00O0OO0 .check_project_container_name (public .readFile (OO000O00O00O0000O ['path']),O0O0O0O00OO0OOOO0 )#line:326
if O00O0OOOOO0OO0OOO :#line:327
return O00O0OOOOO0OO0OOO #line:328
O000000O0000OOOOO =dp .sql ("stacks").where ("name=?",(OOO00OO0O00OOOO0O )).find ()#line:329
if not O000000O0000OOOOO :#line:330
O0OOO0OOO0O0OO0OO ={"name":O0O0O0O00OO0OOOO0 .project_name ,"status":"1","path":OO000O00O00O0000O ['path'],"template_id":O0O0O0O00OO0OOOO0 .template_id ,"time":time .time (),"remark":O0O0O0O00OO0OOOO0 .remark }#line:338
dp .sql ("stacks").insert (O0OOO0OOO0O0OO0OO )#line:339
else :#line:340
return public .return_msg_gettext (False ,"This project name already exists!")#line:341
if OO000O00O00O0000O ['add_in_path']==1 :#line:342
OO0O00O0OO00O0OO0 .create_project_in_path (OOO00OO0O00OOOO0O ,OO000O00O00O0000O ['path'])#line:346
else :#line:347
OO0O00O0OO00O0OO0 .create_project_in_file (OOO00OO0O00OOOO0O ,OO000O00O00O0000O ['path'])#line:351
dp .write_log ("Project [{}] is successfully deployed!".format (OOO00OO0O00OOOO0O ))#line:352
return public .return_msg_gettext (True ,"Deployment succeeded!")#line:354
def compose_project_list (OOOOOO0OO00O0OO0O ,OO0O0000O00O0O000 ):#line:370
""#line:373
OO0O0000O00O0O000 .url ="unix:///var/run/docker.sock"#line:374
O0O000O0000OOO000 =dc .main ().get_list (OO0O0000O00O0O000 )#line:375
if not O0O000O0000OOO000 ['status']:#line:376
return public .return_msg_gettext (False ,"Failed to get the container, maybe the docker service is not started!")#line:377
if not O0O000O0000OOO000 ['msg']['service_status']or not O0O000O0000OOO000 ['msg']['installed']:#line:378
OO0OOO0OO00000OO0 ={"project_list":[],"template":[],"service_status":O0O000O0000OOO000 ['msg']['service_status'],"installed":O0O000O0000OOO000 ['msg']['installed']}#line:384
return public .return_msg_gettext (True ,OO0OOO0OO00000OO0 )#line:385
OO000O00000O00O0O =dp .sql ("stacks").select ()#line:386
if isinstance (OO000O00000O00O0O ,list ):#line:387
for O0OOOO0O000O00O00 in OO000O00000O00O0O :#line:388
OOOOOO0OO00OOOO0O =[]#line:389
for O0000OOO000000OOO in O0O000O0000OOO000 ['msg']["container_list"]:#line:390
try :#line:391
if 'com.docker.compose.project'not in O0000OOO000000OOO ["detail"]['Config']['Labels']:#line:392
continue #line:393
except :#line:394
continue #line:395
if O0000OOO000000OOO ["detail"]['Config']['Labels']['com.docker.compose.project']==public .md5 (O0OOOO0O000O00O00 ['name']):#line:396
OOOOOO0OO00OOOO0O .append (O0000OOO000000OOO )#line:397
O00OOOOO0O0OO0000 =OOOOOO0OO00OOOO0O #line:398
O0OOOO0O000O00O00 ['container']=O00OOOOO0O0OO0000 #line:399
else :#line:400
OO000O00000O00O0O =[]#line:401
OO0OOO0OO0OO00OOO =OOOOOO0OO00O0OO0O .template_list (OO0O0000O00O0O000 )#line:402
if not OO0OOO0OO0OO00OOO ['status']:#line:403
OO0OOO0OO0OO00OOO =list ()#line:404
else :#line:405
OO0OOO0OO0OO00OOO =OO0OOO0OO0OO00OOO ['msg']['template']#line:406
OO0O0O00OOO000O0O =ds .main ()#line:407
OO0OOO0OO00000OO0 ={"project_list":OO000O00000O00O0O ,"template":OO0OOO0OO0OO00OOO ,"service_status":OO0O0O00OOO000O0O .get_service_status (),"installed":OO0O0O00OOO000O0O .check_docker_program ()}#line:413
return public .return_msg_gettext (True ,OO0OOO0OO00000OO0 )#line:414
def remove (O0O0O0O0OO00OOOOO ,OOO0O00OOO0OOOO00 ):#line:417
""#line:422
O0OO0OOO00O000OOO =dp .sql ("stacks").where ("id=?",(OOO0O00OOO0OOOO00 .project_id ,)).find ()#line:423
if not O0OO0OOO00O000OOO :#line:424
return public .return_msg_gettext (True ,"The project configuration was not found!")#line:425
OO0000000000O000O ="/usr/bin/docker-compose -p {} -f {} down &> {}".format (public .md5 (O0OO0OOO00O000OOO ['name']),O0OO0OOO00O000OOO ['path'],O0O0O0O0OO00OOOOO .__O00OO0OO00O0OO000 )#line:426
OO0O0OOO00O00OO00 ,O00OO00O0000000O0 =public .ExecShell (OO0000000000O000O )#line:427
dp .sql ("stacks").delete (id =OOO0O00OOO0OOOO00 .project_id )#line:428
dp .write_log ("Delete item [{}] succeeded!".format (O0OO0OOO00O000OOO ['name']))#line:429
return public .return_msg_gettext (True ,"Successfully deleted!")#line:430
def stop (O0OOO0OOOOOO00O00 ,OOOO0OOO0OO00OO00 ):#line:433
""#line:439
O00O000O00OOO00O0 =dp .sql ("stacks").where ("id=?",(OOOO0OOO0OO00OO00 .project_id ,)).find ()#line:440
if not O00O000O00OOO00O0 :#line:441
return public .return_msg_gettext (True ,"The project configuration was not found!")#line:442
OO0OO0OOO0O0O00O0 ="/usr/bin/docker-compose -p {} -f {} stop &> {}".format (public .md5 (O00O000O00OOO00O0 ['name']),O00O000O00OOO00O0 ['path'],O0OOO0OOOOOO00O00 .__O00OO0OO00O0OO000 )#line:444
OO0O00O0000OOOOOO ,O0OO00000O0OO00O0 =public .ExecShell (OO0OO0OOO0O0O00O0 )#line:445
dp .write_log ("Stop project [{}] succeeded!".format (O00O000O00OOO00O0 ['name']))#line:446
return public .return_msg_gettext (True ,"Set up successfully!")#line:447
def start (O000OO00OOO0000O0 ,O0000O000OO0OOOO0 ):#line:450
""#line:455
OO00O000000OO00O0 =dp .sql ("stacks").where ("id=?",(O0000O000OO0OOOO0 .project_id ,)).find ()#line:456
if not OO00O000000OO00O0 :#line:457
return public .return_msg_gettext (False ,"The project configuration was not found!")#line:458
O0OO000O0OOO0OO0O ="/usr/bin/docker-compose -p {} -f {} start > {}".format (public .md5 (OO00O000000OO00O0 ['name']),OO00O000000OO00O0 ['path'],O000OO00OOO0000O0 .__O00OO0OO00O0OO000 )#line:459
O00O000OOO00O000O ,O0O00OO0OO0OO0OOO =public .ExecShell (O0OO000O0OOO0OO0O )#line:460
dp .write_log ("Startup project [{}] succeeded!".format (OO00O000000OO00O0 ['name']))#line:461
return public .return_msg_gettext (True ,"Set up successfully!")#line:462
def restart (O0OO00OO0O0OOO00O ,O000OOOOOOO00O0OO ):#line:465
""#line:470
OO000OOOOO0OO0O0O =dp .sql ("stacks").where ("id=?",(O000OOOOOOO00O0OO .project_id ,)).find ()#line:471
if not OO000OOOOO0OO0O0O :#line:472
return public .return_msg_gettext (True ,"The project configuration was not found!")#line:473
O00O00O000OO00O0O ="/usr/bin/docker-compose -p {} -f {} restart &> {}".format (public .md5 (OO000OOOOO0OO0O0O ['name']),OO000OOOOO0OO0O0O ['path'],O0OO00OO0O0OOO00O .__O00OO0OO00O0OO000 )#line:474
O00OO0000O0000OO0 ,O0OOOOO000OO0O0O0 =public .ExecShell (O00O00O000OO00O0O )#line:475
dp .write_log ("Restart the project [{}] successfully!".format (OO000OOOOO0OO0O0O ['name']))#line:476
return public .return_msg_gettext (True ,"Set up successfully!")#line:477
def pull (OOO0OO00O0OO00OO0 ,OO0OOOOOO00000OO0 ):#line:480
""#line:485
O0OO0OO0OO0O0OOO0 =dp .sql ("templates").where ("id=?",(OO0OOOOOO00000OO0 .template_id ,)).find ()#line:486
if not O0OO0OO0OO0O0OOO0 :#line:487
return public .return_msg_gettext (True ,"The template was not found!")#line:488
O0OOOO0O000O0O000 ="/usr/bin/docker-compose -p {} -f {} pull &> {}".format (O0OO0OO0OO0O0OOO0 ['name'],O0OO0OO0OO0O0OOO0 ['path'],OOO0OO00O0OO00OO0 .__O00OO0OO00O0OO000 )#line:489
O0O00OOO0O0O0OO00 ,OO000OOO0O000OOO0 =public .ExecShell (O0OOOO0O000O0O000 )#line:490
dp .write_log ("The mirror image of the template [{}] was pulled successfully!".format (O0OO0OO0OO0O0OOO0 ['name']))#line:491
return public .return_msg_gettext (True ,"Pull success!")#line:492
def pause (OOO00O0OO00O00O0O ,O0OOOOO000OO0000O ):#line:495
""#line:500
OO0O0000OOO000O00 =dp .sql ("stacks").where ("id=?",(O0OOOOO000OO0000O .project_id ,)).find ()#line:501
if not OO0O0000OOO000O00 :#line:502
return public .return_msg_gettext (True ,"The project configuration was not found!")#line:503
O0O0OOO0000O0O00O ="/usr/bin/docker-compose -p {} -f {} pause &> {}".format (public .md5 (OO0O0000OOO000O00 ['name']),OO0O0000OOO000O00 ['path'],OOO00O0OO00O00O0O .__O00OO0OO00O0OO000 )#line:504
O0000OO0OOO00OOOO ,O0O0O0OOO0O0O0OOO =public .ExecShell (O0O0OOO0000O0O00O )#line:505
dp .write_log ("Pause [{}] success!".format (OO0O0000OOO000O00 ['name']))#line:506
return public .return_msg_gettext (True ,"Set up successfully!")#line:507
def unpause (O0O0O0OOO00OOOO00 ,O0O00O000OOO00OO0 ):#line:510
""#line:515
OO0O0OO00OOO00O00 =dp .sql ("stacks").where ("id=?",(O0O00O000OOO00OO0 .project_id ,)).find ()#line:516
if not OO0O0OO00OOO00O00 :#line:517
return public .return_msg_gettext (True ,"The project configuration was not found!")#line:518
OOO00O00OOOO0OO00 ="/usr/bin/docker-compose -p {} -f {} unpause &> {}".format (public .md5 (OO0O0OO00OOO00O00 ['name']),OO0O0OO00OOO00O00 ['path'],O0O0O0OOO00OOOO00 .__O00OO0OO00O0OO000 )#line:519
O00000OOO000OOO0O ,O00OO00O0O0O00OO0 =public .ExecShell (OOO00O00OOOO0OO00 )#line:520
dp .write_log ("Unsuspended project [{}] succeeded!".format (OO0O0OO00OOO00O00 ['name']))#line:521
return public .return_msg_gettext (True ,"Set up successfully!")#line:522
def scan_compose_file (OOO000OO000OOOOOO ,O00000OOO00O00OOO ,O000O00O0OOO0O0OO ):#line:525
""#line:531
O0OOOO0O00OOO00O0 =os .listdir (O00000OOO00O00OOO )#line:532
for OO00000OOO00OOOO0 in O0OOOO0O00OOO00O0 :#line:533
OO0O0OO00OO0OO000 =os .path .join (O00000OOO00O00OOO ,OO00000OOO00OOOO0 )#line:534
if os .path .isdir (OO0O0OO00OO0OO000 ):#line:536
OOO000OO000OOOOOO .scan_compose_file (OO0O0OO00OO0OO000 ,O000O00O0OOO0O0OO )#line:537
else :#line:538
if OO00000OOO00OOOO0 =="docker-compose.yaml"or OO00000OOO00OOOO0 =="docker-compose.yam"or OO00000OOO00OOOO0 =="docker-compose.yml":#line:539
if "/www/server/panel/data/compose"in OO0O0OO00OO0OO000 :#line:540
continue #line:541
O000O00O0OOO0O0OO .append (OO0O0OO00OO0OO000 )#line:542
return O000O00O0OOO0O0OO #line:543
def get_compose_project (OOO000O00OO000OO0 ,O0OOOO0OOOOO0000O ):#line:546
""#line:552
O0O0OO00OO0000O0O =list ()#line:553
if O0OOOO0OOOOO0000O .path =="/":#line:554
return public .return_msg_gettext (False ,"Can't start scanning from root directory!")#line:555
if O0OOOO0OOOOO0000O .path [-1 ]=="/":#line:556
O0OOOO0OOOOO0000O .path =O0OOOO0OOOOO0000O .path [:-1 ]#line:557
if str (O0OOOO0OOOOO0000O .sub_dir )=="1":#line:558
O000OOOO0OO00OOOO =OOO000O00OO000OO0 .scan_compose_file (O0OOOO0OOOOO0000O .path ,O0O0OO00OO0000O0O )#line:559
if not O000OOOO0OO00OOOO :#line:560
O000OOOO0OO00OOOO =[]#line:561
else :#line:562
O00O0O0OOO0OO0O00 =list ()#line:563
for O0O00O0O0OOOO000O in O000OOOO0OO00OOOO :#line:564
O00O0O0OOO0OO0O00 .append ({"project_name":O0O00O0O0OOOO000O .split ("/")[-2 ],"conf_file":"/".join (O0O00O0O0OOOO000O .split ("/")),"remark":"Add by local path"})#line:571
O000OOOO0OO00OOOO =O00O0O0OOO0OO0O00 #line:572
else :#line:573
O00O0O00O00O0000O ="{}/docker-compose.yaml".format (O0OOOO0OOOOO0000O .path )#line:574
OOO00OOO00O0O0OOO ="{}/docker-compose.yam".format (O0OOOO0OOOOO0000O .path )#line:575
if os .path .exists (O00O0O00O00O0000O ):#line:576
O000OOOO0OO00OOOO =[{"project_name":O0OOOO0OOOOO0000O .path .split ("/")[-1 ],"conf_file":O00O0O00O00O0000O ,"remark":"Add by local path"}]#line:581
elif os .path .exists (OOO00OOO00O0O0OOO ):#line:582
O000OOOO0OO00OOOO =[{"project_name":O0OOOO0OOOOO0000O .path .split ("/")[-1 ],"conf_file":OOO00OOO00O0O0OOO ,"remark":"Add by local path"}]#line:587
else :#line:588
O000OOOO0OO00OOOO =list ()#line:589
return O000OOOO0OO00OOOO #line:591
def add_template_in_path (O0O00000O0OO00OO0 ,OOO0OO0OO0O00O00O ):#line:594
""#line:599
OO0O000OO000O0OO0 =dict ()#line:600
OO00OOO00000OOOOO =dict ()#line:601
for OO0OO0OOO00O0OO00 in OOO0OO0OO0O00O00O .template_list :#line:602
O0O0OO00O00O00000 =OO0OO0OOO00O0OO00 ['conf_file']#line:603
O00O000OOOO0O00OO =OO0OO0OOO00O0OO00 ['project_name']#line:604
OOOOO00O00O0O0OO0 =OO0OO0OOO00O0OO00 ['remark']#line:605
O00O0O0O000O00O00 =O0O00000O0OO00OO0 .template_list (OOO0OO0OO0O00O00O )['msg']['template']#line:606
for O00O0O0OOO0O0OOOO in O00O0O0O000O00O00 :#line:607
if O00O000OOOO0O00OO ==O00O0O0OOO0O0OOOO ['name']:#line:608
OO0O000OO000O0OO0 [O00O000OOOO0O00OO ]="Template already exists!"#line:609
continue #line:610
if not os .path .exists (O0O0OO00O00O00000 ):#line:612
OO0O000OO000O0OO0 [O00O000OOOO0O00OO ]="The template was not found!"#line:613
continue #line:614
O000O0O0OOO00000O =O0O00000O0OO00OO0 .check_conf (O0O0OO00O00O00000 )#line:616
if not O000O0O0OOO00000O ['status']:#line:617
OO0O000OO000O0OO0 [O00O000OOOO0O00OO ]="Template validation failed, possibly malformed!"#line:618
continue #line:619
OO0OOO0OOOOO0O00O ={"name":O00O000OOOO0O00OO ,"remark":OOOOO00O00O0O0OO0 ,"path":O0O0OO00O00O00000 ,"add_in_path":1 }#line:626
print (OO0OOO0OOOOO0O00O )#line:627
dp .sql ("templates").insert (OO0OOO0OOOOO0O00O )#line:628
OO00OOO00000OOOOO [O00O000OOOO0O00OO ]="Template added successfully!"#line:629
print (OO0O000OO000O0OO0 )#line:631
for O00O0O0OOO0O0OOOO in OO0O000OO000O0OO0 :#line:632
if O00O0O0OOO0O0OOOO in OO00OOO00000OOOOO :#line:633
del (OO00OOO00000OOOOO [O00O0O0OOO0O0OOOO ])#line:634
else :#line:635
dp .write_log ("Add template [{}] from path successfully!".format (O00O0O0OOO0O0OOOO ))#line:636
if not OO0O000OO000O0OO0 and OO00OOO00000OOOOO :#line:637
return {'status':True ,'msg':'Add template successfully: [{}]'.format (','.join (OO00OOO00000OOOOO ))}#line:638
elif not OO00OOO00000OOOOO and OO0O000OO000O0OO0 :#line:639
return {'status':True ,'msg':'Failed to add template: template name already exists or format validation error [{}]'.format (','.join (OO0O000OO000O0OO0 ))}#line:640
return {'status':True ,'msg':'Add template successfully: [{}]<br>Add template failed: template name already exists or format validation error [{}]'.format (','.join (OO00OOO00000OOOOO ),','.join (OO0O000OO000O0OO0 ))}#line:641
@@ -0,0 +1,473 @@
#coding: utf-8
#-------------------------------------------------------------------
# 宝塔Linux面板
#-------------------------------------------------------------------
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
#-------------------------------------------------------------------
# Author: zouhw <zhw@bt.cn>
#-------------------------------------------------------------------
#------------------------------
# Docker模型
#------------------------------
import public
import docker.errors
import projectModel.bt_docker.dk_public as dp
class main:
def __init__(self):
self.alter_table()
def alter_table(self):
if not dp.sql('sqlite_master').where('type=? AND name=? AND sql LIKE ?',
('table', 'container', '%sid%')).count():
dp.sql('container').execute("alter TABLE container add container_name VARCHAR DEFAULT ''", ())
def docker_client(self,url):
return dp.docker_client(url)
# 添加容器
def run(self,args):
"""
:param name:容器名
:param image: 镜像
:param publish_all_ports 暴露所有端口 1/0
:param ports 暴露某些端口 {'1111/tcp': ('127.0.0.1', 1111)}
:param command 命令
:param entrypoint 配置容器启动后执行的命令
:param environment 环境变量 xxx=xxx 一行一条
:param auto_remove 当容器进程退出时,在守护进程端启用自动移除容器。 0/1
:param args:
:return:
"""
if not hasattr(args,'ports'):
args.ports = False
if not hasattr(args,'volumes'):
args.volumes = False
#检测端口是否已经在使用
if args.ports:
for i in args.ports:
if dp.check_socket(args.ports[i]):
return public.returnMsg(False,"The server port [{}] has been used, please replace it with another port!".format(args.ports[i]))
if not args.image:
return public.returnMsg(False, "If there is no image selected, please go to the image tab to pull the image you need!")
if args.restart_policy['Name'] == "always":
args.restart_policy = {"Name":"always"}
# return args.restart_policy
# if
args.cpu_quota = float(args.cpuset_cpus) * 100000
# if not args.volumes:
# args.volumes = {"/sys/fs/cgroup":{"bind":"/sys/fs/cgroup","mode":"rw"}}
# else:
# if not "/sys/fs/cgroup" in args.volumes:
# args.volumes['/sys/fs/cgroup'] = {"bind":"/sys/fs/cgroup","mode":"rw"}
try:
if not args.name:
args.name = "{}-{}".format(args.image,public.GetRandomString(8))
if int(args.cpu_quota) / 100000 > dp.get_cpu_count():
return public.returnMsg(False,"The CPU quota has exceeded the number of cores available!")
mem_limit_byte = dp.byte_conversion(args.mem_limit)
if mem_limit_byte > dp.get_mem_info():
return public.returnMsg(False, "The memory quota has exceeded the available number!")
res = self.docker_client(args.url).containers.run(
name=args.name,
image=args.image,
detach=True,
publish_all_ports=True if args.publish_all_ports == "1" else False,
ports=args.ports if args.ports else None,
command=args.command,
auto_remove=True if str(args.auto_remove) == "1" else False,
environment=dp.set_kv(args.environment), #"HOME=/value\nHOME11=value1"
volumes=args.volumes, #一个字典对象 {'服务器路径/home/user1/': {'bind': '容器路径/mnt/vol2', 'mode': 'rw'},'/var/www': {'bind': '/mnt/vol1', 'mode': 'ro'}}
# cpuset_cpus=args.cpuset_cpus ,#指定容器使用的cpu个数
cpu_quota=int(args.cpu_quota),
mem_limit=args.mem_limit, #b,k,m,g
restart_policy=args.restart_policy,
labels=dp.set_kv(args.labels), #"key=value\nkey1=value1"
tty=True,
stdin_open=True,
privileged=True
)
if res:
pdata = {
"cpu_limit": str(args.cpu_quota),
"container_name": args.name
}
dp.sql('container').insert(pdata)
public.set_module_logs('docker', 'run_container', 1)
dp.write_log("Create container [{}] successful!".format(args.name))
return public.returnMsg(True,"The container was created successfully!")
return public.returnMsg(False, 'Create failed!')
except docker.errors.APIError as e:
if "container to be able to reuse that name." in str(e):
return public.returnMsg(False, "The container name already exists!")
if "Invalid container name" in str(e):
return public.returnMsg(False, "The container name is illegal, please do not use Chinese container name!")
if "bind: address already in use" in str(e):
port = ""
for i in args.ports:
if ":{}:".format(args.ports[i]) in str(e):
port = args.ports[i]
args.id = args.name
self.del_container(args)
return public.returnMsg(False, "Server port {} is in use! Please change other ports".format(port))
return public.returnMsg(False, 'Create failed! {}'.format(public.get_error_info()))
# 保存为镜像
def commit(self,args):
"""
:param repository 推送到的仓库
:param tag 镜像标签 jose:v1
:param message 提交的信息
:param author 镜像作者
:param changes
:param conf dict
:param path 导出路径
:param name 导出文件名
:param args:
:return:
"""
if not hasattr(args,'conf') or not args.conf:
args.conf = None
if args.repository == "docker.io":
args.repository = ""
container = self.docker_client(args.url).containers.get(args.id)
container.commit(
repository=args.repository if args.repository else None,
tag=args.tag if args.tag else None,
message=args.message if args.message else None,
author=args.author if args.author else None,
# changes=args.changes if args.changes else None,
conf=args.conf
)
if hasattr(args,"path") and args.path:
args.id = "{}:{}".format(args.name,args.tag)
import projectModel.bt_docker.dk_image as dk
return dk.main().save(args)
dp.write_log("Submitting container [{}] as image [{}] succeeded!".format(container.attrs['Name'],args.tag))
return public.returnMsg(True,"提交成功!")
# 容器执行命令
def docker_shell(self, args):
"""
:param container_id
:param args:
:return:
"""
try:
self.docker_client(args.url).containers.get(args.container_id)
cmd = 'docker container exec -it {} /bin/bash'.format(args.container_id)
return public.returnMsg(True, cmd)
except docker.errors.APIError as ex:
return public.returnMsg(False, 'Failed to get container')
# 导出容器为tar 没有导入方法,目前弃用
def export(self,args):
"""
:param path 保存路径
:param name 包名
:param args:
:return:
"""
from os import path as ospath
from os import makedirs as makedirs
try:
if "tar" in args.name:
file_name = '{}/{}'.format(args.path,args.name)
else:
file_name = '{}/{}.tar'.format(args.path, args.name)
if not ospath.exists(args.path):
makedirs(args.path)
public.writeFile(file_name,'')
f = open(file_name, 'wb')
container = self.docker_client(args.url).containers.get(args.id)
data = container.export()
for i in data:
f.write(i)
f.close()
return public.returnMsg(True, "Successfully exported to: {}".format(file_name))
except:
return public.returnMsg(False, 'Operation failed:' + str(public.get_error_info()))
# 删除容器
def del_container(self,args):
"""
:return:
"""
import projectModel.bt_docker.dk_public as dp
container = self.docker_client(args.url).containers.get(args.id)
container.remove(force=True)
dp.sql("cpu_stats").where("container_id=?", (args.id,)).delete()
dp.sql("io_stats").where("container_id=?", (args.id,)).delete()
dp.sql("mem_stats").where("container_id=?", (args.id,)).delete()
dp.sql("net_stats").where("container_id=?", (args.id,)).delete()
dp.sql("container").where("container_nam=?", (container.attrs['Name'])).delete()
dp.write_log("Delete container [{}] succeeded!".format(container.attrs['Name']))
return public.returnMsg(True,"Successfully deleted!")
# 设置容器状态
def set_container_status(self,args):
import time
container = self.docker_client(args.url).containers.get(args.id)
if args.act == "start":
container.start()
elif args.act == "stop":
container.stop()
elif args.act == "pause":
container.pause()
elif args.act == "unpause":
container.unpause()
elif args.act == "reload":
container.reload()
else:
container.restart()
time.sleep(1)
tmp = self.docker_client(args.url).containers.get(args.id)
return {"name":container.attrs['Name'].replace('/',''),"status":tmp.attrs['State']['Status']} #返回设置后的状态
# 停止容器
def stop(self,args):
"""
:param url
:param id
:param args:
:return:
"""
try:
args.act = "stop"
data = self.set_container_status(args)
if data['status'] != "exited":
return public.returnMsg(False, "Stop failing!")
dp.write_log("Stop container [{}] succeeded!".format(data['name']))
return public.returnMsg(True, "Stop success!")
except docker.errors.APIError as e:
if "is already paused" in str(e):
return public.returnMsg(False,"The container has been suspended!")
if "No such container" in str(e):
return public.returnMsg(True, "The container has been stopped and deleted because the container has the option to automatically delete after stopping!")
return public.returnMsg(False,"Stop failing!{}".format(e))
def start(self,args):
"""
:param url
:param id
:param args:
:return:
"""
try:
args.act = "start"
data = self.set_container_status(args)
if data['status'] != "running":
return public.returnMsg(False, "Startup failed!")
dp.write_log("Start the container [{}] successfully!".format(data['name']))
return public.returnMsg(True, "Started successfully!")
except docker.errors.APIError as e:
if "cannot start a paused container, try unpause instead" in str(e):
return self.unpause(args)
def pause(self,args):
"""
Pauses all processes within this container.
:param url
:param id
:param args:
:return:
"""
try:
args.act = "pause"
data = self.set_container_status(args)
if data['status'] != "paused":
return public.returnMsg(False, "Container pause failed!")
dp.write_log("Suspended container [{}] succeeded!".format(data['name']))
return public.returnMsg(True, "Container paused successfully!")
except docker.errors.APIError as e:
if "is already paused" in str(e):
return public.returnMsg(False,"The container has been suspended!")
if "is not running" in str(e):
return public.returnMsg(False, "The container is not started and cannot be paused!")
if "is not paused" in str(e):
return public.returnMsg(False, "The container has not been suspended!")
return str(e)
def unpause(self,args):
"""
unPauses all processes within this container.
:param url
:param id
:param args:
:return:
"""
try:
args.act = "unpause"
data = self.set_container_status(args)
if data['status'] != "running":
return public.returnMsg(False, "Startup failed!")
dp.write_log("Unpausing the container [{}] succeeded!".format(data['name']))
return public.returnMsg(True, "Container unpause succeeded!")
except docker.errors.APIError as e:
if "is already paused" in str(e):
return public.returnMsg(False,"The container has been suspended!")
if "is not running" in str(e):
return public.returnMsg(False, "The container is not started and cannot be paused!")
if "is not paused" in str(e):
return public.returnMsg(False, "The container has not been suspended!")
return str(e)
def reload(self,args):
"""
Load this object from the server again and update attrs with the new data.
:param url
:param id
:param args:
:return:
"""
args.act = "reload"
data = self.set_container_status(args)
if data['status'] != "running":
return public.returnMsg(False, "Startup failed!")
dp.write_log("Reloading container [{}] succeeded!".format(data['name']))
return public.returnMsg(True, "Container reload succeeded!")
def restart(self,args):
"""
Restart this container. Similar to the docker restart command.
:param url
:param id
:param args:
:return:
"""
args.act = "restart"
data = self.set_container_status(args)
if data['status'] != "running":
return public.returnMsg(False, "Startup failed!")
dp.write_log("Restarting the container [{}] succeeded!".format(data['name']))
return public.returnMsg(True, "The container restarted successfully!")
def get_container_ip(self,container_networks):
data = list()
for network in container_networks:
data.append(container_networks[network]['IPAddress'])
return data
def get_container_path(self,detail):
import os
if not "GraphDriver" in detail:
return False
if "Data" not in detail["GraphDriver"]:
return False
if "MergedDir" not in detail["GraphDriver"]["Data"]:
return False
path = detail["GraphDriver"]["Data"]["MergedDir"]
if not os.path.exists(path):
return ""
return path
# 获取容器列表所需的外部数据
def get_other_data_for_container_list(self,args):
import projectModel.bt_docker.dk_image as di
import projectModel.bt_docker.dk_volume as dv
import projectModel.bt_docker.dk_compose as dc
import projectModel.bt_docker.dk_setup as ds
# 获取镜像列表
images = di.main().image_list(args)
if images['status']:
images = images['msg']['images_list']
else:
images = list()
# 获取卷列表
volumes = dv.main().get_volume_list(args)
if volumes['status']:
volumes = volumes['msg']['volume']
else:
volumes = list()
# 获取模板列表
template = dc.main().template_list(args)
if template['status']:
template = template['msg']['template']
else:
template = list()
online_cpus = dp.get_cpu_count()
mem_total = dp.get_mem_info()
docker_setup = ds.main()
return {
"images":images,
"volumes":volumes,
"template":template,
"online_cpus":online_cpus,
"mem_total":mem_total,
"installed":docker_setup.check_docker_program(),
"service_status":docker_setup.get_service_status()
}
# 获取容器列表
def get_list(self,args):
"""
:param url
:return:
"""
# 判断docker是否安装
import projectModel.bt_docker.dk_setup as ds
data = self.get_other_data_for_container_list(args)
if not ds.main().check_docker_program():
data['container_list'] = list()
return public.returnMsg(True,data)
client = self.docker_client(args.url)
if not client:
return public.returnMsg(True,data)
containers = client.containers
attr_list = self.get_container_attr(containers)
# data = self.get_other_data_for_container_list(args)
container_detail = list()
for attr in attr_list:
cpu_usage = dp.sql("cpu_stats").where("container_id=?",(attr["Id"],)).select()
if cpu_usage and isinstance(cpu_usage,list):
cpu_usage = cpu_usage[-1]['cpu_usage']
else:
cpu_usage = "0.0"
tmp = {
"id": attr["Id"],
"name": attr['Name'].replace("/",""),
"status": attr["State"]["Status"],
"image": attr["Config"]["Image"],
"time": attr["Created"],
"merged": self.get_container_path(attr),
"ip": self.get_container_ip(attr["NetworkSettings"]['Networks']),
"ports": attr["NetworkSettings"]["Ports"],
"detail": attr,
"cpu_usage":cpu_usage if attr["State"]["Status"] == "running" else ""
}
container_detail.append(tmp)
data['container_list'] = container_detail
return public.returnMsg(True,data)
# 获取容器的attr
def get_container_attr(self,containers):
c_list = containers.list(all=True)
return [container_info.attrs for container_info in c_list]
# 获取容器日志
def get_logs(self,args):
"""
:param url
:param id
:param args:
:return:
"""
try:
container = self.docker_client(args.url).containers.get(args.id)
res = container.logs().decode()
return public.returnMsg(True,res)
except docker.errors.APIError as e:
if "configured logging driver does not support reading" in str(e):
return public.returnMsg(False,"The container has no log files!")
# 登录容器
# 获取容器配置文件
+42
View File
@@ -0,0 +1,42 @@
# coding: utf-8
# -------------------------------------------------------------------
# 宝塔Linux面板
# -------------------------------------------------------------------
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
# -------------------------------------------------------------------
# Author: zouhw <zhw@bt.cn>
# -------------------------------------------------------------------
# ------------------------------
# Docker模型
# ------------------------------
import public #line:1
import projectModel .bt_docker .dk_public as dp #line:2
class main :#line:4
def get_list (O0000O0OOO0OO0O00 ,args =None ):#line:7
OO000O0OOO00OO00O =dp .sql ("hosts").select ()#line:8
for OO0000O00OOO0OOO0 in OO000O0OOO00OO00O :#line:9
if dp .docker_client (OO0000O00OOO0OOO0 ['url']):#line:10
OO0000O00OOO0OOO0 ['status']=True #line:11
else :#line:12
OO0000O00OOO0OOO0 ['status']=False #line:13
return OO000O0OOO00OO00O #line:14
def add (O0OO00O0O000O0000 ,O00O0000O00000O0O ):#line:17
""#line:22
import time #line:23
O00OO0OOO000OO0O0 =O0OO00O0O000O0000 .get_list ()#line:24
for O0O0OO00O00OOOOOO in O00OO0OOO000OO0O0 :#line:25
if O0O0OO00O00OOOOOO ['url']==O00O0000O00000O0O .url :#line:26
return public .returnMsg (False ,"This host already exists!")#line:27
if not dp .docker_client (O00O0000O00000O0O .url ):#line:29
return public .returnMsg (False ,"Failed to connect to the server, please check if docker has been started!")#line:30
O0O0OO0OOOOO0OOO0 ={"url":O00O0000O00000O0O .url ,"remark":O00O0000O00000O0O .remark ,"time":int (time .time ())}#line:35
dp .write_log ("Add host [{}] successful!".format (O00O0000O00000O0O .url ))#line:36
dp .sql ('hosts').insert (O0O0OO0OOOOO0OOO0 )#line:37
return public .returnMsg (True ,"Add docker host successfully!")#line:38
def delete (O0OOOO0000000O00O ,O0O0O0O000000OOOO ):#line:40
""#line:44
OOO00OO0OO0OOO00O =dp .sql ('hosts').where ('id=?',O0O0O0O000000OOOO (O0O0O0O000000OOOO .id ,)).find ()#line:45
dp .sql ('hosts').delete (id =O0O0O0O000000OOOO .id )#line:46
dp .write_log ("Delete host [{}] succeeded!".format (OOO00OO0OO0OOO00O ['url']))#line:47
return public .returnMsg (True ,"Delete host successfully!")
+226
View File
@@ -0,0 +1,226 @@
#coding: utf-8
#-------------------------------------------------------------------
# 宝塔Linux面板
#-------------------------------------------------------------------
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
#-------------------------------------------------------------------
# Author: zouhw <zhw@bt.cn>
#-------------------------------------------------------------------
#------------------------------
# Docker模型
#------------------------------
import os #line:13
import public #line:14
import docker .errors #line:15
import projectModel .bt_docker .dk_public as dp #line:16
class main :#line:18
__O000O000OOOO0OO00 ='/tmp/dockertmp.log'#line:19
def docker_client (O0O0OOO00O0000O0O ,OOOO0O000O000OO00 ):#line:20
import projectModel .bt_docker .dk_public as dp #line:21
return dp .docker_client (OOOO0O000O000OO00 )#line:22
def save (O0O000OO0O0O00OO0 ,OOOO0000OO0O0OOOO ):#line:25
""#line:33
try :#line:34
if "tar"in OOOO0000OO0O0OOOO .name :#line:35
O00OOOO00OO0OO0OO ='{}/{}'.format (OOOO0000OO0O0OOOO .path ,OOOO0000OO0O0OOOO .name )#line:36
else :#line:37
O00OOOO00OO0OO0OO ='{}/{}.tar'.format (OOOO0000OO0O0OOOO .path ,OOOO0000OO0O0OOOO .name )#line:38
if not os .path .exists (OOOO0000OO0O0OOOO .path ):#line:39
os .makedirs (OOOO0000OO0O0OOOO .path )#line:40
public .writeFile (O00OOOO00OO0OO0OO ,"")#line:41
O0000O0OOOOO000OO =open (O00OOOO00OO0OO0OO ,'wb')#line:42
O000OOOOOO00OOO00 =O0O000OO0O0O00OO0 .docker_client (OOOO0000OO0O0OOOO .url ).images .get (OOOO0000OO0O0OOOO .id )#line:43
for OO0O0O0O0O0OO0OOO in O000OOOOOO00OOO00 .save (named =True ):#line:44
O0000O0OOOOO000OO .write (OO0O0O0O0O0OO0OOO )#line:45
O0000O0OOOOO000OO .close ()#line:46
dp .write_log ("Image [{}] exported to [{}] successfully!".format (OOOO0000OO0O0OOOO .id ,O00OOOO00OO0OO0OO ))#line:47
return public .returnMsg (True ,"Saved successfully to: {}".format (O00OOOO00OO0OO0OO ))#line:48
except docker .errors .APIError as OOOO000OOO0O000O0 :#line:49
if "empty export - not implemented"in str (OOOO000OOO0O000O0 ):#line:50
return public .returnMsg (False ,"Empty images cannot be exported!")#line:51
return public .get_error_info ()#line:52
def load (OOO000O000OOOOOO0 ,O00OO0OOOO000O000 ):#line:55
""#line:60
OOOOO000O000O0000 =OOO000O000OOOOOO0 .docker_client (O00OO0OOOO000O000 .url ).images #line:61
with open (O00OO0OOOO000O000 .path ,'rb')as OO00O0O00000000O0 :#line:62
OOOOO000O000O0000 .load (OO00O0O00000000O0 )#line:65
dp .write_log ("Image [{}] imported successfully!".format (O00OO0OOOO000O000 .path ))#line:66
return public .returnMsg (True ,"Import successful! {}".format (O00OO0OOOO000O000 .path ))#line:67
def image_list (OO0O0OOO0OOOOO00O ,OO0O0OO000O0OOOOO ):#line:70
""#line:75
import projectModel .bt_docker .dk_registry as dr #line:76
import projectModel .bt_docker .dk_setup as ds #line:77
OOO00000OOO00000O =list ()#line:78
OO0OO00OOOO0O0O00 =OO0O0OOO0OOOOO00O .docker_client (OO0O0OO000O0OOOOO .url )#line:79
OO0OOO00OOO0O0OO0 =ds .main ()#line:80
O0OO0000O0O0O00O0 =OO0OOO00OOO0O0OO0 .check_docker_program ()#line:81
O00OOO0000OO0O0OO =OO0OOO00OOO0O0OO0 .get_service_status ()#line:82
if not OO0OO00OOOO0O0O00 :#line:83
OOO00000OOO00000O ={"images_list":[],"registry_list":[],"installed":O0OO0000O0O0O00O0 ,"service_status":O00OOO0000OO0O0OO }#line:89
return public .returnMsg (True ,OOO00000OOO00000O )#line:90
OOOO000O0OO00O00O =OO0OO00OOOO0O0O00 .images #line:91
OO0OO0OO000OOO000 =OO0O0OOO0OOOOO00O .get_image_attr (OOOO000O0OO00O00O )#line:92
OO000O0OO000O0000 =dr .main ().registry_list (OO0O0OO000O0OOOOO )#line:93
if OO000O0OO000O0000 ['status']:#line:94
OO000O0OO000O0000 =OO000O0OO000O0000 ['msg']['registry']#line:95
else :#line:96
OO000O0OO000O0000 =[]#line:97
for OO0O0O000000O00O0 in OO0OO0OO000OOO000 :#line:98
if len (OO0O0O000000O00O0 ['RepoTags'])==1 :#line:99
O0O0O0O0000OO0O00 ={"id":OO0O0O000000O00O0 ["Id"],"tags":OO0O0O000000O00O0 ["RepoTags"],"time":OO0O0O000000O00O0 ["Created"],"name":OO0O0O000000O00O0 ['RepoTags'][0 ],"size":OO0O0O000000O00O0 ["Size"],"detail":OO0O0O000000O00O0 }#line:107
OOO00000OOO00000O .append (O0O0O0O0000OO0O00 )#line:108
elif len (OO0O0O000000O00O0 ['RepoTags'])>1 :#line:109
for O0OO0O0O00O000O0O in range (len (OO0O0O000000O00O0 ['RepoTags'])):#line:110
O0O0O0O0000OO0O00 ={"id":OO0O0O000000O00O0 ["Id"],"tags":OO0O0O000000O00O0 ["RepoTags"],"time":OO0O0O000000O00O0 ["Created"],"name":OO0O0O000000O00O0 ['RepoTags'][O0OO0O0O00O000O0O ],"size":OO0O0O000000O00O0 ["Size"],"detail":OO0O0O000000O00O0 }#line:118
OOO00000OOO00000O .append (O0O0O0O0000OO0O00 )#line:119
elif not OO0O0O000000O00O0 ['RepoTags']:#line:120
O0O0O0O0000OO0O00 ={"id":OO0O0O000000O00O0 ["Id"],"tags":OO0O0O000000O00O0 ["RepoTags"],"time":OO0O0O000000O00O0 ["Created"],"name":OO0O0O000000O00O0 ["Id"],"size":OO0O0O000000O00O0 ["Size"],"detail":OO0O0O000000O00O0 }#line:128
OOO00000OOO00000O .append (O0O0O0O0000OO0O00 )#line:129
OOO00000OOO00000O ={"images_list":OOO00000OOO00000O ,"registry_list":OO000O0OO000O0000 ,"installed":O0OO0000O0O0O00O0 ,"service_status":O00OOO0000OO0O0OO }#line:135
return public .returnMsg (True ,OOO00000OOO00000O )#line:136
def get_image_attr (O00OOOO0O00OOO00O ,O000O00OOOOOOO000 ):#line:138
OOO00O0O00OO00OO0 =O000O00OOOOOOO000 .list ()#line:139
return [OO0000OOO0OO0O0OO .attrs for OO0000OOO0OO0O0OO in OOO00O0O00OO00OO0 ]#line:140
def get_logs (OO000O0O000000O0O ,OOOO000000O000O0O ):#line:142
import files #line:143
O0O0O0O0O0OOOOOO0 =OOOO000000O000O0O .logs_file #line:144
return public .returnMsg (True ,files .files ().GetLastLine (O0O0O0O0O0OOOOOO0 ,20 ))#line:145
def build (OOOO0OOO00O000O0O ,O00O0OOO00O00O0O0 ):#line:148
""#line:156
public .writeFile (OOOO0OOO00O000O0O .__O000O000OOOO0OO00 ,"Start building images!")#line:157
public .writeFile ('/tmp/dockertmp.log',"Start building the mirror")#line:158
if not hasattr (O00O0OOO00O00O0O0 ,"pull"):#line:159
O00O0OOO00O00O0O0 .pull =False #line:160
if hasattr (O00O0OOO00O00O0O0 ,"data")and O00O0OOO00O00O0O0 .data :#line:161
O00O0OOO00O00O0O0 .path ="/tmp/dockerfile"#line:162
public .writeFile (O00O0OOO00O00O0O0 .path ,O00O0OOO00O00O0O0 .data )#line:163
with open (O00O0OOO00O00O0O0 .path ,'rb')as OOO000000O000OOOO :#line:164
OO000OOOO0O0OO0O0 ,O000OOO0O0OOOO00O =OOOO0OOO00O000O0O .docker_client (O00O0OOO00O00O0O0 .url ).images .build (pull =True if O00O0OOO00O00O0O0 .pull =="1"else False ,fileobj =OOO000000O000OOOO ,tag =O00O0OOO00O00O0O0 .tag )#line:169
os .remove (O00O0OOO00O00O0O0 .path )#line:170
else :#line:171
if not os .path .isdir (O00O0OOO00O00O0O0 .path ):#line:172
O00O0OOO00O00O0O0 .path ='/'.join (O00O0OOO00O00O0O0 .path .split ('/')[:-1 ])#line:173
OO000OOOO0O0OO0O0 ,O000OOO0O0OOOO00O =OOOO0OOO00O000O0O .docker_client (O00O0OOO00O00O0O0 .url ).images .build (pull =True if O00O0OOO00O00O0O0 .pull =="1"else False ,path =O00O0OOO00O00O0O0 .path ,tag =O00O0OOO00O00O0O0 .tag )#line:178
dp .log_docker (O000OOO0O0OOOO00O ,"Docker build tasks")#line:180
dp .write_log ("Building image [{}] succeeded!".format (O00O0OOO00O00O0O0 .tag ))#line:181
return public .returnMsg (True ,"Building image successfully!")#line:182
def remove (OOOOO00000OO0OO0O ,O0000O000000OOO00 ):#line:185
""#line:193
try :#line:194
OOOOO00000OO0OO0O .docker_client (O0000O000000OOO00 .url ).images .remove (O0000O000000OOO00 .name )#line:195
dp .write_log ("Delete mirror【{}】successful!".format (O0000O000000OOO00 .name ))#line:196
return public .returnMsg (True ,"Mirror deleted successfully!")#line:197
except docker .errors .ImageNotFound as OOO00OOOO00OOO0O0 :#line:198
return public .returnMsg (False ,"Failed to delete the mirror, maybe the mirror does not exist!")#line:199
except docker .errors .APIError as OOO00OOOO00OOO0O0 :#line:200
if "image is referenced in multiple repositories"in str (OOO00OOOO00OOO0O0 ):#line:201
return public .returnMsg (False ,"The image ID is used in multiple images, please check [Force Delete]!")#line:202
if "using its referenced image"in str (OOO00OOOO00OOO0O0 ):#line:203
return public .returnMsg (False ,"The image is in use, please delete the container and then delete it!")#line:204
return public .returnMsg (False ,"Delete mirror failed!<br> {}".format (OOO00OOOO00OOO0O0 ))#line:205
def pull_from_some_registry (O00OOOOOOOOO00000 ,O0O0O0OOO0O0OO0O0 ):#line:208
""#line:215
import projectModel .bt_docker .dk_registry as br #line:216
O00O00OO00OOOOO00 =br .main ().registry_info (O0O0O0OOO0O0OO0O0 .name )#line:217
O0000OO00OO0OO000 =br .main ().login (O0O0O0OOO0O0OO0O0 .url ,O00O00OO00OOOOO00 ['url'],O00O00OO00OOOOO00 ['username'],O00O00OO00OOOOO00 ['password'])['status']#line:218
if not O0000OO00OO0OO000 :#line:219
return O0000OO00OO0OO000 #line:220
O0O0O0OOO0O0OO0O0 .username =O00O00OO00OOOOO00 ['username']#line:221
O0O0O0OOO0O0OO0O0 .password =O00O00OO00OOOOO00 ['password']#line:222
O0O0O0OOO0O0OO0O0 .registry =O00O00OO00OOOOO00 ['url']#line:223
O0O0O0OOO0O0OO0O0 .namespace =O00O00OO00OOOOO00 ['namespace']#line:224
return O00OOOOOOOOO00000 .pull (O0O0O0OOO0O0OO0O0 )#line:225
def push (OO0O0OOO0O0O00O0O ,OO000OOO0OO000O0O ):#line:228
""#line:236
if "/"in OO000OOO0OO000O0O .tag :#line:237
return public .returnMsg (False ,"The pushed image name cannot contain the symbol [/] , please use the following format: image:v1 (image_name:version_number)")#line:238
if ":"not in OO000OOO0OO000O0O .tag :#line:239
return public .returnMsg (False ,"The pushed image name must contain the symbol [ : ] , please use the following format: image:v1 (image_name:version_number)")#line:240
public .writeFile (OO0O0OOO0O0O00O0O .__O000O000OOOO0OO00 ,"Start pushing mirrors!\n")#line:241
import projectModel .bt_docker .dk_registry as br #line:242
O00O0O0O0O0O0O000 =br .main ().registry_info (OO000OOO0OO000O0O .name )#line:243
if OO000OOO0OO000O0O .name =="docker official"and O00O0O0O0O0O0O000 ['url']=="docker.io":#line:244
public .writeFile (OO0O0OOO0O0O00O0O .__O000O000OOOO0OO00 ,"The image cannot be pushed to the Docker public repository!\n")#line:245
return public .returnMsg (False ,"Unable to push to Docker public repo!")#line:246
O0O0000OOO0OOO00O =br .main ().login (OO000OOO0OO000O0O .url ,O00O0O0O0O0O0O000 ['url'],O00O0O0O0O0O0O000 ['username'],O00O0O0O0O0O0O000 ['password'])['status']#line:247
O00OOO0O0O0O0O0O0 =OO000OOO0OO000O0O .tag #line:248
if not O0O0000OOO0OOO00O :#line:249
return O0O0000OOO0OOO00O #line:250
OO00O0000000OO000 ={"username":O00O0O0O0O0O0O000 ['username'],"password":O00O0O0O0O0O0O000 ['password'],"registry":O00O0O0O0O0O0O000 ['url']}#line:254
if ":"not in O00OOO0O0O0O0O0O0 :#line:256
O00OOO0O0O0O0O0O0 ="{}:latest".format (O00OOO0O0O0O0O0O0 )#line:257
OOOO000OOOOO0O00O =O00O0O0O0O0O0O000 ['url']#line:258
O0OO00O0OO000O0OO ="{}/{}/{}".format (OOOO000OOOOO0O00O ,O00O0O0O0O0O0O000 ['namespace'],OO000OOO0OO000O0O .tag )#line:259
OO0O0OOO0O0O00O0O .tag (OO000OOO0OO000O0O .url ,OO000OOO0OO000O0O .id ,O0OO00O0OO000O0OO )#line:260
O000OOOO00O0OO000 =OO0O0OOO0O0O00O0O .docker_client (OO000OOO0OO000O0O .url ).images .push (repository =O0OO00O0OO000O0OO .split (":")[0 ],tag =O00OOO0O0O0O0O0O0 .split (":")[-1 ],auth_config =OO00O0000000OO000 ,stream =True )#line:266
dp .log_docker (O000OOOO00O0OO000 ,"Image push task")#line:267
OO000OOO0OO000O0O .name =O0OO00O0OO000O0OO #line:269
OO0O0OOO0O0O00O0O .remove (OO000OOO0OO000O0O )#line:270
dp .write_log ("The image [{}] was pushed successfully!".format (O0OO00O0OO000O0OO ))#line:271
return public .returnMsg (True ,"推送成功!{}".format (str (O000OOOO00O0OO000 )))#line:272
def tag (OOO0OO00OO0OO0O00 ,O000O0OOO00O000OO ,OOOO0O0OOO0000O00 ,OO0O0000OO00O00O0 ):#line:274
""#line:281
OOO000O000000OOO0 =OO0O0000OO00O00O0 .split (":")[0 ]#line:282
O00OOO0OOOO0O000O =OO0O0000OO00O00O0 .split (":")[1 ]#line:283
OOO0OO00OO0OO0O00 .docker_client (O000O0OOO00O000OO ).images .get (OOOO0O0OOO0000O00 ).tag (repository =OOO000O000000OOO0 ,tag =O00OOO0OOOO0O000O )#line:287
return public .returnMsg (True ,"Set successfully")#line:288
def pull (O0O0O0000OOOOOOO0 ,OO00OOO00OO000O00 ):#line:290
""#line:299
public .writeFile (O0O0O0000OOOOOOO0 .__O000O000OOOO0OO00 ,"Start pulling images!")#line:300
import docker .errors #line:301
try :#line:302
if ':'not in OO00OOO00OO000O00 .image :#line:303
OO00OOO00OO000O00 .image ='{}:latest'.format (OO00OOO00OO000O00 .image )#line:304
O0O00OO000O000OO0 ={"username":OO00OOO00OO000O00 .username ,"password":OO00OOO00OO000O00 .password ,"registry":OO00OOO00OO000O00 .registry if OO00OOO00OO000O00 .registry else None }if OO00OOO00OO000O00 .username else None #line:308
if not hasattr (OO00OOO00OO000O00 ,"tag"):#line:309
OO00OOO00OO000O00 .tag =OO00OOO00OO000O00 .image .split (":")[-1 ]#line:310
if OO00OOO00OO000O00 .registry !="docker.io":#line:311
OO00OOO00OO000O00 .image ="{}/{}/{}".format (OO00OOO00OO000O00 .registry ,OO00OOO00OO000O00 .namespace ,OO00OOO00OO000O00 .image )#line:312
OOO0OOOO000O000O0 =dp .docker_client_low (OO00OOO00OO000O00 .url ).pull (repository =OO00OOO00OO000O00 .image ,auth_config =O0O00OO000O000OO0 ,tag =OO00OOO00OO000O00 .tag ,stream =True )#line:318
dp .log_docker (OOO0OOOO000O000O0 ,"Image pull task")#line:319
if OOO0OOOO000O000O0 :#line:320
dp .write_log ("The image [{}:{}] was pulled successfully!".format (OO00OOO00OO000O00 .image ,OO00OOO00OO000O00 .tag ))#line:321
return public .returnMsg (True ,'Pulling the image succeeded.')#line:322
else :#line:323
return public .returnMsg (False ,'There may not be this image.')#line:324
except docker .errors .ImageNotFound as O0O0OO00OO000O0O0 :#line:325
if "pull access denied for"in str (O0O0OO00OO000O0O0 ):#line:326
return public .returnMsg (False ,"The pull failed, the image is a private image, you need to enter the account password of dockerhub!")#line:327
return public .returnMsg (False ,"Pull failed<br><br>reasons: {}".format (O0O0OO00OO000O0O0 ))#line:329
except docker .errors .NotFound as O0O0OO00OO000O0O0 :#line:331
if "not found: manifest unknown"in str (O0O0OO00OO000O0O0 ):#line:332
return public .returnMsg (False ,"The pull failed, the repository does not have the mirror!")#line:333
return public .returnMsg (False ,"Pull failed<br><br>reason:{}".format (O0O0OO00OO000O0O0 ))#line:334
except docker .errors .APIError as O0O0OO00OO000O0O0 :#line:335
if "invalid tag format"in str (O0O0OO00OO000O0O0 ):#line:336
return public .returnMsg (False ,"The pull failed, the image format is wrong, the format should be: nginx:v 1!")#line:337
return public .returnMsg (False ,"Pull failed!{}".format (O0O0OO00OO000O0O0 ))#line:338
def pull_high_api (OO0O0O0O000O000O0 ,O0000O0O000O0O0O0 ):#line:342
""#line:351
import docker .errors #line:352
try :#line:353
if ':'not in O0000O0O000O0O0O0 .image :#line:354
O0000O0O000O0O0O0 .image ='{}:latest'.format (O0000O0O000O0O0O0 .image )#line:355
O0O0O00O0O0O00000 ={"username":O0000O0O000O0O0O0 .username ,"password":O0000O0O000O0O0O0 .password ,"registry":O0000O0O000O0O0O0 .registry if O0000O0O000O0O0O0 .registry else None }if O0000O0O000O0O0O0 .username else None #line:359
if O0000O0O000O0O0O0 .registry !="docker.io":#line:361
O0000O0O000O0O0O0 .image ="{}/{}/{}".format (O0000O0O000O0O0O0 .registry ,O0000O0O000O0O0O0 .namespace ,O0000O0O000O0O0O0 .image )#line:362
OOOOOOOO0O0OOOO0O =OO0O0O0O000O000O0 .docker_client (O0000O0O000O0O0O0 .url ).images .pull (repository =O0000O0O000O0O0O0 .image ,auth_config =O0O0O00O0O0O00000 ,)#line:366
if OOOOOOOO0O0OOOO0O :#line:367
return public .returnMsg (True ,'Pulling the image succeeded.')#line:368
else :#line:369
return public .returnMsg (False ,'There may not be this mirror.')#line:370
except docker .errors .ImageNotFound as O0O0O0OOO0O0OO0OO :#line:371
if "pull access denied for"in str (O0O0O0OOO0O0OO0OO ):#line:372
return public .returnMsg (False ,"The pull failed, the image is a private image, you need to enter the account password of dockerhub!")#line:373
return public .returnMsg (False ,"Pull failed<br><br>reason: {}".format (O0O0O0OOO0O0OO0OO ))#line:374
def image_for_host (O00O0O0O000OOO0O0 ,O000OO0OOOOO000O0 ):#line:376
""#line:381
O00O000OO0OO000OO =O00O0O0O000OOO0O0 .image_list (O000OO0OOOOO000O0 )#line:382
if not O00O000OO0OO000OO ['status']:#line:383
return O00O000OO0OO000OO #line:384
OO000O0000O000000 =len (O00O000OO0OO000OO ['msg']['images_list'])#line:385
O0OOOO0OO000OO0OO =0 #line:386
for OO00OOO0000OO0O00 in O00O000OO0OO000OO ['msg']['images_list']:#line:387
O0OOOO0OO000OO0OO +=OO00OOO0000OO0O00 ['size']#line:388
return public .returnMsg (True ,{'num':OO000O0000O000000 ,'size':O0OOOO0OO000OO0OO })
@@ -0,0 +1,92 @@
#coding: utf-8
#-------------------------------------------------------------------
# 宝塔Linux面板
#-------------------------------------------------------------------
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
#-------------------------------------------------------------------
# Author: zouhw <zhw@bt.cn>
#-------------------------------------------------------------------
#------------------------------
# Docker模型
#------------------------------
import sys #line:1
import threading #line:2
sys .path .insert (0 ,"/www/server/panel/class/")#line:3
sys .path .insert (1 ,"/www/server/panel/")#line:4
import projectModel .bt_docker .dk_public as dp #line:5
import projectModel .bt_docker .dk_container as dc #line:6
import projectModel .bt_docker .dk_status as ds #line:7
import projectModel .bt_docker .dk_image as di #line:8
import public #line:9
import time #line:11
class main :#line:12
__OOOOO0OOO0OO00O00 =None #line:14
__OOOOOO0OO0OOOOOO0 =86400 #line:15
def __init__ (O00O000000O0OO0OO ,OO00OO00O0O00OO0O ):#line:17
if not OO00OO00O0O00OO0O :#line:18
O00O000000O0OO0OO .__OOOOO0OOO0OO00O00 =30 #line:19
else :#line:20
O00O000000O0OO0OO .__OOOOO0OOO0OO00O00 =OO00OO00O0O00OO0O #line:21
def docker_client (OOOOO000OO0O00OO0 ,OO00OOO0000OO0000 ):#line:23
return dp .docker_client (OO00OOO0000OO0000 )#line:24
def get_all_host_stats (O0000O0000OO0O000 ,O000O0O00OO00O00O ):#line:26
""#line:31
OO000O0OO0O0O0000 =dp .sql ('hosts').select ()#line:32
for O00O0OO00O0O000O0 in OO000O0OO0O0O0000 :#line:33
O0OO00O0O00O0000O =threading .Thread (target =O000O0O00OO00O00O ,args =(O00O0OO00O0O000O0 ,))#line:34
O0OO00O0O00O0000O .setDaemon (True )#line:35
O0OO00O0O00O0000O .start ()#line:36
def container_status_for_all_hosts (OO0O00OO0O0OOOO0O ,OOOOOOO000OO0OOO0 ):#line:39
""#line:44
O000OO000O0O00O00 =public .to_dict_obj ({})#line:46
O000OO000O0O00O00 .url =OOOOOOO000OO0OOO0 ['url']#line:47
O0O0O0O000O00O0OO =dc .main ().get_list (O000OO000O0O00O00 )['msg']#line:48
for O00OOOOOOOO00OOO0 in O0O0O0O000O00O0OO ['container_list']:#line:49
O000OO000O0O00O00 .id =O00OOOOOOOO00OOO0 ['id']#line:50
O000OO000O0O00O00 .write =1 #line:51
O000OO000O0O00O00 .save_date =OO0O00OO0O0OOOO0O .__OOOOO0OOO0OO00O00 #line:52
ds .main ().stats (O000OO000O0O00O00 )#line:53
def container_count (OO0000O0O0O0OOO00 ):#line:57
O0O000O0O000O000O =dp .sql ('hosts').select ()#line:59
O0O00O00O0O00OOO0 =0 #line:60
for O0O0O00OO0OO0O0O0 in O0O000O0O000O000O :#line:61
O00OOOO00OO0OOO00 =public .to_dict_obj ({})#line:62
O00OOOO00OO0OOO00 .url =O0O0O00OO0OO0O0O0 ['url']#line:63
OO00OO00O0O00O00O =dc .main ().get_list (O00OOOO00OO0OOO00 )['msg']#line:64
O0O00O00O0O00OOO0 +=len (OO00OO00O0O00O00O )#line:65
O0000000000000000 ={"time":int (time .time ()),"container_count":O0O00O00O0O00OOO0 }#line:69
OOOOO0OO00OOO0O0O =time .time ()-(OO0000O0O0O0OOO00 .__OOOOO0OOO0OO00O00 *OO0000O0O0O0OOO00 .__OOOOOO0OO0OOOOOO0 )#line:70
dp .sql ("container_count").where ("time<?",(OOOOO0OO00OOO0O0O ,)).delete ()#line:71
dp .sql ("container_count").insert (O0000000000000000 )#line:72
def image_for_all_host (OO0O00O000OO00O0O ):#line:75
OO000OO0OOO00OO0O =dp .sql ('hosts').select ()#line:77
OOO0OOO00O000OOOO =0 #line:78
O0O00000OO0O0O000 =0 #line:79
for O00OOO00O0000O00O in OO000OO0OOO00OO0O :#line:80
O0O00O0OOOO0O00O0 =public .to_dict_obj ({})#line:81
O0O00O0OOOO0O00O0 .url =O00OOO00O0000O00O ['url']#line:82
OO00O0000O0000O00 =di .main ().image_for_host (O0O00O0OOOO0O00O0 )#line:83
if not OO00O0000O0000O00 ['status']:#line:84
continue #line:85
print (OO00O0000O0000O00 )#line:86
OOO0OOO00O000OOOO +=OO00O0000O0000O00 ['msg']['num']#line:87
O0O00000OO0O0O000 +=OO00O0000O0000O00 ['msg']['size']#line:88
O0OO0O00O000000OO ={"time":int (time .time ()),"num":OOO0OOO00O000OOOO ,"size":int (O0O00000OO0O0O000 )}#line:93
O0O000O00OO0OO0O0 =time .time ()-(OO0O00O000OO00O0O .__OOOOO0OOO0OO00O00 *OO0O00O000OO00O0O .__OOOOOO0OO0OOOOOO0 )#line:94
dp .sql ("image_infos").where ("time<?",(O0O000O00OO0OO0O0 ,)).delete ()#line:95
dp .sql ("image_infos").insert (O0OO0O00O000000OO )#line:96
def monitor ():#line:99
while True :#line:102
O0OOO000OOO0OOO00 =dp .docker_conf ()['SAVE']#line:103
O000OO0O0O0OO0000 =main (O0OOO000OOO0OOO00 )#line:104
O000OO0O0O0OO0000 .get_all_host_stats (O000OO0O0O0OO0000 .container_status_for_all_hosts )#line:105
O0000OO0000000O00 =threading .Thread (target =O000OO0O0O0OO0000 .container_count )#line:107
O0000OO0000000O00 .setDaemon (True )#line:108
O0000OO0000000O00 .start ()#line:109
O0000OO0000000O00 =threading .Thread (target =O000OO0O0O0OO0000 .image_for_all_host )#line:111
O0000OO0000000O00 .setDaemon (True )#line:112
O0000OO0000000O00 .start ()#line:113
time .sleep (60 )#line:114
if __name__ =="__main__":#line:119
monitor ()
@@ -0,0 +1,69 @@
#coding: utf-8
#-------------------------------------------------------------------
# 宝塔Linux面板
#-------------------------------------------------------------------
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
#-------------------------------------------------------------------
# Author: zouhw <zhw@bt.cn>
#-------------------------------------------------------------------
#------------------------------
# Docker模型
#------------------------------
import public #line:1
import projectModel .bt_docker .dk_public as dp #line:2
import docker .errors #line:3
class main :#line:5
def docker_client (O00O0O000OO0000O0 ,OOO0OOOO0O0000OO0 ):#line:7
import projectModel .bt_docker .dk_public as dp #line:8
return dp .docker_client (OOO0OOOO0O0000OO0 )#line:9
def get_host_network (OO0O00O000O000O0O ,O00OO00OO00OOOOOO ):#line:11
""#line:16
import projectModel .bt_docker .dk_setup as ds #line:17
O00OO00O00000000O =ds .main ()#line:18
O000O0O0O00OO000O =O00OO00O00000000O .check_docker_program ()#line:19
O0O00O000OOO0OO0O =O00OO00O00000000O .get_service_status ()#line:20
OO0O0O00OO0OO0OO0 =OO0O00O000O000O0O .docker_client (O00OO00OO00OOOOOO .url )#line:21
if not OO0O0O00OO0OO0OO0 :#line:22
O0000O0000O0O0OO0 ={"images_list":[],"registry_list":[],"installed":O000O0O0O00OO000O ,"service_status":O0O00O000OOO0OO0O }#line:28
return public .returnMsg (True ,O0000O0000O0O0OO0 )#line:29
O000OO0OO00OOOO0O =OO0O0O00OO0OO0OO0 .networks #line:30
O0OOO0O00O00OO000 =OO0O00O000O000O0O .get_network_attr (O000OO0OO00OOOO0O )#line:31
O0000O0000O0O0OO0 =list ()#line:32
for OOOO0O0OOOO0O00O0 in O0OOO0O00O00OO000 :#line:33
OOOO00OOOO0O0000O =""#line:34
O00O000OOOO000O0O =""#line:35
if OOOO0O0OOOO0O00O0 ["IPAM"]["Config"]:#line:36
if "Subnet"in OOOO0O0OOOO0O00O0 ["IPAM"]["Config"][0 ]:#line:37
OOOO00OOOO0O0000O =OOOO0O0OOOO0O00O0 ["IPAM"]["Config"][0 ]["Subnet"]#line:38
if "Gateway"in OOOO0O0OOOO0O00O0 ["IPAM"]["Config"][0 ]:#line:39
O00O000OOOO000O0O =OOOO0O0OOOO0O00O0 ["IPAM"]["Config"][0 ]["Gateway"]#line:40
OOOOO000000OO000O ={"id":OOOO0O0OOOO0O00O0 ["Id"],"name":OOOO0O0OOOO0O00O0 ["Name"],"time":OOOO0O0OOOO0O00O0 ["Created"],"driver":OOOO0O0OOOO0O00O0 ["IPAM"]["Driver"],"subnet":OOOO00OOOO0O0000O ,"gateway":O00O000OOOO000O0O ,"labels":OOOO0O0OOOO0O00O0 ["Labels"]}#line:49
O0000O0000O0O0OO0 .append (OOOOO000000OO000O )#line:50
OOOOOOO000O0O0O0O ={"network":O0000O0000O0O0OO0 ,"installed":O000O0O0O00OO000O ,"service_status":O0O00O000OOO0OO0O }#line:56
return public .returnMsg (True ,OOOOOOO000O0O0O0O )#line:57
def get_network_attr (OO0O00O00O000OO00 ,O0OO0000O0OOO0O0O ):#line:59
O000OOOO0OOO00O00 =O0OO0000O0OOO0O0O .list ()#line:60
return [O00O0000O0OO00O00 .attrs for O00O0000O0OO00O00 in O000OOOO0OOO00O00 ]#line:61
def add (O0OOO0O0O0000OO0O ,O0OOO0O000000000O ):#line:63
""#line:75
import docker #line:76
O0O0000OO00OO00OO =docker .types .IPAMPool (subnet =O0OOO0O000000000O .subnet ,gateway =O0OOO0O000000000O .gateway ,iprange =O0OOO0O000000000O .iprange )#line:81
OOOO00000O000OO0O =docker .types .IPAMConfig (pool_configs =[O0O0000OO00OO00OO ])#line:84
O0OOO0O0O0000OO0O .docker_client (O0OOO0O000000000O .url ).networks .create (name =O0OOO0O000000000O .name ,options =O0OOO0O000000000O .options if O0OOO0O000000000O .options else None ,driver ="bridge",ipam =OOOO00000O000OO0O ,labels =dp .set_kv (O0OOO0O000000000O .labels ))#line:91
dp .write_log ("Add network [{}] [{}] successful!".format (O0OOO0O000000000O .name ,O0OOO0O000000000O .iprange ))#line:92
return public .returnMsg (True ,"Added successfully!")#line:93
def del_network (OOOOO0OO0O00O000O ,OOO0OOOO0O0O0O0O0 ):#line:95
""#line:100
try :#line:101
O000O0OO00O0OO000 =OOOOO0OO0O00O000O .docker_client (OOO0OOOO0O0O0O0O0 .url ).networks .get (OOO0OOOO0O0O0O0O0 .id )#line:103
O0OOOOOO0OO0O0OOO =O000O0OO00O0OO000 .attrs #line:104
if O0OOOOOO0OO0O0OOO ['Name']in ["bridge","none"]:#line:105
return public .returnMsg (False ,"The system default network cannot be deleted!")#line:106
O000O0OO00O0OO000 .remove ()#line:107
dp .write_log ("Delete network [{}] successful!".format (O0OOOOOO0OO0O0OOO ['Name']))#line:108
return public .returnMsg (True ,"Successfully deleted!")#line:109
except docker .errors .APIError as OOOOOO0O00O0O0OO0 :#line:110
if " has active endpoints"in str (OOOOOO0O00O0O0OO0 ):#line:111
return public .returnMsg (False ,"The network is in use and cannot be deleted!")#line:112
return public .returnMsg (False ,"Failed to delete! {}".format (str (OOOOOO0O00O0O0OO0 )))
+135
View File
@@ -0,0 +1,135 @@
#coding: utf-8
#-------------------------------------------------------------------
# 宝塔Linux面板
#-------------------------------------------------------------------
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
#-------------------------------------------------------------------
# Author: zouhw <zhw@bt.cn>
#-------------------------------------------------------------------
#------------------------------
# Docker模型
#------------------------------
import db #line:1
import public #line:2
import json #line:3
def sql (O000O0O0O00000OO0 ):#line:5
with db .Sql ()as O000000OOO00O0000 :#line:6
O000000OOO00O0000 .dbfile ("docker")#line:7
return O000000OOO00O0000 .table (O000O0O0O00000OO0 )#line:8
def docker_client (url ="unix:///var/run/docker.sock"):#line:11
import docker #line:12
"""
目前仅支持本地服务器
:param url: unix:///var/run/docker.sock
:return:
"""#line:17
try :#line:18
O00O00O00000OO0OO =docker .DockerClient (base_url =url )#line:19
O00O00O00000OO0OO .networks .list ()#line:20
return O00O00O00000OO0OO #line:21
except :#line:22
return False #line:23
def docker_client_low (url ="unix:///var/run/docker.sock"):#line:25
""#line:30
import docker #line:31
try :#line:32
O0OO0000000O0OOOO =docker .APIClient (base_url =url )#line:33
return O0OO0000000O0OOOO #line:34
except docker .errors .DockerException :#line:35
return False #line:36
def get_cpu_count ():#line:39
import re #line:40
OOO00O00O0000O00O =open ('/proc/cpuinfo','r').read ()#line:41
OO00O0000OO000OOO ="processor\s*:"#line:42
OO0OOO0O00O0O0OOO =re .findall (OO00O0000OO000OOO ,OOO00O00O0000O00O )#line:43
if not OO0OOO0O00O0O0OOO :#line:44
return 0 #line:45
return len (OO0OOO0O00O0O0OOO )#line:46
def set_kv (OO0OO0OOO0O00O0OO ):#line:48
""#line:53
if not OO0OO0OOO0O00O0OO :#line:54
return None #line:55
O00OOOOO0O0OOOO00 =OO0OO0OOO0O00O0OO .split ('\n')#line:56
O000OOO0OO00O00OO =dict ()#line:57
for OOOOO0OO00OO0O0OO in O00OOOOO0O0OOOO00 :#line:58
OOOOO0OO00OO0O0OO =OOOOO0OO00OO0O0OO .strip ()#line:59
if not OOOOO0OO00OO0O0OO :#line:60
continue #line:61
OOO00OO000O000000 ,OO00O0O00000OOO00 =OOOOO0OO00OO0O0OO .split ('=')#line:62
O000OOO0OO00O00OO [OOO00OO000O000000 ]=OO00O0O00000OOO00 #line:63
return O000OOO0OO00O00OO #line:64
def get_mem_info ():#line:66
import psutil #line:68
O0O0OOO000OO0OOO0 =psutil .virtual_memory ()#line:69
O00OOO0O0O00O0O0O =int (O0O0OOO000OO0OOO0 .total )#line:70
return O00OOO0O0O00O0O0O #line:71
def byte_conversion (OO000000O00OOO0O0 ):#line:73
if "b"in OO000000O00OOO0O0 :#line:74
return int (OO000000O00OOO0O0 .replace ('b',''))#line:75
elif "KB"in OO000000O00OOO0O0 :#line:76
return int (OO000000O00OOO0O0 .replace ('KB',''))*1024 #line:77
elif "MB"in OO000000O00OOO0O0 :#line:78
return int (OO000000O00OOO0O0 .replace ('MB',''))*1024 *1024 #line:79
elif "GB"in OO000000O00OOO0O0 :#line:80
return int (OO000000O00OOO0O0 .replace ('GB',''))*1024 *1024 *1024 #line:81
else :#line:82
return False #line:83
def log_docker (OO000O00O0OOO0000 ,O0OO0O0O0O0OOO0O0 ):#line:85
__OO0000000OO0OO0O0 ='/tmp/dockertmp.log'#line:86
while True :#line:87
try :#line:88
O000O0OOOOO0OOOO0 =OO000O00O0OOO0000 .__next__ ()#line:89
try :#line:90
O000O0OOOOO0OOOO0 =json .loads (O000O0OOOOO0OOOO0 )#line:91
if 'status'in O000O0OOOOO0OOOO0 :#line:92
O0OOO00OO0O0OO00O ="{}\n".format (O000O0OOOOO0OOOO0 ['status'])#line:93
public .writeFile (__OO0000000OO0OO0O0 ,O0OOO00OO0O0OO00O ,'a+')#line:94
except :#line:95
public .writeFile (__OO0000000OO0OO0O0 ,public .get_error_info (),'a+')#line:96
if 'stream'in O000O0OOOOO0OOOO0 :#line:97
O0OOO00OO0O0OO00O =O000O0OOOOO0OOOO0 ['stream']#line:98
public .writeFile (__OO0000000OO0OO0O0 ,O0OOO00OO0O0OO00O ,'a+')#line:99
except StopIteration :#line:100
public .writeFile (__OO0000000OO0OO0O0 ,f'{O0OO0O0O0O0OOO0O0} complete.','a+')#line:101
break #line:102
except ValueError :#line:103
public .writeFile (log_path ,f'Error parsing output from {O0OO0O0O0O0OOO0O0}: {O000O0OOOOO0OOOO0}','a+')#line:104
def docker_conf ():#line:106
""#line:112
OO0OOO0000OO0000O =public .readFile ("{}/data/docker.conf".format (public .get_panel_path ()))#line:113
if not OO0OOO0000OO0000O :#line:114
return {"SAVE":30 }#line:115
O0O0OOOO0000OO0OO =dict ()#line:116
for OO0OOO0O0OOO000O0 in OO0OOO0000OO0000O .split ("\n"):#line:117
if not OO0OOO0O0OOO000O0 :#line:118
continue #line:119
O0OOO00O0O0OOOO00 ,OOOO00O0OOO00O00O =OO0OOO0O0OOO000O0 .split ("=")#line:120
if O0OOO00O0O0OOOO00 =="SAVE":#line:121
OOOO00O0OOO00O00O =int (OOOO00O0OOO00O00O )#line:122
O0O0OOOO0000OO0OO [O0OOO00O0O0OOOO00 ]=OOOO00O0OOO00O00O #line:123
return O0O0OOOO0000OO0OO #line:124
def get_process_id (OOOO0000O00OO00OO ,O0OO0OO0OOO0OOOOO ):#line:126
import psutil #line:127
OOOO000O0000OO0OO =psutil .pids ()#line:128
for OO000O0000OOOO0O0 in OOOO000O0000OO0OO :#line:129
try :#line:130
O0OOO0000OOOO00O0 =psutil .Process (OO000O0000OOOO0O0 )#line:131
if O0OOO0000OOOO00O0 .name ()==OOOO0000O00OO00OO and O0OO0OO0OOO0OOOOO in O0OOO0000OOOO00O0 .cmdline ():#line:132
return OO000O0000OOOO0O0 #line:133
except :#line:134
pass #line:135
return False #line:136
def write_log (OOO0OO0O0O00OO0O0 ):#line:138
public .WriteLog ("Docker module",OOO0OO0O0O00OO0O0 )#line:139
def check_socket (O0000O0O000O0O000 ):#line:141
import socket #line:142
OO0O0O0OO0OO0000O =socket .socket (socket .AF_INET ,socket .SOCK_STREAM )#line:143
O0O0OO00OOOO000O0 =("127.0.0.1",int (O0000O0O000O0O000 ))#line:144
O000O00OO00O0000O =OO0O0O0OO0OO0000O .connect_ex (O0O0OO00OOOO000O0 )#line:145
OO0O0O0OO0OO0000O .close ()#line:146
if O000O00OO00O0000O ==0 :#line:147
return True #line:148
else :#line:149
return False
@@ -0,0 +1,81 @@
#coding: utf-8
#-------------------------------------------------------------------
# 宝塔Linux面板
#-------------------------------------------------------------------
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
#-------------------------------------------------------------------
# Author: zouhw <zhw@bt.cn>
#-------------------------------------------------------------------
#------------------------------
# Docker模型
#------------------------------
import public #line:1
import os #line:2
import json #line:3
import projectModel .bt_docker .dk_public as dp #line:4
class main :#line:6
def docker_client (O0OOOO000OOOO0OOO ,O0OO0000O00OO0OO0 ):#line:8
return dp .docker_client (O0OO0000O00OO0OO0 )#line:9
def add (O0OOO0OO00OO0O0O0 ,OOO0000O0O000O0OO ):#line:11
""#line:22
if not OOO0000O0O000O0OO .registry :#line:24
OOO0000O0O000O0OO .registry ="docker.io"#line:25
O000O00O000O0O00O =O0OOO0OO00OO0O0O0 .login (OOO0000O0O000O0OO .url ,OOO0000O0O000O0OO .registry ,OOO0000O0O000O0OO .username ,OOO0000O0O000O0OO .password )#line:26
if not O000O00O000O0O00O ['status']:#line:27
return O000O00O000O0O00O #line:28
O000OO0O00OO00OOO =O0OOO0OO00OO0O0O0 .registry_list ("get")['msg']['registry']#line:29
for OOOOOOO0O000O0OOO in O000OO0O00OO00OOO :#line:30
if OOOOOOO0O000O0OOO ['name']==OOO0000O0O000O0OO .name :#line:31
return public .returnMsg (False ,"Name already exists! <br><br>Name: {}".format (OOO0000O0O000O0OO .name ))#line:32
if OOOOOOO0O000O0OOO ['username']==OOO0000O0O000O0OO .username and OOO0000O0O000O0OO .registry ==OOOOOOO0O000O0OOO ['url']:#line:33
return public .returnMsg (False ,"The repository information already exists!")#line:34
O0OO0000OOO0OO00O ={"name":OOO0000O0O000O0OO .name ,"url":OOO0000O0O000O0OO .registry ,"namespace":OOO0000O0O000O0OO .namespace ,"username":OOO0000O0O000O0OO .username ,"password":OOO0000O0O000O0OO .password ,"remark":OOO0000O0O000O0OO .remark }#line:42
dp .sql ("registry").insert (O0OO0000OOO0OO00O )#line:43
dp .write_log ("Add repository [{}] [{}] successful!".format (OOO0000O0O000O0OO .name ,OOO0000O0O000O0OO .registry ))#line:44
return public .returnMsg (True ,"Added successfully!")#line:45
def edit (O0O0O0O000O00OOO0 ,O0O000OO000000OOO ):#line:47
""#line:58
if str (O0O000OO000000OOO .id )=="1":#line:60
return public .returnMsg (False ,"[Docker official repository] cannot be edited!")#line:61
if not O0O000OO000000OOO .registry :#line:62
O0O000OO000000OOO .registry ="docker.io"#line:63
O00O00O0O0O0000OO =O0O0O0O000O00OOO0 .login (O0O000OO000000OOO .url ,O0O000OO000000OOO .registry ,O0O000OO000000OOO .username ,O0O000OO000000OOO .password )#line:64
if not O00O00O0O0O0000OO ['status']:#line:65
return O00O00O0O0O0000OO #line:66
O00O00O0O0O0000OO =dp .sql ("registry").where ("id=?",(O0O000OO000000OOO .id ,)).find ()#line:67
if not O00O00O0O0O0000OO :#line:68
return public .returnMsg (False ,"This repository was not found")#line:69
OO0OOOOO0O000OOOO ={"name":O0O000OO000000OOO .name ,"url":O0O000OO000000OOO .registry ,"username":O0O000OO000000OOO .username ,"password":O0O000OO000000OOO .password ,"namespace":O0O000OO000000OOO .namespace ,"remark":O0O000OO000000OOO .remark }#line:77
dp .sql ("registry").where ("id=?",(O0O000OO000000OOO .id ,)).update (OO0OOOOO0O000OOOO )#line:78
dp .write_log ("Editing repository [{}][{}] succeeded!".format (O0O000OO000000OOO .name ,O0O000OO000000OOO .registry ))#line:79
return public .returnMsg (True ,"Edited successfully!")#line:80
def remove (OO0OO00O00OO0O000 ,O0O00O0OO0000OO00 ):#line:82
""#line:88
if str (O0O00O0OO0000OO00 .id )=="1":#line:89
return public .returnMsg (False ,"[Docker official repository] cannot be deleted!")#line:90
OO00O0OO00000000O =dp .sql ("registry").where ("id=?",(O0O00O0OO0000OO00 .id )).find ()#line:91
dp .sql ("registry").where ("id=?",(O0O00O0OO0000OO00 .id ,)).delete ()#line:92
dp .write_log ("Deleting repository [{}][{}] succeeded!".format (OO00O0OO00000000O ['name'],OO00O0OO00000000O ['url']))#line:93
return public .returnMsg (True ,"Successfully deleted!")#line:94
def registry_list (OO0OOOO0000O00OOO ,O000OO0O00OO0O0OO ):#line:96
""#line:100
import projectModel .bt_docker .dk_setup as ds #line:101
OO0OO0000OO0O0O00 =dp .sql ("registry").select ()#line:102
if not isinstance (OO0OO0000OO0O0O00 ,list ):#line:103
OO0OO0000OO0O0O00 =[]#line:104
OOOO0OO000O000O00 =ds .main ()#line:105
OO0O0O0OOO0O0000O ={"registry":OO0OO0000OO0O0O00 ,"installed":OOOO0OO000O000O00 .check_docker_program (),"service_status":OOOO0OO000O000O00 .get_service_status ()}#line:110
return public .returnMsg (True ,OO0O0O0OOO0O0000O )#line:111
def registry_info (OOO0OO0O0OOOO0O00 ,O0OOO00O0O00000OO ):#line:113
return dp .sql ("registry").where ("name=?",(O0OOO00O0O00000OO ,)).find ()#line:114
def login (O0O0OO0O000000O00 ,OO00O00O0O0OOOOO0 ,OO0O000O000O00000 ,O0OOO000000000O00 ,O00OO0O00O000OO0O ):#line:116
""#line:121
import docker .errors #line:122
try :#line:123
O0OOO0OO00OOOOOO0 =O0O0OO0O000000O00 .docker_client (OO00O00O0O0OOOOO0 ).login (registry =OO0O000O000O00000 ,username =O0OOO000000000O00 ,password =O00OO0O00O000OO0O ,reauth =False )#line:129
return public .returnMsg (True ,str (O0OOO0OO00OOOOOO0 ))#line:130
except docker .errors .APIError as OOOO0OOO0O00O0000 :#line:131
if "unauthorized: incorrect username or password"in str (OOOO0OOO0O00O0000 ):#line:132
return public .returnMsg (False ,"Login test failed! <br><br>Reason: The account password is incorrect! {}".format (OOOO0OOO0O00O0000 ))#line:133
return public .returnMsg (False ,"Login test failed! <br><br>Reason: {}".format (OOOO0OOO0O00O0000 ))
+67
View File
@@ -0,0 +1,67 @@
#coding: utf-8
#-------------------------------------------------------------------
# 宝塔Linux面板
#-------------------------------------------------------------------
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
#-------------------------------------------------------------------
# Author: zouhw <zhw@bt.cn>
#-------------------------------------------------------------------
#------------------------------
# Docker模型
#------------------------------
import projectModel.bt_docker.dk_public as dp
import time
class main :#line:1
def get_status (O00OO00O00O0OO00O ,OOO0000O00O0OOO0O ):#line:3
""#line:9
O000OO00O0O0OOO0O =dict ()#line:10
O000OO00O0O0OOO0O ['container_count']=O00OO00O00O0OO00O .__O0OO000000O0OO0O0 (OOO0000O00O0OOO0O )#line:12
O000OO00O0O0OOO0O ['image_info']=dp .sql ("image_infos").where ("time>=? and time<=?",(OOO0000O00O0OOO0O .start_time ,OOO0000O00O0OOO0O .stop_time )).select ()#line:14
O000OO00O0O0OOO0O ['host']=len (dp .sql ('hosts').select ())#line:16
O000OO00O0O0OOO0O ['container_top']={"cpu":O00OO00O00O0OO00O .__OO0OOO00O0OOO0OOO (),"mem":O00OO00O00O0OO00O .__O0OO00OOO00O00OOO ()}#line:18
return O000OO00O0O0OOO0O #line:19
def __O0OO000000O0OO0O0 (OOOO0OO0O00O0OOOO ,OO0OO0OO000O00O0O ):#line:21
O0OOO000O0OOOO0O0 =dp .sql ('container_count').where ("time>=? and time<=?",(OO0OO0OO000O00O0O .start_time ,OO0OO0OO000O00O0O .stop_time )).select ()#line:22
if not O0OOO000O0OOOO0O0 :#line:23
return 0 #line:24
return O0OOO000O0OOOO0O0 [-1 ]#line:25
def __O0OO00OOO00O00OOO (OOO0OOO0O00OOOOO0 ):#line:27
O000OO0O00O0O00OO =int (time .time ())#line:28
O0OO0O0OO0O00O0O0 =O000OO0O00O0O00OO -3600 #line:29
OO0O000OO00OO0OOO =dp .sql ("mem_stats").where ("time>=? and time<=?",(O0OO0O0OO0O00O0O0 ,O000OO0O00O0O00OO )).select ()#line:30
O000O0OO00OOOO0O0 =list ()#line:31
O0O0O000OO00OOOOO =dict ()#line:32
for O00OOOO0OOOO00000 in OO0O000OO00OO0OOO :#line:34
O000O0OO00OOOO0O0 .append (O00OOOO0OOOO00000 ['container_id'])#line:35
O000O0OO00OOOO0O0 =set (O000O0OO00OOOO0O0 )#line:37
for OO0O0OO000OO0OO00 in O000O0OO00OOOO0O0 :#line:38
OO0000OOOOOOOO000 =0 #line:39
OO0000O00O000000O =0 #line:40
for O00OOOO0OOOO00000 in OO0O000OO00OO0OOO :#line:41
if O00OOOO0OOOO00000 ['container_id']==OO0O0OO000OO0OO00 :#line:42
OO0000OOOOOOOO000 +=1 #line:43
OO0000O00O000000O +=float (O00OOOO0OOOO00000 ['usage'])#line:44
if OO0000OOOOOOOO000 !=0 :#line:45
O0O0O000OO00OOOOO [OO0O0OO000OO0OO00 ]=OO0000O00O000000O /OO0000OOOOOOOO000 #line:46
return O0O0O000OO00OOOOO #line:47
def __OO0OOO00O0OOO0OOO (O0O0O0O000OOO000O ):#line:49
O0O0OO0OO00OO0000 =int (time .time ())#line:50
OO000OOO00OO0OOO0 =O0O0OO0OO00OO0000 -3600 #line:51
OO000O0OOOO0OO00O =dp .sql ("cpu_stats").where ("time>=? and time<=?",(OO000OOO00OO0OOO0 ,O0O0OO0OO00OO0000 )).select ()#line:52
OOO00O00O0OO0O0OO =list ()#line:53
OO0OOOOOO000OO000 =dict ()#line:54
for O0000O0O0000O0OOO in OO000O0OOOO0OO00O :#line:56
OOO00O00O0OO0O0OO .append (O0000O0O0000O0OOO ['container_id'])#line:57
OOO00O00O0OO0O0OO =set (OOO00O00O0OO0O0OO )#line:59
for OO0OO00OOOOOO0O0O in OOO00O00O0OO0O0OO :#line:60
OO00O0000000OO0OO =0 #line:61
OO0OOOO0OOOO000O0 =0 #line:62
for O0000O0O0000O0OOO in OO000O0OOOO0OO00O :#line:63
if O0000O0O0000O0OOO ['container_id']==OO0OO00OOOOOO0O0O :#line:64
OO00O0000000OO0OO +=1 #line:65
OO0OOOO0OOOO000O0 +=float (0 if O0000O0O0000O0OOO ['cpu_usage']=='0.0'else O0000O0O0000O0OOO ['cpu_usage'])#line:66
if OO00O0000000OO0OO !=0 :#line:67
OO0OOOOOO000OO000 [OO0OO00OOOOOO0O0O ]=OO0OOOO0OOOO000O0 /OO00O0000000OO0OO #line:68
return OO0OOOOOO000OO000
+155
View File
@@ -0,0 +1,155 @@
#coding: utf-8
#-------------------------------------------------------------------
# 宝塔Linux面板
#-------------------------------------------------------------------
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
#-------------------------------------------------------------------
# Author: zouhw <zhw@bt.cn>
#-------------------------------------------------------------------
#------------------------------
# Docker模型
#------------------------------
import os
import json
import public
import projectModel.bt_docker.dk_public as dp
class main :#line:1
def get_config (O0OO0OO0O0OOO0OOO ,O0OOOO000OOOO0000 ):#line:3
import projectModel .bt_docker .dk_public as dp #line:4
O00O0OOO0O0O0OO00 =O0OO0OO0O0OOO0OOO .get_registry_mirrors (O0OOOO000OOOO0000 )#line:6
if not O00O0OOO0O0O0OO00 ["status"]:#line:7
return O00O0OOO0O0O0OO00 #line:8
else :#line:9
O00O0OOO0O0O0OO00 =O00O0OOO0O0O0OO00 ['msg']#line:10
OOO00O00O00000000 =O0OO0OO0O0OOO0OOO .get_service_status ()#line:11
return public .returnMsg (True ,{"registry_mirrors":O00O0OOO0O0O0OO00 ,"service_status":OOO00O00O00000000 ,"installed":O0OO0OO0O0OOO0OOO .check_docker_program (),"monitor_status":O0OO0OO0O0OOO0OOO .get_monitor_status (),"monitor_save_date":dp .docker_conf ()['SAVE']})#line:18
def set_monitor_save_date (O0OO0000000O0OO0O ,OO0OO0O0O00OO0OOO ):#line:20
""#line:25
import re #line:26
OOOO0O0OO00O00O00 ="{}/data/docker.conf".format (public .get_panel_path ())#line:27
O00OO000O0OO0000O =public .readFile (OOOO0O0OO00O00O00 )#line:28
try :#line:29
OOO00O0000000OO0O =int (OO0OO0O0O00OO0OOO .save_date )#line:30
except :#line:31
return public .returnMsg (False ,"The monitoring save time needs to be a positive integer!")#line:32
if OOO00O0000000OO0O >999 :#line:33
return public .returnMsg (False ,"Monitoring data cannot be retained for more than 999 days!")#line:34
if not O00OO000O0OO0000O :#line:35
O00OO000O0OO0000O ="SAVE={}".format (OOO00O0000000OO0O )#line:36
public .writeFile (OOOO0O0OO00O00O00 ,O00OO000O0OO0000O )#line:37
return public .returnMsg (True ,"Set up successfully!")#line:38
O00OO000O0OO0000O =re .sub ("SAVE\s*=\s*\d+","SAVE={}".format (OOO00O0000000OO0O ),O00OO000O0OO0000O )#line:39
public .writeFile (OOOO0O0OO00O00O00 ,O00OO000O0OO0000O )#line:40
dp .write_log ("Set the monitoring time to [] days!".format (OOO00O0000000OO0O ))#line:41
return public .returnMsg (True ,"Set up successfully!")#line:42
def get_service_status (OO0O0OOOO00O0000O ):#line:44
import projectModel .bt_docker .dk_public as dp #line:45
OOOO0OO00O00O0O0O ='/var/run/docker.pid'#line:46
if os .path .exists (OOOO0OO00O00O0O0O ):#line:47
try :#line:48
O0O0O0OOO0OO0OOOO =dp .docker_client ()#line:49
if O0O0O0OOO0OO0OOOO :#line:50
return True #line:51
else :#line:52
return False #line:53
except :#line:54
return False #line:55
else :#line:56
return False #line:57
def docker_service (O00OOO000O0000O0O ,OOO00OO000000OOOO ):#line:60
""#line:65
import public #line:66
O000O0OOO0O0O000O ={'start':'start','stop':'stop','restart':'restart'}#line:67
if OOO00OO000000OOOO .act not in O000O0OOO0O0O000O :#line:68
return public .returnMsg (False ,'There is no way to do this!')#line:69
O0000OO0O0OOOOOO0 ='systemctl {} docker'.format (OOO00OO000000OOOO .act )#line:70
if OOO00OO000000OOOO .act =="stop":#line:71
O0000OO0O0OOOOOO0 +="&& systemctl {} docker.socket".format (OOO00OO000000OOOO .act )#line:72
public .ExecShell (O0000OO0O0OOOOOO0 )#line:73
dp .write_log ("Set the Docker service status to [{}] successful".format (O000O0OOO0O0O000O [OOO00OO000000OOOO .act ]))#line:74
return public .returnMsg (True ,"Set the status to [{}] successful".format (O000O0OOO0O0O000O [OOO00OO000000OOOO .act ]))#line:75
def get_registry_mirrors (O000O0OO0O00O0000 ,OO00O0OOO000O00O0 ):#line:78
try :#line:79
if not os .path .exists ('/etc/docker/daemon.json'):#line:80
return public .returnMsg (True ,[])#line:81
O00000OOOOOOOO0O0 =json .loads (public .readFile ('/etc/docker/daemon.json'))#line:82
if "registry-mirrors"not in O00000OOOOOOOO0O0 :#line:83
return public .returnMsg (True ,[])#line:84
return public .returnMsg (True ,O00000OOOOOOOO0O0 ['registry-mirrors'])#line:85
except :#line:86
return public .returnMsg (False ,'Get failed! Reason for failure: {}'.format (public .get_error_info ()))#line:87
def set_registry_mirrors (OO0OO0000OO0OOOO0 ,OOOO000OO0O00O000 ):#line:90
""#line:95
import re #line:96
try :#line:97
O0000O0O0O000O00O ={}#line:98
if os .path .exists ('/etc/docker/daemon.json'):#line:99
O0000O0O0O000O00O =json .loads (public .readFile ('/etc/docker/daemon.json'))#line:100
if not OOOO000OO0O00O000 .registry_mirrors_address .strip ():#line:101
if 'registry-mirrors'not in O0000O0O0O000O00O :#line:103
return public .returnMsg (True ,'Set successfully')#line:104
del (O0000O0O0O000O00O ['registry-mirrors'])#line:105
else :#line:106
O0O0O0O00OOOO0O0O =OOOO000OO0O00O000 .registry_mirrors_address .strip ().split ('\n')#line:107
for O0000OOO0OO0000O0 in O0O0O0O00OOOO0O0O :#line:108
if not re .search ('https?://',O0000OOO0OO0000O0 ):#line:109
return public .returnMsg (False ,'The acceleration address [{}] is malformed<br>Reference: https://mirror.ccs.tencentyun.com'.format (O0000OOO0OO0000O0 ))#line:110
O0000O0O0O000O00O ['registry-mirrors']=O0O0O0O00OOOO0O0O #line:112
public .writeFile ('/etc/docker/daemon.json',json .dumps (O0000O0O0O000O00O ,indent =2 ))#line:115
dp .write_log ("Set up Docker acceleration successfully!")#line:116
return public .returnMsg (True ,'Set successfully')#line:117
except :#line:118
return public .returnMsg (False ,'Setup failed! Reason for failure:{}'.format (public .get_error_info ()))#line:119
def get_monitor_status (OO0O00O0OO0O0O000 ):#line:121
""#line:124
O00O000O00OO00000 =public .process_exists ("python",cmdline ="/www/server/panel/class/projectModel/bt_docker/dk_monitor.py")#line:126
if O00O000O00OO00000 :#line:127
return O00O000O00OO00000 #line:128
O00O000O00OO00000 =public .process_exists ("python3",cmdline ="/www/server/panel/class/projectModel/bt_docker/dk_monitor.py")#line:129
if O00O000O00OO00000 :#line:130
return O00O000O00OO00000 #line:131
return O00O000O00OO00000 #line:132
def set_docker_monitor (OO0OOOOOOO0O00OO0 ,O0O0O0000O0OOO000 ):#line:134
""#line:139
import time #line:140
import projectModel .bt_docker .dk_public as dp #line:141
OOO000O0O0O0OOOO0 ="/www/server/panel/pyenv/bin/python"#line:142
if not os .path .exists (OOO000O0O0O0OOOO0 ):#line:143
OOO000O0O0O0OOOO0 ="/www/server/panel/pyenv/bin/python3"#line:144
O0O000O0O00O0O000 ="/www/server/panel/class/projectModel/bt_docker/dk_monitor.py"#line:145
if O0O0O0000O0OOO000 .act =="start":#line:146
OOO0O00OO0OO0O00O ="nohup {} {} &".format (OOO000O0O0O0OOOO0 ,O0O000O0O00O0O000 )#line:147
public .ExecShell (OOO0O00OO0OO0O00O )#line:148
time .sleep (1 )#line:149
if OO0OOOOOOO0O00OO0 .get_monitor_status ():#line:150
dp .write_log ("Docker monitoring started successfully!")#line:151
return public .returnMsg (True ,"Start monitoring successfully!")#line:152
return public .returnMsg (False ,"Failed to start monitoring!")#line:153
else :#line:154
O0O0OOOOOOOO0O0OO =dp .get_process_id ("python","/www/server/panel/class/projectModel/bt_docker/dk_monitor.py")#line:155
if not O0O0OOOOOOOO0O0OO :#line:156
O0O0OOOOOOOO0O0OO =dp .get_process_id ("python3","/www/server/panel/class/projectModel/bt_docker/dk_monitor.py")#line:157
public .ExecShell ("kill -9 {}".format (O0O0OOOOOOOO0O0OO ))#line:158
dp .write_log ("Docker monitoring stopped successfully!")#line:159
return public .returnMsg (True ,"Stop monitoring successfully!")#line:160
def check_docker_program (O0O00O00OOOO0O000 ):#line:162
""#line:166
O0O0O00O000OOO000 ="/usr/bin/docker"#line:167
O00OO00OO0OOOOOO0 ="/usr/bin/docker-compose"#line:168
if not os .path .exists (O0O0O00O000OOO000 )or not os .path .exists (O00OO00OO0OOOOOO0 ):#line:169
return False #line:170
return True #line:171
def install_docker_program (OOO0000OOO0O0O0O0 ,O0O000O0OO000OO0O ):#line:173
""#line:178
import time #line:179
O000O000O0OO00O00 ="Install Docker service"#line:180
O00O000OOOOOOO000 ="/bin/bash /www/server/panel/install/install_soft.sh 0 install docker_install_en"#line:183
public .M ('tasks').add ('id,name,type,status,addtime,execstr',(None ,O000O000O0OO00O00 ,'execshell','0',time .strftime ('%Y-%m-%d %H:%M:%S'),O00O000OOOOOOO000 ))#line:184
public .httpPost (public .GetConfigValue ('home')+'/api/panel/plugin_total',{"pid":"1111111",'p_name':"Docker商用模块"},3 )#line:185
public.arequests('post', 'https://www.aapanel.com/api/setupCount/setupPlugin',
data={"pid": "1111111", 'p_name': "Dockerpaymodel"}, timeout=3)
return public .returnMsg (True ,"Install task added to queue!")#line:186
+160
View File
@@ -0,0 +1,160 @@
#coding: utf-8
#-------------------------------------------------------------------
# 宝塔Linux面板
#-------------------------------------------------------------------
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
#-------------------------------------------------------------------
# Author: zouhw <zhw@bt.cn>
#-------------------------------------------------------------------
#------------------------------
# Docker模型
#------------------------------
import public #line:13
import time #line:14
import projectModel .bt_docker .dk_public as dp #line:15
class main :#line:18
__OOOO00OOO0O00O0O0 =dict ()#line:20
__OO0O0O00OO0OOO000 =None #line:21
def docker_client (OOOOOO000OOOO0OOO ,OO0OOO0O0O00O0000 ):#line:23
if not OOOOOO000OOOO0OOO .__OO0O0O00OO0OOO000 :#line:24
OOOOOO000OOOO0OOO .__OO0O0O00OO0OOO000 =dp .docker_client (OO0OOO0O0O00O0000 )#line:25
return OOOOOO000OOOO0OOO .__OO0O0O00OO0OOO000 #line:26
def io_stats (O00OOOOO000OO00OO ,O00O0OO0000OO0O0O ,write =None ):#line:28
O0O0OO0OOO0OO0000 =O00O0OO0000OO0O0O ['blkio_stats']['io_service_bytes_recursive']#line:29
if len (O0O0OO0OOO0OO0000 )<=2 :#line:30
try :#line:31
O0OO0OO0O000OOOOO =O0O0OO0OOO0OO0000 [0 ]['value']#line:32
O00OOOOO000OO00OO .__OOOO00OOO0O00O0O0 ['read_total']=O0OO0OO0O000OOOOO #line:33
except :#line:34
O00OOOOO000OO00OO .__OOOO00OOO0O00O0O0 ['read_total']=0 #line:35
try :#line:36
O0OO0OO0O000OOOOO =O0O0OO0OOO0OO0000 [1 ]['value']#line:37
O00OOOOO000OO00OO .__OOOO00OOO0O00O0O0 ['write_total']=O0OO0OO0O000OOOOO #line:38
except :#line:39
O00OOOOO000OO00OO .__OOOO00OOO0O00O0O0 ['write_total']=0 #line:40
else :#line:41
try :#line:42
O0OO0OO0O000OOOOO =O0O0OO0OOO0OO0000 [0 ]['value']+O0O0OO0OOO0OO0000 [2 ]['value']#line:43
O00OOOOO000OO00OO .__OOOO00OOO0O00O0O0 ['read_total']=O0OO0OO0O000OOOOO #line:44
except :#line:45
O00OOOOO000OO00OO .__OOOO00OOO0O00O0O0 ['read_total']=0 #line:46
try :#line:47
O0OO0OO0O000OOOOO =O0O0OO0OOO0OO0000 [1 ]['value']+O0O0OO0OOO0OO0000 [3 ]['value']#line:48
O00OOOOO000OO00OO .__OOOO00OOO0O00O0O0 ['write_total']=O0OO0OO0O000OOOOO #line:49
except :#line:50
O00OOOOO000OO00OO .__OOOO00OOO0O00O0O0 ['write_total']=0 #line:51
if write :#line:52
O00OOOOO000OO00OO .__OOOO00OOO0O00O0O0 ['container_id']=O00O0OO0000OO0O0O ['id']#line:53
O00OOOOO000OO00OO .write_io (O00OOOOO000OO00OO .__OOOO00OOO0O00O0O0 )#line:54
def net_stats (OOO0000O0O0O00O0O ,O0O0OOO00O0000OOO ,OO0O0O000OOO000OO ,write =None ):#line:56
try :#line:57
OO00OOOO0O0000OOO =O0O0OOO00O0000OOO ['networks']['eth0']#line:58
OOO00O00O0O00OOOO =OO0O0O000OOO000OO ['networks']['eth0']#line:59
except :#line:60
OOO0000O0O0O00O0O .__OOOO00OOO0O00O0O0 ['rx_total']=0 #line:61
OOO0000O0O0O00O0O .__OOOO00OOO0O00O0O0 ['rx']=0 #line:62
OOO0000O0O0O00O0O .__OOOO00OOO0O00O0O0 ['tx_total']=0 #line:63
OOO0000O0O0O00O0O .__OOOO00OOO0O00O0O0 ['tx']=0 #line:64
if write :#line:65
OOO0000O0O0O00O0O .__OOOO00OOO0O00O0O0 ['container_id']=O0O0OOO00O0000OOO ['id']#line:66
OOO0000O0O0O00O0O .write_net (OOO0000O0O0O00O0O .__OOOO00OOO0O00O0O0 )#line:67
return #line:68
O0000OO00OO0OOO00 =O0O0OOO00O0000OOO ["time"]#line:69
O0000OO0OO0OOOOOO =OO0O0O000OOO000OO ["time"]#line:70
try :#line:71
O0O000O00O0OO0OO0 =OO00OOOO0O0000OOO ["rx_bytes"]#line:72
OOO0000O0O0O00O0O .__OOOO00OOO0O00O0O0 ['rx_total']=O0O000O00O0OO0OO0 #line:73
O0000OOO0OO00OOO0 =OOO00O00O0O00OOOO ["rx_bytes"]#line:74
OOO0000O0O0O00O0O .__OOOO00OOO0O00O0O0 ['rx']=int ((O0O000O00O0OO0OO0 -O0000OOO0OO00OOO0 )/(O0000OO00OO0OOO00 -O0000OO0OO0OOOOOO ))#line:75
except :#line:76
OOO0000O0O0O00O0O .__OOOO00OOO0O00O0O0 ['rx_total']=0 #line:77
OOO0000O0O0O00O0O .__OOOO00OOO0O00O0O0 ['rx']=0 #line:78
try :#line:79
O0O000O00O0OO0OO0 =OO00OOOO0O0000OOO ["tx_bytes"]#line:80
O0000OOO0OO00OOO0 =OOO00O00O0O00OOOO ["tx_bytes"]#line:81
OOO0000O0O0O00O0O .__OOOO00OOO0O00O0O0 ['tx_total']=O0O000O00O0OO0OO0 #line:82
OOO0000O0O0O00O0O .__OOOO00OOO0O00O0O0 ['tx']=int ((O0O000O00O0OO0OO0 -O0000OOO0OO00OOO0 )/(O0000OO00OO0OOO00 -O0000OO0OO0OOOOOO ))#line:83
except :#line:84
OOO0000O0O0O00O0O .__OOOO00OOO0O00O0O0 ['tx_total']=0 #line:85
OOO0000O0O0O00O0O .__OOOO00OOO0O00O0O0 ['tx']=0 #line:86
if write :#line:87
OOO0000O0O0O00O0O .__OOOO00OOO0O00O0O0 ['container_id']=O0O0OOO00O0000OOO ['id']#line:88
OOO0000O0O0O00O0O .write_net (OOO0000O0O0O00O0O .__OOOO00OOO0O00O0O0 )#line:89
def mem_stats (O0OO000OOO0O0O000 ,O00OOO0OO00OOO000 ,write =None ):#line:92
OOO0000OO0OOO000O =O00OOO0OO00OOO000 ['memory_stats']#line:93
try :#line:94
O0OO000OOO0O0O000 .__OOOO00OOO0O00O0O0 ['limit']=OOO0000OO0OOO000O ['limit']#line:95
O0OO000OOO0O0O000 .__OOOO00OOO0O00O0O0 ['usage_total']=OOO0000OO0OOO000O ['usage']#line:96
if 'cache'not in OOO0000OO0OOO000O ['stats']:#line:97
OOO0000OO0OOO000O ['stats']['cache']=0 #line:98
O0OO000OOO0O0O000 .__OOOO00OOO0O00O0O0 ['usage']=OOO0000OO0OOO000O ['usage']-OOO0000OO0OOO000O ['stats']['cache']#line:99
O0OO000OOO0O0O000 .__OOOO00OOO0O00O0O0 ['cache']=OOO0000OO0OOO000O ['stats']['cache']#line:100
except :#line:102
O0OO000OOO0O0O000 .__OOOO00OOO0O00O0O0 ['limit']=0 #line:104
O0OO000OOO0O0O000 .__OOOO00OOO0O00O0O0 ['usage']=0 #line:105
O0OO000OOO0O0O000 .__OOOO00OOO0O00O0O0 ['cache']=0 #line:106
O0OO000OOO0O0O000 .__OOOO00OOO0O00O0O0 ['usage_total']=0 #line:107
if write :#line:109
O0OO000OOO0O0O000 .__OOOO00OOO0O00O0O0 ['container_id']=O00OOO0OO00OOO000 ['id']#line:110
O0OO000OOO0O0O000 .write_mem (O0OO000OOO0O0O000 .__OOOO00OOO0O00O0O0 )#line:111
def cpu_stats (OO0OO000OO000O000 ,OO0000OOO00OO0O0O ,write =None ):#line:114
try :#line:120
OOOOO0O0OO0O00O0O =OO0000OOO00OO0O0O ['cpu_stats']['cpu_usage']['total_usage']-OO0000OOO00OO0O0O ['precpu_stats']['cpu_usage']['total_usage']#line:121
except :#line:122
OOOOO0O0OO0O00O0O =0 #line:123
try :#line:124
OO00000O0O0OO0O00 =OO0000OOO00OO0O0O ['cpu_stats']['system_cpu_usage']-OO0000OOO00OO0O0O ['precpu_stats']['system_cpu_usage']#line:125
except :#line:126
OO00000O0O0OO0O00 =0 #line:127
try :#line:128
OO0OO000OO000O000 .__OOOO00OOO0O00O0O0 ['online_cpus']=OO0000OOO00OO0O0O ['cpu_stats']['online_cpus']#line:129
except :#line:130
OO0OO000OO000O000 .__OOOO00OOO0O00O0O0 ['online_cpus']=0 #line:131
if OOOOO0O0OO0O00O0O >0 and OO00000O0O0OO0O00 >0 :#line:132
OO0OO000OO000O000 .__OOOO00OOO0O00O0O0 ['cpu_usage']=round ((OOOOO0O0OO0O00O0O /OO00000O0O0OO0O00 )*100 *OO0OO000OO000O000 .__OOOO00OOO0O00O0O0 ['online_cpus'],2 )#line:133
else :#line:134
OO0OO000OO000O000 .__OOOO00OOO0O00O0O0 ['cpu_usage']=0.0 #line:135
if write :#line:136
OO0OO000OO000O000 .__OOOO00OOO0O00O0O0 ['container_id']=OO0000OOO00OO0O0O ['id']#line:137
OO0OO000OO000O000 .write_cpu (OO0OO000OO000O000 .__OOOO00OOO0O00O0O0 )#line:138
def stats (OO0OOOO00OO0OO000 ,OO00OO0OO00OOO0O0 ):#line:141
""#line:148
OOOOO00O00000OOO0 =OO0OOOO00OO0OO000 .docker_client (OO00OO0OO00OOO0O0 .url ).containers .get (OO00OO0OO00OOO0O0 .id )#line:149
O00O0OOOO000O0O0O =OOOOO00O00000OOO0 .stats (decode =None ,stream =False )#line:150
O00O0OOOO000O0O0O ['time']=time .time ()#line:151
OOOOOOOOO0OO0O00O =public .cache_get ('stats')#line:152
if not OOOOOOOOO0OO0O00O :#line:153
OOOOOOOOO0OO0O00O =O00O0OOOO000O0O0O #line:154
public .cache_set ('stats',O00O0OOOO000O0O0O )#line:155
OOO000O0000O0OO0O =None #line:156
if hasattr (OO00OO0OO00OOO0O0 ,"write"):#line:157
OOO000O0000O0OO0O =OO00OO0OO00OOO0O0 .write #line:158
OO0OOOO00OO0OO000 .__OOOO00OOO0O00O0O0 ['expired']=time .time ()-(OO00OO0OO00OOO0O0 .save_date *86400 )#line:159
O00O0OOOO000O0O0O ['id']=OO00OO0OO00OOO0O0 .id #line:160
OO0OOOO00OO0OO000 .io_stats (O00O0OOOO000O0O0O ,OOO000O0000O0OO0O )#line:161
OO0OOOO00OO0OO000 .net_stats (O00O0OOOO000O0O0O ,OOOOOOOOO0OO0O00O ,OOO000O0000O0OO0O )#line:162
OO0OOOO00OO0OO000 .cpu_stats (O00O0OOOO000O0O0O ,OOO000O0000O0OO0O )#line:163
OO0OOOO00OO0OO000 .mem_stats (O00O0OOOO000O0O0O ,OOO000O0000O0OO0O )#line:164
public .cache_set ('stats',O00O0OOOO000O0O0O )#line:165
OO0OOOO00OO0OO000 .__OOOO00OOO0O00O0O0 ['detail']=O00O0OOOO000O0O0O #line:166
return public .returnMsg (True ,OO0OOOO00OO0OO000 .__OOOO00OOO0O00O0O0 )#line:167
def write_cpu (O0OOO000OOOO00OO0 ,OO0O0O0OO0OOO0000 ):#line:169
OOOO0OO0OOOO00O00 ={"time":time .time (),"cpu_usage":OO0O0O0OO0OOO0000 ['cpu_usage'],"online_cpus":OO0O0O0OO0OOO0000 ['online_cpus'],"container_id":OO0O0O0OO0OOO0000 ['container_id']}#line:175
dp .sql ("cpu_stats").where ("time<?",(O0OOO000OOOO00OO0 .__OOOO00OOO0O00O0O0 ['expired'],)).delete ()#line:176
dp .sql ("cpu_stats").insert (OOOO0OO0OOOO00O00 )#line:177
def write_io (OOOO00O0O00OO0OO0 ,OOOOO000OOOOO00O0 ):#line:179
O000OO0O000OOOOOO ={"time":time .time (),"write_total":OOOOO000OOOOO00O0 ['write_total'],"read_total":OOOOO000OOOOO00O0 ['read_total'],"container_id":OOOOO000OOOOO00O0 ['container_id']}#line:185
dp .sql ("io_stats").where ("time<?",(OOOO00O0O00OO0OO0 .__OOOO00OOO0O00O0O0 ['expired'],)).delete ()#line:186
dp .sql ("io_stats").insert (O000OO0O000OOOOOO )#line:187
def write_net (O0000000OO0O00OO0 ,O0O0O00O0OO0OO0O0 ):#line:189
O00O00OO0OO0OOOOO ={"time":time .time (),"tx_total":O0O0O00O0OO0OO0O0 ['tx_total'],"rx_total":O0O0O00O0OO0OO0O0 ['rx_total'],"tx":O0O0O00O0OO0OO0O0 ['tx'],"rx":O0O0O00O0OO0OO0O0 ['rx'],"container_id":O0O0O00O0OO0OO0O0 ['container_id']}#line:197
dp .sql ("net_stats").where ("time<?",(O0000000OO0O00OO0 .__OOOO00OOO0O00O0O0 ['expired'],)).delete ()#line:198
dp .sql ("net_stats").insert (O00O00OO0OO0OOOOO )#line:199
def write_mem (OO0O00O0O000O00OO ,O0000OO0O0OOO00OO ):#line:201
O00OOOOOOO000O00O ={"time":time .time (),"mem_limit":O0000OO0O0OOO00OO ['limit'],"cache":O0000OO0O0OOO00OO ['cache'],"usage":O0000OO0O0OOO00OO ['usage'],"usage_total":O0000OO0O0OOO00OO ['usage_total'],"container_id":O0000OO0O0OOO00OO ['container_id']}#line:209
dp .sql ("mem_stats").where ("time<?",(OO0O00O0O000O00OO .__OOOO00OOO0O00O0O0 ['expired'],)).delete ()#line:210
dp .sql ("mem_stats").insert (O00OOOOOOO000O00O )#line:211
def get_container_count (O0OO00O0OOO0O0000 ,OO0OOOOOO0OO0O0OO ):#line:214
O0O00OO0O0OOOO000 =OO0OOOOOO0OO0O0OO .url #line:215
return len (O0OO00O0OOO0O0000 .docker_client (O0O00OO0O0OOOO000 ).containers .list ())#line:216
+73
View File
@@ -0,0 +1,73 @@
#coding: utf-8
#-------------------------------------------------------------------
# 宝塔Linux面板
#-------------------------------------------------------------------
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
#-------------------------------------------------------------------
# Author: zouhw <zhw@bt.cn>
#-------------------------------------------------------------------
#------------------------------
# Docker模型
#------------------------------
import public
import projectModel.bt_docker.dk_public as dp
import docker.errors
class main :#line:1
__O0O0O00O00OOO00O0 =None #line:3
def docker_client (OO0000OOOO0O00000 ,O00000O0O00OO0O0O ):#line:5
import projectModel .bt_docker .dk_public as dp #line:6
return dp .docker_client (O00000O0O00OO0O0O )#line:7
def get_volume_container_name (O0O000O0OOO00O0O0 ,O0O00OOOOO0O0O00O ):#line:10
OO000OO00OOOOOOO0 =O0O000O0OOO00O0O0 .docker_client (O0O000O0OOO00O0O0 .__O0O0O00O00OOO00O0 ).containers #line:11
O0O0OOOO00000OO0O =OO000OO00OOOOOOO0 .list (all =True )#line:12
O0000O00OOOO00O00 =[O000OO00OOOO00O0O .attrs for O000OO00OOOO00O0O in O0O0OOOO00000OO0O ]#line:14
for O00OOO00000OO0OOO in O0000O00OOOO00O00 :#line:15
if not O00OOO00000OO0OOO ['Mounts']:#line:16
continue #line:17
for O0O00O0O0OOO000OO in O00OOO00000OO0OOO ['Mounts']:#line:18
if "Name"not in O0O00O0O0OOO000OO :#line:19
continue #line:20
if O0O00OOOOO0O0O00O ['Name']==O0O00O0O0OOO000OO ['Name']:#line:21
O0O00OOOOO0O0O00O ['container']=O00OOO00000OO0OOO ['Name'].replace ("/","")#line:22
if 'container'not in O0O00OOOOO0O0O00O :#line:23
O0O00OOOOO0O0O00O ['container']=''#line:24
return O0O00OOOOO0O0O00O #line:25
def get_volume_list (O0O0OOO0OO000000O ,OO0OO0O0OOOO0OO0O ):#line:27
""#line:31
import projectModel .bt_docker .dk_setup as ds #line:32
O0O0OOO0OO000000O .__O0O0O00O00OOO00O0 =OO0OO0O0OOOO0OO0O .url #line:33
O0O0O0OOO0OOO0O00 =O0O0OOO0OO000000O .docker_client (OO0OO0O0OOOO0OO0O .url )#line:34
O0O000O0OOOOOO00O =ds .main ()#line:35
OO0OO00000OOOOOO0 =O0O000O0OOOOOO00O .check_docker_program ()#line:36
OOOOO0OOOO000OOOO =O0O000O0OOOOOO00O .get_service_status ()#line:37
if not O0O0O0OOO0OOO0O00 :#line:38
O000O0000OOO000OO ={"volume":[],"installed":OO0OO00000OOOOOO0 ,"service_status":OOOOO0OOOO000OOOO }#line:43
return public .returnMsg (True ,O000O0000OOO000OO )#line:44
OO00O00OOO0O000O0 =O0O0O0OOO0OOO0O00 .volumes #line:45
O000O0000OOO000OO ={"volume":O0O0OOO0OO000000O .get_volume_attr (OO00O00OOO0O000O0 ),"installed":OO0OO00000OOOOOO0 ,"service_status":OOOOO0OOOO000OOOO }#line:51
return public .returnMsg (True ,O000O0000OOO000OO )#line:52
def get_volume_attr (O00O000OO00000O00 ,O0O0OO0OO0OO0O0OO ):#line:54
OOO00O0O0000O0O0O =O0O0OO0OO0OO0O0OO .list ()#line:55
O00O00OOOOO00O000 =list ()#line:56
for OO0OOOOOOOOO0OO00 in OOO00O0O0000O0O0O :#line:57
OO0OOOOOOOOO0OO00 =O00O000OO00000O00 .get_volume_container_name (OO0OOOOOOOOO0OO00 .attrs )#line:58
O00O00OOOOO00O000 .append (OO0OOOOOOOOO0OO00 )#line:59
return O00O00OOOOO00O000 #line:60
def add (O000O0OOOO0O0OOOO ,O0OO00O0O0OO0O0OO ):#line:62
""#line:70
O000O0OOOO0O0OOOO .docker_client (O0OO00O0O0OO0O0OO .url ).volumes .create (name =O0OO00O0O0OO0O0OO .name ,driver =O0OO00O0O0OO0O0OO .driver ,driver_opts =O0OO00O0O0OO0O0OO .driver_opts if O0OO00O0O0OO0O0OO .driver_opts else None ,labels =dp .set_kv (O0OO00O0O0OO0O0OO .labels ))#line:76
dp .write_log ("Adding storage volume [[]] succeeded!".format (O0OO00O0O0OO0O0OO .name ))#line:77
return public .returnMsg (True ,"Added successfully!")#line:78
def remove (O0OOO000000OO0OOO ,O0OO00OO0OOO00000 ):#line:80
""#line:86
try :#line:87
O0000O0OO000O0O0O =O0OOO000000OO0OOO .docker_client (O0OO00OO0OOO00000 .url ).volumes .get (O0OO00OO0OOO00000 .name )#line:88
O0000O0OO000O0O0O .remove ()#line:89
dp .write_log ("Delete storage volume [[]] successful!".format (O0OO00OO0OOO00000 .name ))#line:90
return public .returnMsg (True ,"Successfully deleted")#line:91
except docker .errors .APIError as OO00OO0O000O0O0O0 :#line:92
if "volume is in use"in str (OO00OO0O000O0O0O0 ):#line:93
return public .returnMsg (False ,"Storage volume is in use and cannot be deleted!")#line:94
return public .returnMsg (False ,"Failed to delete! {}".format (OO00OO0O000O0O0O0 ))#line:95
+58
View File
@@ -0,0 +1,58 @@
# coding: utf-8
# -------------------------------------------------------------------
# 宝塔Linux面板
# -------------------------------------------------------------------
# Copyright (c) 2015-2017 宝塔软件(http:#bt.cn) All rights reserved.
# -------------------------------------------------------------------
# Author: zouhw <zhw@bt.cn>
# -------------------------------------------------------------------
# ------------------------------
# 项目管理控制器
# ------------------------------
import os ,public ,json ,re ,time #line:13
class main :#line:15
def __init__ (O00000000O0OO000O ):#line:17
pass #line:18
def model (O0O0OOO0OO0OO00OO ,OO0O0O000O00O00O0 ):#line:20
""#line:29
import panelPlugin #line:30
OO00OO0OOOO0OO0O0 =public .to_dict_obj ({})#line:31
OO00OO0OOOO0OO0O0 .focre =1 #line:32
O0OO000000O0000O0 =panelPlugin .panelPlugin ().get_soft_list (OO00OO0OOOO0OO0O0 )#line:33
__OO000O0000OO000OO =int (O0OO000000O0000O0 ['ltd'])>1 #line:34
try :#line:40
OO0O0O000O00O00O0 .def_name =OO0O0O000O00O00O0 .dk_def_name #line:41
OO0O0O000O00O00O0 .mod_name =OO0O0O000O00O00O0 .dk_model_name #line:42
if OO0O0O000O00O00O0 ['mod_name']in ['base']:return public .return_status_code (1000 ,'Wrong call!')#line:43
public .exists_args ('def_name,mod_name',OO0O0O000O00O00O0 )#line:44
if OO0O0O000O00O00O0 ['def_name'].find ('__')!=-1 :return public .return_status_code (1000 ,'The called method name cannot contain the "__" characterrong call!')#line:45
if not re .match (r"^\w+$",OO0O0O000O00O00O0 ['mod_name']):return public .return_status_code (1000 ,'The called module name cannot contain characters other than \w')#line:46
if not re .match (r"^\w+$",OO0O0O000O00O00O0 ['def_name']):return public .return_status_code (1000 ,'The called module name cannot contain characters other than \w')#line:47
except :#line:48
return public .get_error_object ()#line:49
O0OOO0O0O00O00O0O ="dk_{}".format (OO0O0O000O00O00O0 ['mod_name'].strip ())#line:51
OO00OO0OOOO0OOOOO =OO0O0O000O00O00O0 ['def_name'].strip ()#line:52
OO00OO0O0OOOOO000 ="{}/projectModel/bt_docker/{}.py".format (public .get_class_path (),O0OOO0O0O00O00O0O )#line:55
if not os .path .exists (OO00OO0O0OOOOO000 ):#line:56
return public .return_status_code (1003 ,O0OOO0O0O00O00O0O )#line:57
OO00O00OOOOOO0000 =public .get_script_object (OO00OO0O0OOOOO000 )#line:59
if not OO00O00OOOOOO0000 :return public .return_status_code (1000 ,'{} model not found'.format (O0OOO0O0O00O00O0O ))#line:60
OOO0O000O0OOOOO0O =getattr (OO00O00OOOOOO0000 .main (),OO00OO0OOOO0OOOOO ,None )#line:61
if not OOO0O000O0OOOOO0O :return public .return_status_code (1000 ,'{} method not found in {} model'.format (O0OOO0O0O00O00O0O ,OO00OO0OOOO0OOOOO ))#line:62
O00O0O00O000O0000 ='{}_{}_LAST'.format (O0OOO0O0O00O00O0O .upper (),OO00OO0OOOO0OOOOO .upper ())#line:76
O0OO0OOOOO00OOOO0 =public .exec_hook (O00O0O00O000O0000 ,OO0O0O000O00O00O0 )#line:77
if isinstance (O0OO0OOOOO00OOOO0 ,public .dict_obj ):#line:78
OOO0OOOOOOO000O0O =O0OO0OOOOO00OOOO0 #line:79
elif isinstance (O0OO0OOOOO00OOOO0 ,dict ):#line:80
return O0OO0OOOOO00OOOO0 #line:81
elif isinstance (O0OO0OOOOO00OOOO0 ,bool ):#line:82
if not O0OO0OOOOO00OOOO0 :#line:83
return public .return_data (False ,{},error_msg ='Pre-HOOK interrupt operation')#line:84
OO000OOOO000OOO0O =OOO0O000O0OOOOO0O (OO0O0O000O00O00O0 )#line:87
O00O0O00O000O0000 ='{}_{}_END'.format (O0OOO0O0O00O00O0O .upper (),OO00OO0OOOO0OOOOO .upper ())#line:90
O0O000OO0O00O0OOO =public .to_dict_obj ({'args':OO0O0O000O00O00O0 ,'result':OO000OOOO000OOO0O })#line:94
O0OO0OOOOO00OOOO0 =public .exec_hook (O00O0O00O000O0000 ,O0O000OO0O00O0OOO )#line:95
if isinstance (O0OO0OOOOO00OOOO0 ,dict ):#line:96
OO000OOOO000OOO0O =O0OO0OOOOO00OOOO0 ['result']#line:97
return OO000OOOO000OOO0O #line:98
+18 -4
View File
@@ -123,6 +123,12 @@ class main(projectBase):
if not os.path.exists(self._nodejs_path): return nodejs_list
for v in os.listdir(self._nodejs_path):
if v[0] != 'v' or v.find('.') == -1: continue
node_path = os.path.join(self._nodejs_path,v)
node_bin = '{}/bin/node'.format(node_path)
if not os.path.exists(node_bin):
if os.path.exists(node_path + '/bin'):
public.ExecShell('rm -rf {}'.format(node_path))
continue
nodejs_list.append(v)
return nodejs_list
@@ -193,12 +199,12 @@ class main(projectBase):
_bin = '{}/node_modules/.bin'.format(project_cwd)
if os.path.exists(_bin):
nodejs_bin_path = _bin + ':' + nodejs_bin_path
last_env = '''PATH={nodejs_bin_path}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
'''.format(nodejs_bin_path = nodejs_bin_path)
return last_env
def install_packages(self,get):
'''
@@ -658,7 +664,7 @@ export PATH
'''
project_find = self.get_project_find(get.project_name)
if not project_find:
return public.return_error('The specified item does not exist')
return public.return_error('The specified item does not exist',data='')
project_id = project_find['id']
domains = get.domains
@@ -1297,6 +1303,7 @@ echo $! > {pid_file}
n+=1
if not os.path.exists(pid_file):
p = '\n'.join(p)
public.writeFile(log_file,p,"a+")
if p.find('[Errno 0]') != -1:
if os.path.exists('{}/bt_security'.format(public.get_plugin_path())):
return public.return_error('The start command was intercepted by [Fort Tower Defense Privilege], please turn off {} user protection'.format(project_find['project_config']['run_user']))
@@ -1369,6 +1376,11 @@ cd {}
if not res['status']: return res
return public.return_data(True, 'Successful restart')
# xss 防御
def xsssec(self,text):
return text.replace('<', '&lt;').replace('>', '&gt;')
def get_project_log(self,get):
'''
@name 获取项目日志
@@ -1380,7 +1392,7 @@ cd {}
'''
log_file = "{}/{}.log".format(self._node_logs_path,get.project_name)
if not os.path.exists(log_file): return public.return_error('Log file does not exist')
return public.GetNumLines(log_file,200)
return self.xsssec(public.GetNumLines(log_file,200))
def get_project_load_info(self,get = None,project_name = None):
@@ -1528,8 +1540,10 @@ cd {}
@param p: Process<进程对像>
@return list
'''
skey = "io_speed_{}".format(p.pid)
old_pio = cache.get(skey)
if not hasattr(p,'io_counters'): return 0,0
pio = p.io_counters()
if not old_pio:
cache.set(skey,[pio,time.time()],3600)
+304
View File
@@ -0,0 +1,304 @@
#coding: utf-8
#-------------------------------------------------------------------
# 宝塔Linux面板
#-------------------------------------------------------------------
# Copyright (c) 2015-2017 宝塔软件(http:#bt.cn) All rights reserved.
#-------------------------------------------------------------------
# Author: hwliang <hwl@bt.cn>
#-------------------------------------------------------------------
#------------------------------
# 磁盘配额管理
#------------------------------
import os ,public ,psutil ,json ,time ,re
from projectModel .base import projectBase
class main (projectBase ):
xfs_quota ="xfs_quota"
__O0O000000OO000000 ='{}/config/quota.json'.format (public .get_panel_path ())
__O00OOOO00OO0OO0OO ='{}/config/mysql_quota.json'.format (public .get_panel_path ())
__O0O00000000OOO0O0 =public .to_string ([84 ,104 ,105 ,115 ,32 ,102 ,101 ,97 ,116 ,117 ,114 ,101 ,32 ,105 ,115 ,32 ,101 ,120 ,99 ,108 ,117 ,115 ,105 ,118 ,101 ,32 ,116 ,111 ,32 ,116 ,104 ,101 ,32 ,112 ,114 ,111 ,32 ,101 ,100 ,105 ,116 ,105 ,111 ,110 ,44 ,32 ,112 ,108 ,101 ,97 ,115 ,101 ,32 ,97 ,99 ,116 ,105 ,118 ,97 ,116 ,101 ,32 ,105 ,116 ,32 ,102 ,105 ,114 ,115 ,116 ])
def __init__ (OOO0000OO0OO0O00O ):
_O0OOO0O00O0O0O000 ='{}/data/quota_install.pl'.format (public .get_panel_path ())
if not os .path .exists (_O0OOO0O00O0O0O000 ):
O0OO0OOO0OO0O0O00 ='/usr/sbin/xfs_quota'
if not os .path .exists (O0OO0OOO0OO0O0O00 ):
if os .path .exists ('/usr/bin/apt-get'):
public .ExecShell ('nohup apt-get install xfsprogs -y > /dev/null &')
else :
public .ExecShell ('nohup yum install xfsprogs -y > /dev/null &')
public .writeFile (_O0OOO0O00O0O0O000 ,'True')
if os .path .exists ("/sbin/xfs_quota"):
OOO0000OO0OO0O00O .xfs_quota ="/sbin/xfs_quota"
def __OO00OO00O0000O0OO (O00OOO0000000000O ,args =None ):
""
OO00000OO0O00O0O0 =[]
for OO00O0OO0O0000OOO in psutil .disk_partitions ():
if OO00O0OO0O0000OOO .fstype =='xfs':
OO00000OO0O00O0O0 .append ((OO00O0OO0O0000OOO .mountpoint ,OO00O0OO0O0000OOO .device ,psutil .disk_usage (OO00O0OO0O0000OOO .mountpoint ).free ,OO00O0OO0O0000OOO .opts .split (',')))
return OO00000OO0O00O0O0
def __O00OOOO0OO00O0OO0 (O000O00O0O0000O00 ,args =None ):
""
return O000O00O0O0000O00 .__O000O0O0000OOOOOO (args .path )
def __O000000O0O0000OOO (O00OOO00000OOOO00 ,O000O00O00O00OOOO ):
""
O0OOO000OO000OOO0 =O00OOO00000OOOO00 .__OO00OO00O0000O0OO ()
OO0OO000OO00O0OO0 =None
for O0O0OOOO00O00OOO0 in O0OOO000OO000OOO0 :
if O0O0OOOO00O00OOO0 [0 ]=="/":
OO0OO000OO00O0OO0 =O0O0OOOO00O00OOO0
if O000O00O00O00OOOO .find (O0O0OOOO00O00OOO0 [0 ]+'/')==0 :
if not 'prjquota'in O0O0OOOO00O00OOO0 [3 ]:
return O0O0OOOO00O00OOO0
return O0O0OOOO00O00OOO0 [1 ]
if OO0OO000OO00O0OO0 and O000O00O00O00OOOO .find (OO0OO000OO00O0OO0 [0 ])==0 :
if not 'prjquota'in OO0OO000OO00O0OO0 [3 ]:
return OO0OO000OO00O0OO0
return OO0OO000OO00O0OO0 [1 ]
return ''
def __O000O0O0000OOOOOO (OO0OOO00OO000000O ,O0O0O0OOOOO0OOO0O ):
""
if not os .path .exists (O0O0O0OOOOO0OOO0O ):return -1
if not os .path .isdir (O0O0O0OOOOO0OOO0O ):return -2
OO0O0OO0O0000000O =OO0OOO00OO000000O .__OO00OO00O0000O0OO ()
O0O00OO00O0O0O00O =None
for O0OO0O0O00O00OO00 in OO0O0OO0O0000000O :
if O0OO0O0O00O00OO00 [0 ]=="/":
O0O00OO00O0O0O00O =O0OO0O0O00O00OO00
if O0O0O0OOOOO0OOO0O .find (O0OO0O0O00O00OO00 [0 ]+'/')==0 :
return O0OO0O0O00O00OO00 [2 ]/1024 /1024
if O0O00OO00O0O0O00O and O0O0O0OOOOO0OOO0O .find (O0O00OO00O0O0O00O [0 ])==0 :
return O0O00OO00O0O0O00O [2 ]/1024 /1024
return -3
def get_quota_path_list (OOOO000OO000O000O ,args =None ,get_path =None ):
""
if not os .path .exists (OOOO000OO000O000O .__O0O000000OO000000 ):
public .writeFile (OOOO000OO000O000O .__O0O000000OO000000 ,'[]')
O00OO00OO000O0OO0 =json .loads (public .readFile (OOOO000OO000O000O .__O0O000000OO000000 ))
OO00OOO0O00OOOO00 =[]
for O0OOOO0O0O000O0O0 in O00OO00OO000O0OO0 :
if not os .path .exists (O0OOOO0O0O000O0O0 ['path'])or not os .path .isdir (O0OOOO0O0O000O0O0 ['path'])or os .path .islink (O0OOOO0O0O000O0O0 ['path']):continue
if get_path :
if O0OOOO0O0O000O0O0 ['path']==get_path :
OOO00OO0OOO0O0OO0 =psutil .disk_usage (O0OOOO0O0O000O0O0 ['path'])
O0OOOO0O0O000O0O0 ['used']=OOO00OO0OOO0O0OO0 .used
O0OOOO0O0O000O0O0 ['free']=OOO00OO0OOO0O0OO0 .free
return O0OOOO0O0O000O0O0
else :
continue
OOO00OO0OOO0O0OO0 =psutil .disk_usage (O0OOOO0O0O000O0O0 ['path'])
O0OOOO0O0O000O0O0 ['used']=OOO00OO0OOO0O0OO0 .used
O0OOOO0O0O000O0O0 ['free']=OOO00OO0OOO0O0OO0 .free
OO00OOO0O00OOOO00 .append (O0OOOO0O0O000O0O0 )
if get_path :
return {'size':0 ,'used':0 ,'free':0 }
if len (OO00OOO0O00OOOO00 )!=len (O00OO00OO000O0OO0 ):
public .writeFile (OOOO000OO000O000O .__O0O000000OO000000 ,json .dumps (OO00OOO0O00OOOO00 ))
return O00OO00OO000O0OO0
def get_quota_mysql_list (OO000O0O00OOOOO0O ,args =None ,get_name =None ):
""
if not os .path .exists (OO000O0O00OOOOO0O .__O00OOOO00OO0OO0OO ):
public .writeFile (OO000O0O00OOOOO0O .__O00OOOO00OO0OO0OO ,'[]')
OO00OO0000O0O0OOO =json .loads (public .readFile (OO000O0O00OOOOO0O .__O00OOOO00OO0OO0OO ))
O00O00OOO0OOO00OO =[]
OOOO000000OO0O0O0 =public .M ('databases')
for OOO0OO0O000O0O00O in OO00OO0000O0O0OOO :
if get_name :
if OOO0OO0O000O0O00O ['db_name']==get_name :
OOO0OO0O000O0O00O ['used']=OOO0OO0O000O0O00O ['used']=int (public .get_database_size_by_name (OOO0OO0O000O0O00O ['db_name']))
_O0OO00O000O0OOO00 =OOO0OO0O000O0O00O ['size']*1024 *1024
if (OOO0OO0O000O0O00O ['used']>_O0OO00O000O0OOO00 and OOO0OO0O000O0O00O ['insert_accept'])or (OOO0OO0O000O0O00O ['used']<_O0OO00O000O0OOO00 and not OOO0OO0O000O0O00O ['insert_accept']):
OO000O0O00OOOOO0O .mysql_quota_check ()
return OOO0OO0O000O0O00O
else :
if OOOO000000OO0O0O0 .where ('name=?',OOO0OO0O000O0O00O ['db_name']).count ():
if args :OOO0OO0O000O0O00O ['used']=int (public .get_database_size_by_name (OOO0OO0O000O0O00O ['db_name']))
O00O00OOO0OOO00OO .append (OOO0OO0O000O0O00O )
OOOO000000OO0O0O0 .close ()
if get_name :
return {'size':0 ,'used':0 }
if len (O00O00OOO0OOO00OO )!=len (OO00OO0000O0O0OOO ):
public .writeFile (OO000O0O00OOOOO0O .__O00OOOO00OO0OO0OO ,json .dumps (O00O00OOO0OOO00OO ))
return O00O00OOO0OOO00OO
def __OOO000O00000O0OO0 (OOOOOOOO0OOO000OO ,OOO0000OOO00O000O ,OO0OOO0000000OOO0 ,O0OOO0OO00O00O0OO ,OOOO00000OOOO0OO0 ):
""
O0OO0O00O000O00O0 =OOO0000OOO00O000O .execute ("REVOKE ALL PRIVILEGES ON `{}`.* FROM '{}'@'{}';".format (O0OOO0OO00O00O0OO ,OO0OOO0000000OOO0 ,OOOO00000OOOO0OO0 ))
if O0OO0O00O000O00O0 :raise public .PanelError ('Failed to remove insert permission for database user:{}'.format (O0OO0O00O000O00O0 ))
O0OO0O00O000O00O0 =OOO0000OOO00O000O .execute ("GRANT SELECT, DELETE, CREATE, DROP, REFERENCES, INDEX, CREATE TEMPORARY TABLES, LOCK TABLES, CREATE VIEW, EVENT, TRIGGER, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EXECUTE ON `{}`.* TO '{}'@'{}';".format (O0OOO0OO00O00O0OO ,OO0OOO0000000OOO0 ,OOOO00000OOOO0OO0 ))
if O0OO0O00O000O00O0 :raise public .PanelError ('Failed to remove insert permission for database user:{}'.format (O0OO0O00O000O00O0 ))
OOO0000OOO00O000O .execute ("FLUSH PRIVILEGES;")
return True
def __O000O000O0OOOOOOO (OO00OOO00OO0OOO00 ,O000OOOO0OO0O00OO ,O0OOO0OOO0OO00O00 ,O00OOO0OO0OO0OOOO ,OOOOOOOO0OO00O000 ):
""
OOO0O000OOOOO0O00 =O000OOOO0OO0O00OO .execute ("REVOKE ALL PRIVILEGES ON `{}`.* FROM '{}'@'{}';".format (O00OOO0OO0OO0OOOO ,O0OOO0OOO0OO00O00 ,OOOOOOOO0OO00O000 ))
if OOO0O000OOOOO0O00 :raise public .PanelError ('Failed to restore insert privileges for database user:{}'.format (OOO0O000OOOOO0O00 ))
OOO0O000OOOOO0O00 =O000OOOO0OO0O00OO .execute ("GRANT ALL PRIVILEGES ON `{}`.* TO '{}'@'{}';".format (O00OOO0OO0OO0OOOO ,O0OOO0OOO0OO00O00 ,OOOOOOOO0OO00O000 ))
if OOO0O000OOOOO0O00 :raise public .PanelError ('Failed to restore insert privileges for database user:{}'.format (OOO0O000OOOOO0O00 ))
O000OOOO0OO0O00OO .execute ("FLUSH PRIVILEGES;")
return True
def mysql_quota_service (O00000OO00O0O0000 ):
""
while 1 :
time .sleep (600 )
O00000OO00O0O0000 .mysql_quota_check ()
def __O0OO00O00O0OOO0OO (O0OO0O0000OOO0O0O ,OO0O0OOOOO0O00O0O ):
try :
if type (OO0O0OOOOO0O00O0O )!=list and type (OO0O0OOOOO0O00O0O )!=str :OO0O0OOOOO0O00O0O =list (OO0O0OOOOO0O00O0O )
return OO0O0OOOOO0O00O0O
except :return []
def mysql_quota_check (OO0O0OOO00O0OO00O ):
""
if not OO0O0OOO00O0OO00O .__OO000OOO0OO0O00OO ():return public .returnMsg (False ,OO0O0OOO00O0OO00O .__O0O00000000OOO0O0 )
O00000OOO00OO000O =OO0O0OOO00O0OO00O .get_quota_mysql_list ()
for OO0O0O0O0OO00OOO0 in O00000OOO00OO000O :
try :
if OO0O0O0O0OO00OOO0 ['size']<1 :
if not OO0O0O0O0OO00OOO0 ['insert_accept']:
OO0O0OOO00O0OO00O .__O000O000O0OOOOOOO (O0OOOO000OOO0O0OO ,O0000O00OO0O00O0O ,OO0O0O0O0OO00OOO0 ['db_name'],O000O00O0000OOO0O [0 ])
OO0O0O0O0OO00OOO0 ['insert_accept']=True
public .WriteLog ('Quota','Database [{}] quota has been closed, restore insert privileges'.format (OO0O0O0O0OO00OOO0 ['db_name']))
continue
O000O000O00000O0O =public .get_database_size_by_name (OO0O0O0O0OO00OOO0 ['db_name'])/1024 /1024
O0000O00OO0O00O0O =public .M ('databases').where ('name=?',(OO0O0O0O0OO00OOO0 ['db_name'],)).getField ('username')
O0OOOO000OOO0O0OO =public .get_mysql_obj (OO0O0O0O0OO00OOO0 ['db_name'])
O0O0OOO0O0O00OOOO =OO0O0OOO00O0OO00O .__O0OO00O00O0OOO0OO (O0OOOO000OOO0O0OO .query ("select Host from mysql.user where User='"+O0000O00OO0O00O0O +"'"))
if O000O000O00000O0O <OO0O0O0O0OO00OOO0 ['size']:
if not OO0O0O0O0OO00OOO0 ['insert_accept']:
for O000O00O0000OOO0O in O0O0OOO0O0O00OOOO :
OO0O0OOO00O0OO00O .__O000O000O0OOOOOOO (O0OOOO000OOO0O0OO ,O0000O00OO0O00O0O ,OO0O0O0O0OO00OOO0 ['db_name'],O000O00O0000OOO0O [0 ])
OO0O0O0O0OO00OOO0 ['insert_accept']=True
public .WriteLog ('Quota','The database [{}] is below the quota [{}MB], restore the insert permission'.format (OO0O0O0O0OO00OOO0 ['db_name'],OO0O0O0O0OO00OOO0 ['size']))
if hasattr (O0OOOO000OOO0O0OO ,'close'):O0OOOO000OOO0O0OO .close ()
continue
if OO0O0O0O0OO00OOO0 ['insert_accept']:
for O000O00O0000OOO0O in O0O0OOO0O0O00OOOO :
OO0O0OOO00O0OO00O .__OOO000O00000O0OO0 (O0OOOO000OOO0O0OO ,O0000O00OO0O00O0O ,OO0O0O0O0OO00OOO0 ['db_name'],O000O00O0000OOO0O [0 ])
OO0O0O0O0OO00OOO0 ['insert_accept']=False
public .WriteLog ('Quota','Database [{}] removed insert permission due to exceeding quota [{}MB]'.format (OO0O0O0O0OO00OOO0 ['db_name'],OO0O0O0O0OO00OOO0 ['size']))
if hasattr (O0OOOO000OOO0O0OO ,'close'):O0OOOO000OOO0O0OO .close ()
except :
public .print_log (public .get_error_info ())
public .writeFile (OO0O0OOO00O0OO00O .__O00OOOO00OO0OO0OO ,json .dumps (O00000OOO00OO000O ))
def __O0000OO00OO00O0O0 (OO0000O0OO00O0OOO ,O0O0O00OO0OOOOOOO ):
""
if not OO0000O0OO00O0OOO .__OO000OOO0OO0O00OO ():return public .returnMsg (False ,OO0000O0OO00O0OOO .__O0O00000000OOO0O0 )
if not os .path .exists (OO0000O0OO00O0OOO .__O00OOOO00OO0OO0OO ):
public .writeFile (OO0000O0OO00O0OOO .__O00OOOO00OO0OO0OO ,'[]')
OOOO0000OOOO0OOOO =int (O0O0O00OO0OOOOOOO ['size'])
OOO000O0OO00O00OO =O0O0O00OO0OOOOOOO .db_name .strip ()
O0OO0OOOOO00O00OO =json .loads (public .readFile (OO0000O0OO00O0OOO .__O00OOOO00OO0OO0OO ))
for OO000O0O0O0O000OO in O0OO0OOOOO00O00OO :
if OO000O0O0O0O000OO ['db_name']==OOO000O0OO00O00OO :
return public .returnMsg (False ,'Database quota already exists')
O0OO0OOOOO00O00OO .append ({'db_name':OOO000O0OO00O00OO ,'size':OOOO0000OOOO0OOOO ,'insert_accept':True })
public .writeFile (OO0000O0OO00O0OOO .__O00OOOO00OO0OO0OO ,json .dumps (O0OO0OOOOO00O00OO ))
public .WriteLog ('Quota','The quota limit for creating database [{db_name}] is: {size}MB'.format (db_name =OOO000O0OO00O00OO ,size =OOOO0000OOOO0OOOO ))
OO0000O0OO00O0OOO .mysql_quota_check ()
return public .returnMsg (True ,'Added successfully')
def __OO000OOO0OO0O00OO (OOOO00OOOO00O0O00 ):
import panelPlugin
O0OOOOOO0O0000O0O =public .to_dict_obj ({})
O0OOOOOO0O0000O0O .focre =1
O0O0O00O0OO00O000 =panelPlugin .panelPlugin ().get_soft_list (O0OOOOOO0O0000O0O )
return int (O0O0O00O0OO00O000 ['pro'])>time .time ()
def modify_mysql_quota (OO00OO0OOOO00O000 ,OOOO00O0OO000OOOO ):
""
if not OO00OO0OOOO00O000 .__OO000OOO0OO0O00OO ():return public .returnMsg (False ,OO00OO0OOOO00O000 .__O0O00000000OOO0O0 )
if not os .path .exists (OO00OO0OOOO00O000 .__O00OOOO00OO0OO0OO ):
public .writeFile (OO00OO0OOOO00O000 .__O00OOOO00OO0OO0OO ,'[]')
if not re .match (r"^\d+$",OOOO00O0OO000OOOO .size ):return public .returnMsg (False ,'Quota size must be an integer!')
OO0O0OOOO00000OOO =int (OOOO00O0OO000OOOO ['size'])
OO0OO0OO000O0O00O =OOOO00O0OO000OOOO .db_name .strip ()
O0OOOO0OOOO0O0000 =json .loads (public .readFile (OO00OO0OOOO00O000 .__O00OOOO00OO0OO0OO ))
O0O00O0O000OOO0O0 =False
for OO00O0000O0OOOOO0 in O0OOOO0OOOO0O0000 :
if OO00O0000O0OOOOO0 ['db_name']==OO0OO0OO000O0O00O :
OO00O0000O0OOOOO0 ['size']=OO0O0OOOO00000OOO
O0O00O0O000OOO0O0 =True
break
if O0O00O0O000OOO0O0 :
public .writeFile (OO00OO0OOOO00O000 .__O00OOOO00OO0OO0OO ,json .dumps (O0OOOO0OOOO0O0000 ))
public .WriteLog ('Quota','Modify the quota limit of database [{db_name}] to: {size}MB'.format (db_name =OO0OO0OO000O0O00O ,size =OO0O0OOOO00000OOO ))
OO00OO0OOOO00O000 .mysql_quota_check ()
return public .returnMsg (True ,'Successfully modified')
return OO00OO0OOOO00O000 .__O0000OO00OO00O0O0 (OOOO00O0OO000OOOO )
def __O0OOOO00O00000OOO (O0OO0O0O00O0OO00O ,O0O0O0O0O000O0OOO ):
""
O0OOO0OO0O0000O00 =[]
OO0000OO0OO00O0O0 =public .ExecShell ("{xfs_quota} -x -c report {mountpoint}|awk '{{print $1}}'|grep '#'".format (xfs_quota =O0OO0O0O00O0OO00O .xfs_quota ,mountpoint =O0O0O0O0O000O0OOO ))[0 ]
if not OO0000OO0OO00O0O0 :return O0OOO0OO0O0000O00
for O0OO0O00OO0O0OO0O in OO0000OO0OO00O0O0 .split ('\n'):
if O0OO0O00OO0O0OO0O :O0OOO0OO0O0000O00 .append (int (O0OO0O00OO0O0OO0O .split ('#')[-1 ]))
return O0OOO0OO0O0000O00
def __OO00O000OOOOOOO00 (O0OOO0O00OOOO0OOO ,OO0000O0OOOOOOO0O ,OOO0000OO0O0000OO ):
""
O00O00OO0O000O000 =1001
if not OO0000O0OOOOOOO0O :return O00O00OO0O000O000
O00O00OO0O000O000 =OO0000O0OOOOOOO0O [-1 ]['id']+1
O0OO00OO00O00O000 =sorted (O0OOO0O00OOOO0OOO .__O0OOOO00O00000OOO (OOO0000OO0O0000OO ))
if O0OO00OO00O00O000 :
if O0OO00OO00O00O000 [-1 ]>O00O00OO0O000O000 :
O00O00OO0O000O000 =O0OO00OO00O00O000 [-1 ]+1
return O00O00OO0O000O000
def __OOOO0O000OOOO00O0 (OO0OO00O0O0000O0O ,O000O0OOOO0OOO00O ):
""
if not OO0OO00O0O0000O0O .__OO000OOO0OO0O00OO ():return public .returnMsg (False ,OO0OO00O0O0000O0O .__O0O00000000OOO0O0 )
OOOO000000O00OO00 =O000O0OOOO0OOO00O .path .strip ()
OO000OOO0000OO00O =int (O000O0OOOO0OOO00O .size )
if not os .path .exists (OOOO000000O00OO00 ):return public .returnMsg (False ,'The specified directory does not exist')
if os .path .isfile (OOOO000000O00OO00 ):return public .returnMsg (False ,'this is not a valid directory!')
if os .path .islink (OOOO000000O00OO00 ):return public .returnMsg (False ,'The specified directory is a soft link!')
OOOOO000OO0000OOO =OO0OO00O0O0000O0O .get_quota_path_list ()
for O00O0OOOO0O00O000 in OOOOO000OO0000OOO :
if O00O0OOOO0O00O000 ['path']==OOOO000000O00OO00 :return public .returnMsg (False ,'The specified directory has already set a quota!')
OO000O0OO0000OO00 =OO0OO00O0O0000O0O .__O000O0O0000OOOOOO (OOOO000000O00OO00 )
if OO000O0OO0000OO00 ==-3 :return public .returnMsg (False ,'The partition where the specified directory is located is not an XFS partition and does not support directory quotas!')
if OO000O0OO0000OO00 ==-2 :return public .returnMsg (False ,'this is not a valid directory!')
if OO000O0OO0000OO00 ==-1 :return public .returnMsg (False ,'The specified directory does not exist!')
if OO000OOO0000OO00O >OO000O0OO0000OO00 :return public .returnMsg (False ,'Insufficient quota capacity available for the specified disk!')
OOO0O0O0O0O000O0O =OO0OO00O0O0000O0O .__O000000O0O0000OOO (OOOO000000O00OO00 )
if not OOO0O0O0O0O000O0O :return public .returnMsg (False ,'The specified directory is not in the xfs disk partition!')
if isinstance (OOO0O0O0O0O000O0O ,tuple ):return public .returnMsg (False ,'The directory quota function is not enabled for this xfs partition, please increase the [prjquota] parameter when mounting the partition<p>/etc/fstab File configuration example<pre>{mountpoint} {path} xfs defaults,prjquota 0 0</pre></p><p>Note: You need to remount the partition or reboot the server to take effect</p><br>The setup is completed and the error still occurs, please refer to<br><a class="btlink" target ="_blank" href="https://forum.aapanel.com/d/12700-how-to-enable-disk-quota-for-root-directory">How to enable disk quota for root directory</a>'.format (mountpoint =OOO0O0O0O0O000O0O [1 ],path =OOO0O0O0O0O000O0O [0 ]))
O0000OO000OO00O0O =OO0OO00O0O0000O0O .__OO00O000OOOOOOO00 (OOOOO000OO0000OOO ,OOO0O0O0O0O000O0O )
OO0O0O0O0OOOOO00O =public .ExecShell ("{xfs_quota} -x -c 'project -s -p {path} {quota_id}'".format (path =OOOO000000O00OO00 ,quota_id =O0000OO000OO00O0O ,xfs_quota =OO0OO00O0O0000O0O .xfs_quota ))
if OO0O0O0O0OOOOO00O [1 ]:return public .returnMsg (False ,OO0O0O0O0OOOOO00O [1 ])
OO0O0O0O0OOOOO00O =public .ExecShell ("{xfs_quota} -x -c 'limit -p bhard={size}m {quota_id}' {mountpoint}".format (quota_id =O0000OO000OO00O0O ,size =OO000OOO0000OO00O ,mountpoint =OOO0O0O0O0O000O0O ,xfs_quota =OO0OO00O0O0000O0O .xfs_quota ))
if OO0O0O0O0OOOOO00O [1 ]:return public .returnMsg (False ,OO0O0O0O0OOOOO00O [1 ])
OOOOO000OO0000OOO .append ({'path':O000O0OOOO0OOO00O .path ,'size':OO000OOO0000OO00O ,'id':O0000OO000OO00O0O })
public .writeFile (OO0OO00O0O0000O0O .__O0O000000OO000000 ,json .dumps (OOOOO000OO0000OOO ))
public .WriteLog ('Quota','The quota limit for creating directory [{path}] is: {size}MB'.format (path =OOOO000000O00OO00 ,size =OO000OOO0000OO00O ))
return public .returnMsg (True ,'Added successfully')
def modify_path_quota (O0O0OOOOO0OOO0OOO ,OO0O0000000OO0OO0 ):
""
if not O0O0OOOOO0OOO0OOO .__OO000OOO0OO0O00OO ():return public .returnMsg (False ,O0O0OOOOO0OOO0OOO .__O0O00000000OOO0O0 )
O00O0O00OOO0O0O0O =OO0O0000000OO0OO0 .path .strip ()
if not re .match (r"^\d+$",OO0O0000000OO0OO0 .size ):return public .returnMsg (False ,'Quota size must be an integer!')
O0O00O0OOO0O0O0OO =int (OO0O0000000OO0OO0 .size )
if not os .path .exists (O00O0O00OOO0O0O0O ):return public .returnMsg (False ,'The specified directory does not exist')
if os .path .isfile (O00O0O00OOO0O0O0O ):return public .returnMsg (False ,'This is not a valid directory!')
if os .path .islink (O00O0O00OOO0O0O0O ):return public .returnMsg (False ,'The specified directory is a soft link!')
OO0O00O00OO0000OO =O0O0OOOOO0OOO0OOO .get_quota_path_list ()
OOOO0OO0OOOOO0OOO =0
for OOO00000OOOOO0OOO in OO0O00O00OO0000OO :
if OOO00000OOOOO0OOO ['path']==O00O0O00OOO0O0O0O :
OOOO0OO0OOOOO0OOO =OOO00000OOOOO0OOO ['id']
break
if not OOOO0OO0OOOOO0OOO :return O0O0OOOOO0OOO0OOO .__OOOO0O000OOOO00O0 (OO0O0000000OO0OO0 )
O0O0O00OOOOOO00O0 =O0O0OOOOO0OOO0OOO .__O000O0O0000OOOOOO (O00O0O00OOO0O0O0O )
if O0O0O00OOOOOO00O0 ==-3 :return public .returnMsg (False ,'The partition where the specified directory is located is not an XFS partition, and directory quotas are not supported!')
if O0O0O00OOOOOO00O0 ==-2 :return public .returnMsg (False ,'This is not a valid directory!')
if O0O0O00OOOOOO00O0 ==-1 :return public .returnMsg (False ,'The specified directory does not exist!')
if O0O00O0OOO0O0O0OO >O0O0O00OOOOOO00O0 :return public .returnMsg (False ,'Insufficient quota capacity available for the specified disk!')
OOO0OO0O0000O0OO0 =O0O0OOOOO0OOO0OOO .__O000000O0O0000OOO (O00O0O00OOO0O0O0O )
if not OOO0OO0O0000O0OO0 :return public .returnMsg (False ,'The specified directory is not in the xfs disk partition!')
if isinstance (OOO0OO0O0000O0OO0 ,tuple ):return public .returnMsg (False ,'The directory quota function is not enabled for this xfs partition, please increase the [prjquota] parameter when mounting the partition<p>/etc/fstab File configuration example<pre>{mountpoint} {path} xfs defaults,prjquota 0 0</pre></p><p>Note: After the configuration is complete, you need to remount the partition or restart the server to take effect</p>'.format (mountpoint =OOO0OO0O0000O0OO0 [1 ],path =OOO0OO0O0000O0OO0 [0 ]))
OO00O0OOO00OOOO0O =public .ExecShell ("{xfs_quota} -x -c 'project -s -p {path} {quota_id}'".format (path =O00O0O00OOO0O0O0O ,quota_id =OOOO0OO0OOOOO0OOO ,xfs_quota =O0O0OOOOO0OOO0OOO .xfs_quota ))
if OO00O0OOO00OOOO0O [1 ]:return public .returnMsg (False ,OO00O0OOO00OOOO0O [1 ])
OO00O0OOO00OOOO0O =public .ExecShell ("{xfs_quota} -x -c 'limit -p bhard={size}m {quota_id}' {mountpoint}".format (quota_id =OOOO0OO0OOOOO0OOO ,size =O0O00O0OOO0O0O0OO ,mountpoint =OOO0OO0O0000O0OO0 ,xfs_quota =O0O0OOOOO0OOO0OOO .xfs_quota ))
if OO00O0OOO00OOOO0O [1 ]:return public .returnMsg (False ,OO00O0OOO00OOOO0O [1 ])
for OOO00000OOOOO0OOO in OO0O00O00OO0000OO :
if OOO00000OOOOO0OOO ['path']==O00O0O00OOO0O0O0O :
OOO00000OOOOO0OOO ['size']=O0O00O0OOO0O0O0OO
break
public .writeFile (O0O0OOOOO0OOO0OOO .__O0O000000OO000000 ,json .dumps (OO0O00O00OO0000OO ))
public .WriteLog ('Quota','Modify the quota limit of directory [{path}] to:{size}MB'.format (path =O00O0O00OOO0O0O0O ,size =O0O00O0OOO0O0O0OO ))
return public .returnMsg (True ,'Successfully modified')