mcsmapi 0.1.1__py3-none-any.whl → 0.1.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,300 @@
1
+ from typing import Any
2
+ from ..pool import ApiPool
3
+ from ..request import send
4
+ from ..models.instance import (
5
+ InstanceSearchList,
6
+ InstanceDetail,
7
+ InstanceCreateResult,
8
+ InstanceConfig,
9
+ )
10
+
11
+
12
+ class Instance:
13
+ def search(
14
+ self,
15
+ daemonId: str,
16
+ page: int = 1,
17
+ page_size: int = 20,
18
+ instance_name: str = "",
19
+ status: str = "",
20
+ tag: list[str] | None = None,
21
+ ) -> InstanceSearchList:
22
+ """
23
+ 根据指定的参数搜索实例信息
24
+
25
+ **参数:**
26
+ - daemonId (str): 守护进程的唯一标识符
27
+ - page (int): 页码,用于指示返回数据的页数。默认为1,表示返回第一页数据
28
+ - page_size (int): 每页大小,用于指定每页包含的数据条数。默认为20,表示每页包含20条数据
29
+ - instance_name (str): 实例的名称。默认为空字符串,表示不进行实例名称过滤
30
+ - status (str): 实例的状态。默认为空字符串,表示不进行状态过滤
31
+ - tag (list[str] | None): 实例的标签列表。默认为None,表示不进行标签过滤
32
+
33
+ **返回:**
34
+ - InstanceSearchList: 包含搜索结果的模型。该模型包含了符合搜索条件的实例信息列表,以及总数据条数、总页数等分页信息。
35
+ """
36
+ if tag is None:
37
+ tag = []
38
+ result = send(
39
+ "GET",
40
+ "api/service/remote_service_instances",
41
+ params={
42
+ "daemonId": daemonId,
43
+ "page": page,
44
+ "page_size": page_size,
45
+ "instance_name": instance_name,
46
+ "status": status,
47
+ "tag": tag,
48
+ },
49
+ )
50
+ return InstanceSearchList(**result, daemonId=daemonId)
51
+
52
+ def detail(self, daemonId: str, uuid: str) -> InstanceDetail:
53
+ """
54
+ 获取指定实例的详细信息
55
+
56
+ **参数:**
57
+ - daemonId (str): 守护进程的唯一标识符
58
+ - uuid (str): 实例的唯一标识符
59
+
60
+ **返回:**
61
+ - InstanceDetail: 包含实例详细信息的模型。
62
+ """
63
+ result = send(
64
+ "GET",
65
+ ApiPool.INSTANCE,
66
+ params={"uuid": uuid, "daemonId": daemonId},
67
+ )
68
+ return InstanceDetail(**result)
69
+
70
+ def create(self, daemonId: str, config: dict[str, Any]) -> InstanceCreateResult:
71
+ """
72
+ 创建一个实例。
73
+
74
+ **参数:**
75
+ - daemonId (str): 守护进程的唯一标识符,用于关联新创建的实例。
76
+ - config (dict[str, Any]): 实例的配置信息,以字典形式提供,缺失内容由InstanceConfig模型补全。
77
+
78
+ **返回:**
79
+ - InstanceCreateResult: 一个包含新创建实例信息的结果对象,内容由InstanceCreateResult模型定义。
80
+ """
81
+ result = send(
82
+ "POST",
83
+ ApiPool.INSTANCE,
84
+ params={"daemonId": daemonId},
85
+ data=InstanceConfig(**config).dict(),
86
+ )
87
+ return InstanceCreateResult(**result)
88
+
89
+ def updateConfig(self, daemonId: str, uuid: str, config: dict) -> str | bool:
90
+ """
91
+ 更新实例配置。
92
+
93
+ **不建议直接使用此函数,建议调用search后在data属性内使用updateConfig方法按需更新**
94
+
95
+ **参数:**
96
+ - daemonId (str): 守护进程的标识符。
97
+ - uuid (str): 实例的唯一标识符。
98
+ - config (dict): 新的实例配置,以字典形式提供,缺失内容由InstanceConfig模型补全。
99
+
100
+ **返回:**
101
+ - str|bool: 更新成功后返回更新的实例UUID,如果未找到该字段,则默认返回True。
102
+ """
103
+ result = send(
104
+ "PUT",
105
+ ApiPool.INSTANCE,
106
+ params={"uuid": uuid, "daemonId": daemonId},
107
+ data=InstanceConfig(**config).dict(),
108
+ )
109
+ return result.get("uuid", True)
110
+
111
+ def delete(
112
+ self, daemonId: str, uuids: list[str], deleteFile: bool = False
113
+ ) -> list[str]:
114
+ """
115
+ 删除实例。
116
+
117
+ **参数:**
118
+ - daemonId (str): 守护进程的标识符。
119
+ - uuids (list): 要删除的实例UUID列表。
120
+ - deleteFile (bool, optional): 是否删除关联的文件,默认为False。
121
+
122
+ **返回:**
123
+ - list[str]: 删除操作后返回的UUID列表。
124
+ """
125
+ return send(
126
+ "DELETE",
127
+ ApiPool.INSTANCE,
128
+ params={"daemonId": daemonId},
129
+ data={"uuids": uuids, "deleteFile": deleteFile},
130
+ )
131
+
132
+ def start(self, daemonId: str, uuid: str) -> str | bool:
133
+ """
134
+ 启动实例。
135
+
136
+ **参数:**
137
+ - daemonId (str): 守护进程的ID,用于标识特定的守护进程。
138
+ - uuid (str): 实例的唯一标识符,用于指定需要启动的实例。
139
+
140
+ **返回:**
141
+ - str|bool: 返回结果中的 "instanceUuid" 字段值,如果未找到该字段,则默认返回True。
142
+ """
143
+ result = send(
144
+ "GET",
145
+ f"{ApiPool.PROTECTED_INSTANCE}/open",
146
+ params={"daemonId": daemonId, "uuid": uuid},
147
+ )
148
+ return result.get("instanceUuid", True)
149
+
150
+ def stop(self, daemonId: str, uuid: str) -> str | bool:
151
+ """
152
+ 关闭实例。
153
+
154
+ **参数:**
155
+ - daemonId (str): 守护进程的ID,用于标识特定的守护进程。
156
+ - uuid (str): 实例的唯一标识符,用于指定需要关闭的实例。
157
+
158
+ **返回:**
159
+ - str|bool: 返回结果中的 "instanceUuid" 字段值,如果未找到该字段,则默认返回True。
160
+ """
161
+ result = send(
162
+ "GET",
163
+ f"{ApiPool.PROTECTED_INSTANCE}/stop",
164
+ params={"daemonId": daemonId, "uuid": uuid},
165
+ )
166
+ return result.get("instanceUuid", True)
167
+
168
+ def restart(self, daemonId: str, uuid: str) -> str | bool:
169
+ """
170
+ 重启实例。
171
+
172
+ **参数:**
173
+ - daemonId (str): 守护进程的ID,用于标识特定的守护进程。
174
+ - uuid (str): 实例的唯一标识符,用于指定需要重启的实例。
175
+
176
+ **返回:**
177
+ - str|bool: 返回结果中的 "instanceUuid" 字段值,如果未找到该字段,则默认返回True。
178
+ """
179
+ result = send(
180
+ "GET",
181
+ f"{ApiPool.PROTECTED_INSTANCE}/restart",
182
+ params={"daemonId": daemonId, "uuid": uuid},
183
+ )
184
+ return result.get("instanceUuid", True)
185
+
186
+ def kill(self, daemonId: str, uuid: str) -> str | bool:
187
+ """
188
+ 强制关闭实例。
189
+
190
+ **参数:**
191
+ - daemonId (str): 守护进程的ID,用于标识特定的守护进程。
192
+ - uuid (str): 实例的唯一标识符,用于指定需要强制关闭的实例。
193
+
194
+ **返回:**
195
+ - str|bool: 返回结果中的 "instanceUuid" 字段值,如果未找到该字段,则默认返回True。
196
+ """
197
+ result = send(
198
+ "GET",
199
+ f"{ApiPool.PROTECTED_INSTANCE}/kill",
200
+ params={"daemonId": daemonId, "uuid": uuid},
201
+ )
202
+ return result.get("instanceUuid", True)
203
+
204
+ def batchOperation(self, instances: list[dict[str, str]], operation: str) -> bool:
205
+ """
206
+ 对多个实例进行批量操作。
207
+
208
+ **参数:**
209
+ - instances (list[dict[str,str]]): 包含多个实例信息的列表,每个实例信息为一个字典,包含 "uuid" 和 "daemonId" 字段。
210
+ - operation (str): 要执行的操作,可以是 "start", "stop", "restart", 或 "kill"。
211
+
212
+ **返回:**
213
+ - list[dict[str,str]]:包含每个实例操作结果的列表,每个结果为一个字典,包含 "uuid" 和 "result" 字段。
214
+ """
215
+ if operation in {"start", "stop", "restart", "kill"}:
216
+ return send("POST", f"{ApiPool.INSTANCE}/multi_{operation}", data=instances)
217
+ else:
218
+ raise ValueError("operation must be one of start, stop, restart, kill")
219
+
220
+ def update(self, daemonId: str, uuid: str) -> bool:
221
+ """
222
+ 升级实例。
223
+
224
+ **参数:**
225
+ - daemonId (str): 守护进程的ID,用于标识特定的守护进程。
226
+ - uuid (str): 实例的唯一标识符,用于指定需要升级的实例。
227
+
228
+ **返回:**
229
+ - bool: 返回操作结果,成功时返回True。
230
+ """
231
+ return send(
232
+ "GET",
233
+ f"{ApiPool.PROTECTED_INSTANCE}/asynchronous",
234
+ params={"daemonId": daemonId, "uuid": uuid, "task_name": "update"},
235
+ )
236
+
237
+ def command(self, daemonId: str, uuid: str, command: str) -> str:
238
+ """
239
+ 向实例发送命令。
240
+
241
+ **参数:**
242
+ - daemonId (str): 守护进程的ID,用于标识特定的守护进程。
243
+ - uuid (str): 实例的唯一标识符,用于指定需要发送命令的实例。
244
+ - command (str): 要发送的命令。
245
+
246
+ **返回:**
247
+ - str|bool: 返回结果中的 "instanceUuid" 字段值,如果未找到该字段,则默认返回True。
248
+ """
249
+ result = send(
250
+ "GET",
251
+ f"{ApiPool.PROTECTED_INSTANCE}/command",
252
+ params={"daemonId": daemonId, "uuid": uuid, "command": command},
253
+ )
254
+ return result.get("instanceUuid", True)
255
+
256
+ def get_output(self, daemonId: str, uuid: str, size: int | str = "") -> str:
257
+ """
258
+ 获取实例输出。
259
+
260
+ **参数:**
261
+ - daemonId (str): 守护进程的ID,用于标识特定的守护进程。
262
+ - uuid (str): 实例的唯一标识符,用于指定需要获取输出的实例。
263
+ - size (int, optional): 获取的日志大小: 1KB ~ 2048KB,如果未设置,则返回所有日志
264
+
265
+ **返回:**
266
+ - str: 返回结果中的 "instanceUuid" 字段值,如果未找到该字段,则默认返回True。
267
+ """
268
+ return send(
269
+ "GET",
270
+ f"{ApiPool.PROTECTED_INSTANCE}/outputlog",
271
+ params={"daemonId": daemonId, "uuid": uuid, "size": size},
272
+ )
273
+
274
+ def reinstall(
275
+ self,
276
+ daemonId: str,
277
+ uuid: str,
278
+ targetUrl: str,
279
+ title: str = "",
280
+ description: str = "",
281
+ ) -> bool:
282
+ """
283
+ 重装实例。
284
+
285
+ **参数:**
286
+ - daemonId (str): 守护进程的ID,用于标识特定的守护进程。
287
+ - uuid (str): 实例的唯一标识符。
288
+ - targetUrl (str): 重装文件的目标URL。
289
+ - title (str): 重装文件的标题。
290
+ - description (str, optional): 重装文件的描述,默认为空字符串。
291
+
292
+ **返回:**
293
+ - bool: 返回操作结果,成功时返回True。
294
+ """
295
+ return send(
296
+ "POST",
297
+ f"{ApiPool.PROTECTED_INSTANCE}/install_instance",
298
+ params={"uuid": uuid, "daemonId": daemonId},
299
+ data={"targetUrl": targetUrl, "title": title, "description": description},
300
+ )
@@ -0,0 +1,17 @@
1
+ from ..pool import ApiPool
2
+ from ..request import send
3
+ from ..models.overview import OverviewModel
4
+
5
+
6
+ class Overview:
7
+ def init(self):
8
+ """
9
+ 初始化方法,用于获取API概览信息并构建概览模型。
10
+
11
+ 本方法通过发送GET请求获取API概览信息,确保返回的数据类型为字典,
12
+ 然后使用这些数据来构建一个OverviewModel实例。
13
+
14
+ :return: 返回一个OverviewModel实例,该实例使用获取的API概览信息进行初始化。
15
+ """
16
+ result = send("GET", ApiPool.OVERVIEW)
17
+ return OverviewModel(**result)
mcsmapi/apis/user.py ADDED
@@ -0,0 +1,82 @@
1
+ from typing import Any
2
+ from ..pool import ApiPool
3
+ from ..request import send
4
+ from ..models.user import SearchUserModel, UserConfig
5
+
6
+
7
+ class User:
8
+ def search(
9
+ self, username: str = "", page: int = 1, page_size: int = 20, role: str = ""
10
+ ) -> SearchUserModel:
11
+ """根据用户名和角色搜索用户信息
12
+
13
+ **参数:**
14
+ - username (str): 要搜索的用户名。默认为空字符串,表示不进行用户名过滤
15
+ - page (int): 页码,用于指示返回数据的页数。默认为1,表示返回第一页数据
16
+ - page_size (int): 每页大小,用于指定每页包含的数据条数。默认为20,表示每页包含20条数据
17
+ - role (str): 用户权限。默认为空字符串,表示不进行权限过滤
18
+ 可用的值为 1=用户, 10=管理员, -1=被封禁的用户
19
+
20
+ **返回:**
21
+ - SearchUserModel: 包含搜索结果的模型。该模型包含了符合搜索条件的用户信息列表,以及总数据条数、总页数等分页信息。
22
+ """
23
+ result = send(
24
+ "GET",
25
+ f"{ApiPool.AUTH}/search",
26
+ params={
27
+ "userName": username,
28
+ "page": page,
29
+ "pageSize": page_size,
30
+ "role": role,
31
+ },
32
+ )
33
+ return SearchUserModel(**result)
34
+
35
+ def create(self, username: str, password: str, permission: int = 1) -> str | bool:
36
+ """
37
+ 创建新用户的方法
38
+
39
+ **参数:**
40
+ - username (str): 用户名,字符串类型
41
+ - password (str): 密码,字符串类型
42
+ - permission (int): 权限等级,整数类型,默认值为1
43
+
44
+ **返回:**
45
+ - str|bool: 创建成功后返回用户的UUID,如果未找到该字段,则默认返回True。
46
+ """
47
+ return send(
48
+ "POST",
49
+ ApiPool.AUTH,
50
+ data={"username": username, "password": password, "permission": permission},
51
+ ).get("uuid", True)
52
+
53
+ def update(self, uuid: str, config: dict[str, Any]) -> bool:
54
+ """
55
+ 更新用户信息的方法
56
+
57
+ **不建议直接使用此函数,建议调用search后使用update方法按需更新**
58
+
59
+ **参数:**
60
+ - uuid (str): 用户的唯一标识符UUID
61
+ - config (dict[str, Any]): 新的用户信息,以字典形式提供,缺失内容由UserConfig模型补全。
62
+
63
+ **返回:**
64
+ - bool: 成功时返回True
65
+ """
66
+ return send(
67
+ "PUT",
68
+ ApiPool.AUTH,
69
+ data={"uuid": uuid, "config": UserConfig(**config).dict()},
70
+ )
71
+
72
+ def delete(self, uuids: list[str]) -> bool:
73
+ """
74
+ 删除用户的方法
75
+
76
+ **参数:**
77
+ - uuids (list[str]): 包含要删除的用户UUID的列表。
78
+
79
+ **返回:**
80
+ - bool: 成功时返回True
81
+ """
82
+ return send("DELETE", ApiPool.AUTH, data=uuids)
mcsmapi/exceptions.py ADDED
@@ -0,0 +1,5 @@
1
+ class MCSMError(Exception):
2
+ def __init__(self, status_code, data=None):
3
+ self.status_code = status_code
4
+ self.data = data
5
+ super().__init__(status_code, data)
@@ -0,0 +1,134 @@
1
+ from typing import Any, List
2
+ from pydantic import BaseModel
3
+ from ..models.instance import InstanceCreateResult
4
+
5
+
6
+ class CpuMemChart(BaseModel):
7
+ cpu: float = 0
8
+ mem: float = 0
9
+
10
+
11
+ class ProcessInfo(BaseModel):
12
+ cpu: int = 0
13
+ memory: int = 0
14
+ cwd: str = ""
15
+
16
+
17
+ class InstanceInfo(BaseModel):
18
+ running: int = 0
19
+ total: int = 0
20
+
21
+
22
+ class SystemInfo(BaseModel):
23
+ type: str = ""
24
+ hostname: str = ""
25
+ platform: str = ""
26
+ release: str = ""
27
+ uptime: float = 0
28
+ cwd: str = ""
29
+ loadavg: List[float] = []
30
+ freemem: int = 0
31
+ cpuUsage: float = 0
32
+ memUsage: float = 0
33
+ totalmem: int = 0
34
+ processCpu: int = 0
35
+ processMem: int = 0
36
+
37
+
38
+ class DaemonModel(BaseModel):
39
+ version: str = ""
40
+ process: ProcessInfo = ProcessInfo()
41
+ instance: InstanceInfo = InstanceInfo()
42
+ system: SystemInfo = SystemInfo()
43
+ cpuMemChart: List[CpuMemChart] = []
44
+ uuid: str = ""
45
+ ip: str = ""
46
+ port: int = 24444
47
+ prefix: str = ""
48
+ available: bool = False
49
+ remarks: str = ""
50
+
51
+ def delete(self) -> bool:
52
+ """
53
+ 删除该节点。
54
+
55
+ 返回:
56
+ - bool: 删除成功后返回True
57
+ """
58
+ from ..apis.daemon import Daemon
59
+
60
+ return Daemon().delete(self.uuid)
61
+
62
+ def link(self) -> bool:
63
+ """
64
+ 链接该节点。
65
+
66
+ 返回:
67
+ - bool: 链接成功后返回True
68
+ """
69
+ from ..apis.daemon import Daemon
70
+
71
+ return Daemon().link(self.uuid)
72
+
73
+ def updateConfig(self, config: dict[str, Any]) -> bool:
74
+ """
75
+ 更新该节点的配置。
76
+
77
+ 参数:
78
+ - config (dict[str, Any]): 节点的配置信息,以字典形式提供,缺失内容使用原节点配置填充。
79
+
80
+ 返回:
81
+ - bool: 更新成功后返回True
82
+ """
83
+ from ..apis.daemon import Daemon
84
+
85
+ updated_config = self.dict()
86
+ updated_config.update(config)
87
+ # 过滤节点配置中不需要的字段
88
+ daemon_config_dict = {
89
+ key: updated_config[key]
90
+ for key in DaemonConfig.__fields__.keys()
91
+ if key in updated_config
92
+ }
93
+
94
+ daemon_config = DaemonConfig(**daemon_config_dict).dict()
95
+
96
+ return Daemon().update(self.uuid, daemon_config)
97
+
98
+ def createInstance(self, config: dict[str, Any]) -> "InstanceCreateResult":
99
+ """
100
+ 在当前节点创建一个实例。
101
+
102
+ 参数:
103
+ - config (dict[str, Any]): 实例的配置信息,以字典形式提供,缺失内容由InstanceConfig模型补全。
104
+
105
+ 返回:
106
+ - InstanceCreateResult: 一个包含新创建实例信息的结果对象,内容由InstanceCreateResult模型定义。
107
+ """
108
+ from ..apis.instance import Instance
109
+ from .instance import InstanceConfig
110
+
111
+ return Instance().create(self.uuid, InstanceConfig(**config).dict())
112
+
113
+ def deleteInstance(self, uuids: list[str], deleteFile=False) -> list[str]:
114
+ """
115
+ 删除当前节点的一个或多个实例。
116
+
117
+ 参数:
118
+ - uuids (list[str]): 要删除的实例UUID列表。
119
+ - deleteFile (bool, optional): 是否删除关联的文件,默认为False。
120
+
121
+ 返回:
122
+ - list[str]: 删除操作后返回的UUID列表。
123
+ """
124
+ from ..apis.instance import Instance
125
+
126
+ return Instance().delete(self.uuid, uuids, deleteFile)
127
+
128
+
129
+ class DaemonConfig(BaseModel):
130
+ ip: str = "localhost"
131
+ port: int = 24444
132
+ prefix: str = ""
133
+ remarks: str = "New Daemon"
134
+ available: bool = True
mcsmapi/models/file.py ADDED
@@ -0,0 +1,108 @@
1
+ from pydantic import BaseModel
2
+ from typing import List
3
+ import os
4
+
5
+
6
+ class FileItem(BaseModel):
7
+ name: str = "New File"
8
+ size: int = 0 # byte
9
+ time: str = ""
10
+ mode: int = 777 # Linux file permission
11
+ type: int = 0 # 0 = Folder, 1 = File
12
+ daemonId: str = ""
13
+ uuid: str = ""
14
+ target: str = ""
15
+
16
+ def rename(self, newName: str) -> bool:
17
+ """
18
+ 重命名该文件或文件夹。
19
+
20
+ **参数:**
21
+ - new_name (str): 源文件或文件夹的新名字。
22
+
23
+ **返回:**
24
+ - bool: 重命名成功后返回True。
25
+ """
26
+ from ..apis.file import File
27
+
28
+ return File().rename(
29
+ self.daemonId, self.uuid, os.path.join(self.target, self.name), newName
30
+ )
31
+
32
+ def delete(self) -> bool:
33
+ """
34
+ 删除该文件或文件夹。
35
+
36
+ **返回:**
37
+ - bool: 重命名成功后返回True。
38
+ """
39
+ from ..apis.file import File
40
+
41
+ return File().delete(
42
+ self.daemonId, self.uuid, [os.path.join(self.target, self.name)]
43
+ )
44
+
45
+ def copy(self, target: str) -> bool:
46
+ from ..apis.file import File
47
+
48
+ return File().copyOne(
49
+ self.daemonId, self.uuid, os.path.join(self.target, self.name), target
50
+ )
51
+
52
+ def move(self, target: str) -> bool:
53
+ """
54
+ 移动该文件或文件夹到目标路径。
55
+
56
+ **参数:**
57
+ - target (str): 目标文件或文件夹的路径。
58
+
59
+ **返回:**
60
+ - bool: 移动成功后返回True。
61
+ """
62
+ from ..apis.file import File
63
+
64
+ return File().moveOne(
65
+ self.daemonId, self.uuid, os.path.join(self.target, self.name), target
66
+ )
67
+
68
+ def unzip(self, target: str, code: str = "utf-8") -> bool:
69
+ """
70
+ 解压缩该 zip 文件到目标位置。
71
+
72
+ **参数:**
73
+ - target (str): 解压到的目标路径。
74
+ - code (str, optional): 压缩文件的编码方式,默认为"utf-8"。
75
+ 可选值: utf-8, gbk, big5
76
+
77
+ **返回:**
78
+ - bool: 解压成功后返回True。
79
+ """
80
+ from ..apis.file import File
81
+
82
+ return File().unzip(
83
+ self.daemonId, self.uuid, os.path.join(self.target, self.name), target, code
84
+ )
85
+
86
+
87
+ class FileList(BaseModel):
88
+ items: List[FileItem]
89
+ page: int = 0
90
+ pageSize: int = 100
91
+ total: int = 0
92
+ absolutePath: str = "\\"
93
+ daemonId: str = ""
94
+ uuid: str = ""
95
+ target: str = ""
96
+
97
+ def __init__(self, **data: str):
98
+ super().__init__(**data)
99
+ for item in self.items:
100
+ item.daemonId = self.daemonId
101
+ item.uuid = self.uuid
102
+ item.target = self.target
103
+
104
+
105
+
106
+ class CommonConfig(BaseModel):
107
+ password: str = ""
108
+ addr: str = ""