docker_remote_service.py 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. # app/services/docker_remote_service.py
  2. import json
  3. from typing import Optional, Dict, Any, List
  4. from app.services.docker_remote_control import DockerRemoteController
  5. from app.schemas.docker_remote import (
  6. RemoteServerConfig,
  7. DockerContainerStatus,
  8. DockerLogsRequest,
  9. ConfigUpdateRequest,
  10. LogReadRequest,
  11. )
  12. from app.core.logger import logger
  13. class DockerRemoteService:
  14. """Docker远程控制服务"""
  15. @staticmethod
  16. async def get_container_status(config: RemoteServerConfig) -> Dict[str, DockerContainerStatus]:
  17. """获取容器状态"""
  18. controller = DockerRemoteController(
  19. host=config.host,
  20. port=config.port,
  21. username=config.username,
  22. password=config.password,
  23. key_file=config.key_file,
  24. project_path=config.project_path
  25. )
  26. try:
  27. if not controller.connect():
  28. raise Exception("连接失败")
  29. containers = controller.docker_status()
  30. result = {}
  31. for name, info in containers.items():
  32. result[name] = DockerContainerStatus(
  33. name=name,
  34. status=info['status'],
  35. image=info['image']
  36. )
  37. return result
  38. except Exception as e:
  39. logger.error(f"获取容器状态失败: {e}")
  40. raise
  41. finally:
  42. controller.disconnect()
  43. @staticmethod
  44. async def docker_compose_up(config: RemoteServerConfig, services: Optional[List[str]] = None) -> bool:
  45. """启动Docker Compose服务"""
  46. controller = DockerRemoteController(
  47. host=config.host,
  48. port=config.port,
  49. username=config.username,
  50. password=config.password,
  51. key_file=config.key_file,
  52. project_path=config.project_path
  53. )
  54. try:
  55. if not controller.connect():
  56. raise Exception("连接失败")
  57. return controller.docker_compose_up(services)
  58. except Exception as e:
  59. logger.error(f"启动Docker服务失败: {e}")
  60. raise
  61. finally:
  62. controller.disconnect()
  63. @staticmethod
  64. async def docker_compose_down(config: RemoteServerConfig, services: Optional[List[str]] = None) -> bool:
  65. """停止Docker Compose服务"""
  66. controller = DockerRemoteController(
  67. host=config.host,
  68. port=config.port,
  69. username=config.username,
  70. password=config.password,
  71. key_file=config.key_file,
  72. project_path=config.project_path
  73. )
  74. try:
  75. if not controller.connect():
  76. raise Exception("连接失败")
  77. return controller.docker_compose_down(services)
  78. except Exception as e:
  79. logger.error(f"停止Docker服务失败: {e}")
  80. raise
  81. finally:
  82. controller.disconnect()
  83. @staticmethod
  84. async def docker_restart(config: RemoteServerConfig, container_name: str) -> bool:
  85. """重启容器"""
  86. controller = DockerRemoteController(
  87. host=config.host,
  88. port=config.port,
  89. username=config.username,
  90. password=config.password,
  91. key_file=config.key_file,
  92. project_path=config.project_path
  93. )
  94. try:
  95. if not controller.connect():
  96. raise Exception("连接失败")
  97. return controller.docker_restart(container_name)
  98. except Exception as e:
  99. logger.error(f"重启容器失败: {e}")
  100. raise
  101. finally:
  102. controller.disconnect()
  103. @staticmethod
  104. async def docker_start(config: RemoteServerConfig, container_name: str) -> bool:
  105. """启动容器"""
  106. controller = DockerRemoteController(
  107. host=config.host,
  108. port=config.port,
  109. username=config.username,
  110. password=config.password,
  111. key_file=config.key_file,
  112. project_path=config.project_path
  113. )
  114. try:
  115. if not controller.connect():
  116. raise Exception("连接失败")
  117. return controller.docker_start(container_name)
  118. except Exception as e:
  119. logger.error(f"启动容器失败: {e}")
  120. raise
  121. finally:
  122. controller.disconnect()
  123. @staticmethod
  124. async def docker_stop(config: RemoteServerConfig, container_name: str) -> bool:
  125. """停止容器"""
  126. controller = DockerRemoteController(
  127. host=config.host,
  128. port=config.port,
  129. username=config.username,
  130. password=config.password,
  131. key_file=config.key_file,
  132. project_path=config.project_path
  133. )
  134. try:
  135. if not controller.connect():
  136. raise Exception("连接失败")
  137. return controller.docker_stop(container_name)
  138. except Exception as e:
  139. logger.error(f"停止容器失败: {e}")
  140. raise
  141. finally:
  142. controller.disconnect()
  143. @staticmethod
  144. async def docker_logs(config: RemoteServerConfig, request: DockerLogsRequest) -> str:
  145. """查看容器日志"""
  146. controller = DockerRemoteController(
  147. host=config.host,
  148. port=config.port,
  149. username=config.username,
  150. password=config.password,
  151. key_file=config.key_file,
  152. project_path=config.project_path
  153. )
  154. try:
  155. if not controller.connect():
  156. raise Exception("连接失败")
  157. return controller.docker_logs(request.container_name, request.lines, request.follow)
  158. except Exception as e:
  159. logger.error(f"查看容器日志失败: {e}")
  160. raise
  161. finally:
  162. controller.disconnect()
  163. @staticmethod
  164. async def read_config(config: RemoteServerConfig, config_file: str) -> Dict[str, Any]:
  165. """读取配置文件"""
  166. controller = DockerRemoteController(
  167. host=config.host,
  168. port=config.port,
  169. username=config.username,
  170. password=config.password,
  171. key_file=config.key_file,
  172. project_path=config.project_path
  173. )
  174. try:
  175. if not controller.connect():
  176. raise Exception("连接失败")
  177. result = controller.read_config(config_file)
  178. if result is None:
  179. raise Exception("配置文件不存在或读取失败")
  180. return result
  181. except Exception as e:
  182. logger.error(f"读取配置文件失败: {e}")
  183. raise
  184. finally:
  185. controller.disconnect()
  186. @staticmethod
  187. async def update_config(config: RemoteServerConfig, request: ConfigUpdateRequest) -> bool:
  188. """更新配置文件"""
  189. controller = DockerRemoteController(
  190. host=config.host,
  191. port=config.port,
  192. username=config.username,
  193. password=config.password,
  194. key_file=config.key_file,
  195. project_path=config.project_path
  196. )
  197. try:
  198. if not controller.connect():
  199. raise Exception("连接失败")
  200. return controller.update_config(request.config_file, request.key_path, request.value)
  201. except Exception as e:
  202. logger.error(f"更新配置文件失败: {e}")
  203. raise
  204. finally:
  205. controller.disconnect()
  206. @staticmethod
  207. async def read_log(config: RemoteServerConfig, request: LogReadRequest) -> str:
  208. """读取日志文件"""
  209. controller = DockerRemoteController(
  210. host=config.host,
  211. port=config.port,
  212. username=config.username,
  213. password=config.password,
  214. key_file=config.key_file,
  215. project_path=config.project_path
  216. )
  217. try:
  218. if not controller.connect():
  219. raise Exception("连接失败")
  220. return controller.read_log(
  221. request.log_file,
  222. lines=request.lines,
  223. from_head=request.from_head,
  224. full=request.full
  225. )
  226. except Exception as e:
  227. logger.error(f"读取日志文件失败: {e}")
  228. raise
  229. finally:
  230. controller.disconnect()
  231. @staticmethod
  232. async def list_logs(config: RemoteServerConfig) -> List[str]:
  233. """列出所有日志文件"""
  234. controller = DockerRemoteController(
  235. host=config.host,
  236. port=config.port,
  237. username=config.username,
  238. password=config.password,
  239. key_file=config.key_file,
  240. project_path=config.project_path
  241. )
  242. try:
  243. if not controller.connect():
  244. raise Exception("连接失败")
  245. return controller.list_logs()
  246. except Exception as e:
  247. logger.error(f"列出日志文件失败: {e}")
  248. raise
  249. finally:
  250. controller.disconnect()