manage.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. import os
  2. import io
  3. import sys
  4. import platform
  5. import shutil
  6. import time
  7. import subprocess
  8. import json
  9. import datetime
  10. import socket
  11. from threading import Thread
  12. from api.utils import shell_execute, network, docker, const
  13. from api.model.app import App
  14. from api.model.response import Response
  15. # 获取所有app的信息
  16. def get_my_app(app_name=None):
  17. ret = Response(code=const.RETURN_FAIL, message="app查询失败")
  18. # get all info
  19. cmd = "sudo docker compose ls -a"
  20. output = shell_execute.execute_command_output_all(cmd)
  21. if int(output["code"]) == 0:
  22. output_list = output["result"].split("\n")
  23. list = []
  24. output_list = output_list[1:-1]
  25. list = set_app_info(output_list)
  26. flag = 0
  27. if app_name != None:
  28. for app in list:
  29. if app["name"] == app_name:
  30. list.clear()
  31. list.append(app)
  32. flag = 1
  33. break
  34. if app_name == None or flag == 1:
  35. ret = Response(code=const.RETURN_SUCCESS,
  36. message="app查询成功", data=list)
  37. ret = ret.dict()
  38. return ret
  39. def set_app_info(output_list):
  40. ip_result = shell_execute.execute_command_output_all("curl ifconfig.me")
  41. ip = ip_result["result"]
  42. app_list = []
  43. for app_info in output_list:
  44. app_name = app_info.split()[0] # app_name
  45. real_name = docker.read_var(app_name, 'name')
  46. image_url = "https://libs.websoft9.com/Websoft9/logo/product/" + real_name + "-websoft9.png"
  47. # get trade_mark
  48. trade_mark = docker.read_var(app_name, 'trademark')
  49. id = app_name # id
  50. case = app_info.split()[1].split("(")[0] # case
  51. if case == "running":
  52. case_code = const.RETURN_RUNNING # case_code
  53. elif case == "exited":
  54. case = "stop"
  55. case_code = const.RETURN_STOP
  56. elif case == "installing":
  57. case_code = const.RETURN_READY
  58. else:
  59. case_code = const.RETURN_ERROR
  60. volume = app_info.split()[-1] # volume
  61. # get env info
  62. path = "/data/apps/" + app_name + "/.env"
  63. port = 0
  64. url = "-"
  65. admin_url = "-"
  66. # get port and url
  67. try:
  68. http_port = list(docker.read_env(
  69. path, "APP_HTTP_PORT").values())[0]
  70. port = int(http_port)
  71. easy_url = "http://" + ip + ":" + str(port)
  72. url = get_url(real_name, easy_url)
  73. admin_url = get_admin_url(real_name, url)
  74. except IndexError:
  75. try:
  76. db_port = list(docker.read_env(
  77. path, "APP_DB.*_PORT").values())[0]
  78. port = int(db_port)
  79. except IndexError:
  80. pass
  81. # get user_name
  82. user_name = "-"
  83. try:
  84. user_name = list(docker.read_env(path, "APP_USER").values())[0]
  85. except IndexError:
  86. pass
  87. # get password
  88. password = "-"
  89. try:
  90. password = list(docker.read_env(
  91. path, "POWER_PASSWORD").values())[0]
  92. except IndexError:
  93. pass
  94. real_name = docker.read_var(app_name, 'name')
  95. app = App(id=id, name=real_name, customer_name=app_name, status_code=case_code, status=case, port=port, volume=volume, url=url,
  96. image_url=image_url, admin_url=admin_url, trade_mark=trade_mark, user_name=user_name, password=password)
  97. app_list.append(app.dict())
  98. file_path = "/data/apps/running_apps.txt"
  99. if os.path.exists(file_path) and os.path.getsize(file_path):
  100. with open(file_path, "r", encoding="utf-8") as f:
  101. for running_app_name in f:
  102. image_url = "https://libs.websoft9.com/Websoft9/logo/product/" + \
  103. running_app_name + "-websoft9.png"
  104. trade_mark = docker.read_var(app_name, 'trademark')
  105. real_name = docker.read_var(app_name, 'name')
  106. app = App(id=running_app_name, name=real_name, customer_name=running_app_name, status_code=const.RETURN_READY, status="installing", port=0, volume="-",
  107. url="-", image_url=image_url, admin_url="-", trade_mark=trade_mark, user_name="-", password="-")
  108. app_list.append(app.dict())
  109. return app_list
  110. def get_url(app_name, easy_url):
  111. url = easy_url
  112. if app_name == "joomla":
  113. url = easy_url + "/administrator"
  114. elif app_name == "other":
  115. url = easy_url + "/administrator"
  116. else:
  117. url = easy_url
  118. return url
  119. def get_admin_url(app_name, url):
  120. admin_url = "-"
  121. if app_name == "wordpress":
  122. admin_url = url + "/wp-admin"
  123. elif app_name == "other":
  124. admin_url = url + "/admin"
  125. else:
  126. admin_url = "-"
  127. return admin_url
  128. def install_app_process(app_name):
  129. if docker.check_app_directory(app_name):
  130. percentage = docker.get_process_perc(app_name)
  131. ret = Response(code=const.RETURN_SUCCESS, message=percentage)
  132. ret = ret.dict()
  133. else:
  134. ret = Response(code=const.RETURN_FAIL, message="目前没有安装此App")
  135. ret = ret.dict()
  136. return ret
  137. def install_app(app_name, customer_app_name, app_version, app_force):
  138. # if app_force == False:
  139. # if docker.check_vm_resource(app_name) == False:
  140. # ret = Response(code=const.RETURN_FAIL , message="系统资源不足,继续安装可能导致应用无法运行或服务器异常!")
  141. # ret = ret.dict()
  142. # return ret
  143. app_file_path = '/data/apps/'+app_name
  144. running_file_path = "/data/apps/running_apps.txt"
  145. unique_app_path = "/data/apps/"+customer_app_name
  146. if os.path.exists(running_file_path) and os.path.getsize(running_file_path):
  147. ret = Response(code=const.RETURN_SUCCESS, message="已有应用正在启动,请稍后再试")
  148. ret = ret.dict()
  149. # 防止app名重复
  150. if if_app_exits(customer_app_name):
  151. ret = Response(code=const.RETURN_FAIL,
  152. message="APP名称已经使用,请指定其他名称重新安装。")
  153. ret = ret.dict()
  154. return ret
  155. elif docker.check_app_directory(app_name):
  156. if app_name != customer_app_name:
  157. output = shell_execute.execute_command_output_all(
  158. "cp -r /data/apps/" + app_name + " /data/apps/" + customer_app_name)
  159. if int(output["code"]) != 0:
  160. ret.code = const.RETURN_FAIL
  161. ret.message = "创建" + customer_app_name + "目录失败."
  162. ret = ret.dict()
  163. return ret
  164. env_file = unique_app_path + '/.env'
  165. docker.modify_env(env_file, 'APP_NAME', customer_app_name)
  166. # check port
  167. docker.check_app_compose(customer_app_name)
  168. if app_version != None:
  169. path = "/data/apps/"+customer_app_name+"/.env"
  170. docker.modify_env(path, "APP_VERSION", app_version)
  171. t1 = Thread(target=record_and_install_app, args=(customer_app_name,))
  172. t1.start()
  173. ret = Response(code=const.RETURN_SUCCESS, message="应用正在启动中,请过几分钟再查询")
  174. ret = ret.dict()
  175. else:
  176. ret = Response(code=const.RETURN_FAIL, message="目前不支持安装此App")
  177. ret = ret.dict()
  178. return ret
  179. def record_and_install_app(app_name):
  180. # modify running_apps.txt
  181. file_path = "/data/apps/running_apps.txt"
  182. with open(file_path, "w", encoding="utf-8") as f:
  183. f.write(app_name)
  184. cmd = "cd /data/apps/" + app_name + " && sudo docker compose up -d"
  185. shell_execute.execute_command_output_all(cmd)
  186. with open(file_path, "a+", encoding="utf-8") as f:
  187. f.truncate(0)
  188. def if_app_exits(app_name):
  189. cmd = "docker compose ls -a | grep \'"+app_name+"\\b\'"
  190. output = shell_execute.execute_command_output_all(cmd)
  191. if int(output["code"]) == -1:
  192. return False
  193. else:
  194. return True
  195. def start_app(app_name):
  196. ret = Response(code=const.RETURN_FAIL, message="")
  197. if if_app_exits(app_name):
  198. docker.check_app_compose(app_name)
  199. cmd = "docker compose -f /data/apps/"+app_name+"/docker-compose.yml start"
  200. output = shell_execute.execute_command_output_all(cmd)
  201. if int(output["code"]) == 0:
  202. ret.code = const.RETURN_SUCCESS
  203. ret.message = "应用启动成功"
  204. else:
  205. ret.message = "应用启动失败"
  206. else:
  207. ret.message = "应用不存在"
  208. ret = ret.dict()
  209. return ret
  210. def stop_app(app_name):
  211. ret = Response(code=const.RETURN_FAIL, message="")
  212. if if_app_exits(app_name):
  213. cmd = "docker compose -f /data/apps/"+app_name+"/docker-compose.yml stop"
  214. output = shell_execute.execute_command_output_all(cmd)
  215. if int(output["code"]) == 0:
  216. ret.code = const.RETURN_SUCCESS
  217. ret.message = "应用停止成功"
  218. else:
  219. ret.message = "应用停止失败"
  220. else:
  221. ret.message = "应用不存在"
  222. ret = ret.dict()
  223. return ret
  224. def restart_app(app_name):
  225. ret = Response(code=const.RETURN_FAIL, message="")
  226. if if_app_exits(app_name):
  227. cmd = "docker compose -f /data/apps/"+app_name+"/docker-compose.yml restart"
  228. output = shell_execute.execute_command_output_all(cmd)
  229. if int(output["code"]) == 0:
  230. ret.code = const.RETURN_SUCCESS
  231. ret.message = "应用重启成功"
  232. else:
  233. ret.message = "应用重启失败"
  234. else:
  235. ret.message = "应用不存在"
  236. ret = ret.dict()
  237. return ret
  238. def uninstall_app(app_name, delete_flag):
  239. ret = Response(code=const.RETURN_FAIL, message="")
  240. if_stopped = stop_app(app_name)
  241. if if_stopped["code"] == 0:
  242. if delete_flag == 0:
  243. cmd = "docker compose -f /data/apps/"+app_name+"/docker-compose.yml down"
  244. elif delete_flag == 1:
  245. cmd = "docker compose -f /data/apps/"+app_name+"/docker-compose.yml down -v"
  246. else:
  247. cmd = "docker compose -f /data/apps/"+app_name+"/docker-compose.yml down"
  248. output = shell_execute.execute_command_output_all(cmd)
  249. if int(output["code"]) == 0:
  250. ret.code = 0
  251. ret.message = "应用删除成功"
  252. else:
  253. ret.message = "应用删除失败"
  254. else:
  255. ret.message = if_stopped["message"]
  256. ret = ret.dict()
  257. return ret