ryry-cli 6.18__tar.gz → 6.19__tar.gz
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.
- {ryry_cli-6.18/ryry_cli.egg-info → ryry_cli-6.19}/PKG-INFO +1 -1
- {ryry_cli-6.18 → ryry_cli-6.19}/ryry/constant.py +2 -2
- {ryry_cli-6.18 → ryry_cli-6.19}/ryry/store.py +1 -1
- {ryry_cli-6.18 → ryry_cli-6.19}/ryry/upload.py +193 -20
- {ryry_cli-6.18 → ryry_cli-6.19}/ryry/utils.py +219 -217
- {ryry_cli-6.18 → ryry_cli-6.19/ryry_cli.egg-info}/PKG-INFO +1 -1
- {ryry_cli-6.18 → ryry_cli-6.19}/setup.py +1 -1
- {ryry_cli-6.18 → ryry_cli-6.19}/LICENSE +0 -0
- {ryry_cli-6.18 → ryry_cli-6.19}/README.md +0 -0
- {ryry_cli-6.18 → ryry_cli-6.19}/ryry/__init__.py +0 -0
- {ryry_cli-6.18 → ryry_cli-6.19}/ryry/daemon_base.py +0 -0
- {ryry_cli-6.18 → ryry_cli-6.19}/ryry/daemon_manager.py +0 -0
- {ryry_cli-6.18 → ryry_cli-6.19}/ryry/main.py +0 -0
- {ryry_cli-6.18 → ryry_cli-6.19}/ryry/proxy_manager.py +0 -0
- {ryry_cli-6.18 → ryry_cli-6.19}/ryry/ryry_server_socket.py +0 -0
- {ryry_cli-6.18 → ryry_cli-6.19}/ryry/ryry_service.py +0 -0
- {ryry_cli-6.18 → ryry_cli-6.19}/ryry/ryry_webapi.py +0 -0
- {ryry_cli-6.18 → ryry_cli-6.19}/ryry/ryry_widget.py +0 -0
- {ryry_cli-6.18 → ryry_cli-6.19}/ryry/script_template/__init__.py +0 -0
- {ryry_cli-6.18 → ryry_cli-6.19}/ryry/script_template/daemon.py +0 -0
- {ryry_cli-6.18 → ryry_cli-6.19}/ryry/script_template/main.py +0 -0
- {ryry_cli-6.18 → ryry_cli-6.19}/ryry/script_template/run.py +0 -0
- {ryry_cli-6.18 → ryry_cli-6.19}/ryry/server_func.py +0 -0
- {ryry_cli-6.18 → ryry_cli-6.19}/ryry/shared_memory.py +0 -0
- {ryry_cli-6.18 → ryry_cli-6.19}/ryry/task.py +0 -0
- {ryry_cli-6.18 → ryry_cli-6.19}/ryry/taskUtils.py +0 -0
- {ryry_cli-6.18 → ryry_cli-6.19}/ryry_cli.egg-info/SOURCES.txt +0 -0
- {ryry_cli-6.18 → ryry_cli-6.19}/ryry_cli.egg-info/dependency_links.txt +0 -0
- {ryry_cli-6.18 → ryry_cli-6.19}/ryry_cli.egg-info/entry_points.txt +0 -0
- {ryry_cli-6.18 → ryry_cli-6.19}/ryry_cli.egg-info/requires.txt +0 -0
- {ryry_cli-6.18 → ryry_cli-6.19}/ryry_cli.egg-info/top_level.txt +0 -0
- {ryry_cli-6.18 → ryry_cli-6.19}/setup.cfg +0 -0
|
@@ -177,7 +177,7 @@ def extend():
|
|
|
177
177
|
_genExtend()
|
|
178
178
|
elif read_data["extend"].get("device_id", "") != read_data.get("deviceInfo", {}).get("device_id", ""):
|
|
179
179
|
_genExtend()
|
|
180
|
-
elif read_data["extend"].get("app", "") == "ryry-cli 6.
|
|
180
|
+
elif read_data["extend"].get("app", "") == "ryry-cli 6.19":
|
|
181
181
|
_genExtend()
|
|
182
182
|
elif any(k not in read_data["extend"] for k in ["device_id", "host_name", "cpu", "memory", "disk", "gpu"]):
|
|
183
183
|
_genExtend()
|
|
@@ -78,8 +78,8 @@ def upload(src, taskUUID=None, needTranscode=False, keepItAlways=False, addition
|
|
|
78
78
|
os.remove(newSrc)
|
|
79
79
|
return ossurl
|
|
80
80
|
|
|
81
|
-
def uploadByDomain(src, targetDomain,
|
|
82
|
-
taskUUID, keepItAlways=False,
|
|
81
|
+
def uploadByDomain(src, targetDomain,
|
|
82
|
+
taskUUID, keepItAlways=False,
|
|
83
83
|
needTranscode=False, additionalUrl=False):
|
|
84
84
|
import os
|
|
85
85
|
from pathlib import Path
|
|
@@ -90,23 +90,33 @@ def uploadByDomain(src, targetDomain,
|
|
|
90
90
|
ext = os.path.splitext(file_name)[-1][1:]
|
|
91
91
|
|
|
92
92
|
parsed_domain, upload_path = parseDomainAndPath(targetDomain)
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
|
|
94
|
+
s3_config = getS3Config(parsed_domain)
|
|
95
|
+
if s3_config:
|
|
96
|
+
if isS3ConfigReady(s3_config):
|
|
97
|
+
new_file_name = ''.join(str(uuid.uuid4()).split('-'))
|
|
98
|
+
return uploadToS3(src, f"{new_file_name}.{ext}", s3_config, upload_path)
|
|
99
|
+
return uploadByApiFallback(src, ext, s3_config.get("fallback"),
|
|
100
|
+
keepItAlways=keepItAlways,
|
|
101
|
+
needTranscode=needTranscode,
|
|
102
|
+
additionalUrl=additionalUrl)
|
|
103
|
+
|
|
96
104
|
oss_config = getOssConfig(parsed_domain)
|
|
97
105
|
if oss_config:
|
|
98
106
|
new_file_name = ''.join(str(uuid.uuid4()).split('-'))
|
|
99
107
|
return uploadToOss(src, f"{new_file_name}.{ext}", oss_config, upload_path)
|
|
100
|
-
|
|
108
|
+
|
|
109
|
+
if isMekoConfig(parsed_domain):
|
|
110
|
+
return uploadToMeko(src, ext=ext)
|
|
111
|
+
|
|
101
112
|
ftp_config = getFtpConfig(parsed_domain)
|
|
102
113
|
if ftp_config:
|
|
103
114
|
return ftpUpload(src, file_name, ftp_config, upload_path)
|
|
104
115
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
additionalUrl=additionalUrl)
|
|
116
|
+
return uploadByApiFallback(src, ext, "dalipen_api",
|
|
117
|
+
keepItAlways=keepItAlways,
|
|
118
|
+
needTranscode=needTranscode,
|
|
119
|
+
additionalUrl=additionalUrl)
|
|
110
120
|
|
|
111
121
|
def parseDomainAndPath(targetDomain):
|
|
112
122
|
from urllib.parse import urlparse
|
|
@@ -131,13 +141,29 @@ def parseDomainAndPath(targetDomain):
|
|
|
131
141
|
def uploadToMeko(file_path: str, ext: str = ".jpg") -> str:
|
|
132
142
|
import requests
|
|
133
143
|
url = "https://api.mekoapp.com/upload/create"
|
|
134
|
-
|
|
144
|
+
|
|
135
145
|
with open(file_path, "rb") as f:
|
|
136
146
|
files = {"file": (file_path.split("/")[-1], f)}
|
|
137
147
|
data = {"ext": ext}
|
|
138
148
|
response = requests.post(url, files=files, data=data)
|
|
139
149
|
response.raise_for_status()
|
|
140
|
-
|
|
150
|
+
result = response.json()
|
|
151
|
+
if "url" in result:
|
|
152
|
+
return result["url"]
|
|
153
|
+
if result.get("code") == 0 and result.get("data"):
|
|
154
|
+
return result["data"]
|
|
155
|
+
raise Exception(f"meko upload failed: {result}")
|
|
156
|
+
|
|
157
|
+
def uploadByApiFallback(src, ext, fallback,
|
|
158
|
+
keepItAlways=False, needTranscode=False, additionalUrl=False):
|
|
159
|
+
if fallback == "meko_api":
|
|
160
|
+
return uploadToMeko(src, ext=ext)
|
|
161
|
+
|
|
162
|
+
from ryry import ryry_webapi
|
|
163
|
+
return ryry_webapi.upload(src, ext,
|
|
164
|
+
keepItAlways=keepItAlways or fallback == "dalipen_datanet_api",
|
|
165
|
+
needTranscode=needTranscode,
|
|
166
|
+
additionalUrl=additionalUrl)
|
|
141
167
|
|
|
142
168
|
def uploadToOss(file, new_file_name, oss_config, upload_path=""):
|
|
143
169
|
import hashlib
|
|
@@ -182,6 +208,35 @@ def uploadToOss(file, new_file_name, oss_config, upload_path=""):
|
|
|
182
208
|
else:
|
|
183
209
|
raise Exception(f"OSS upload failed: {response.status_code}")
|
|
184
210
|
|
|
211
|
+
def _safe_join_path(*parts):
|
|
212
|
+
clean_parts = []
|
|
213
|
+
for part in parts:
|
|
214
|
+
if not part:
|
|
215
|
+
continue
|
|
216
|
+
clean = str(part).strip("/")
|
|
217
|
+
if clean:
|
|
218
|
+
clean_parts.append(clean)
|
|
219
|
+
return "/".join(clean_parts)
|
|
220
|
+
|
|
221
|
+
def _s3_object_key(new_file_name, s3_config, upload_path=""):
|
|
222
|
+
if upload_path:
|
|
223
|
+
return _safe_join_path(upload_path, new_file_name)
|
|
224
|
+
return _safe_join_path("temp", new_file_name)
|
|
225
|
+
|
|
226
|
+
def uploadToS3(file, new_file_name, s3_config, upload_path=""):
|
|
227
|
+
bucket = s3_config["bucket"]
|
|
228
|
+
content_type = s3_config.get("content_type", "application/octet-stream")
|
|
229
|
+
object_key = _s3_object_key(new_file_name, s3_config, upload_path)
|
|
230
|
+
s3_client = getS3Client(s3_config)
|
|
231
|
+
with open(file, "rb") as f:
|
|
232
|
+
s3_client.put_object(
|
|
233
|
+
Bucket=bucket,
|
|
234
|
+
Key=object_key,
|
|
235
|
+
Body=f,
|
|
236
|
+
ContentType=content_type,
|
|
237
|
+
)
|
|
238
|
+
return f"{s3_config['domain'].rstrip('/')}/{object_key}"
|
|
239
|
+
|
|
185
240
|
def deepFtpUpload(file, new_file_name, ftp, writepath, readpath):
|
|
186
241
|
try:
|
|
187
242
|
safe_cwd(ftp, writepath)
|
|
@@ -280,6 +335,32 @@ ftp_219_136_123_179={
|
|
|
280
335
|
}
|
|
281
336
|
|
|
282
337
|
from ryry import utils
|
|
338
|
+
_s3_client_cache = {}
|
|
339
|
+
def getS3Client(s3_config):
|
|
340
|
+
import boto3
|
|
341
|
+
from botocore.config import Config
|
|
342
|
+
|
|
343
|
+
a_k_i, s_a_k = utils._decode_key(utils.RK11), utils._decode_key(utils.RK22)
|
|
344
|
+
endpoint = s3_config["endpoint"].rstrip("/")
|
|
345
|
+
region = s3_config.get("region", "auto")
|
|
346
|
+
cache_key = (endpoint, region, a_k_i)
|
|
347
|
+
if cache_key not in _s3_client_cache:
|
|
348
|
+
_s3_client_cache[cache_key] = boto3.client(
|
|
349
|
+
"s3",
|
|
350
|
+
endpoint_url=endpoint,
|
|
351
|
+
aws_access_key_id=a_k_i,
|
|
352
|
+
aws_secret_access_key=s_a_k,
|
|
353
|
+
region_name=region,
|
|
354
|
+
config=Config(
|
|
355
|
+
signature_version="s3v4",
|
|
356
|
+
connect_timeout=10,
|
|
357
|
+
read_timeout=100,
|
|
358
|
+
retries={"max_attempts": 3, "mode": "standard"},
|
|
359
|
+
s3={"addressing_style": "path"},
|
|
360
|
+
),
|
|
361
|
+
)
|
|
362
|
+
return _s3_client_cache[cache_key]
|
|
363
|
+
|
|
283
364
|
oss_res_config = {
|
|
284
365
|
"bucket": "p-res-gz",
|
|
285
366
|
"endpoint": "oss-cn-guangzhou.aliyuncs.com",
|
|
@@ -298,6 +379,16 @@ oss_template_config = {
|
|
|
298
379
|
"domain": "https://oss.zjtemplate.com"
|
|
299
380
|
}
|
|
300
381
|
|
|
382
|
+
REP = utils._decode_key(utils.RK23)
|
|
383
|
+
def r2Config(bucket, domain, fallback="dalipen_api"):
|
|
384
|
+
return {
|
|
385
|
+
"bucket": bucket,
|
|
386
|
+
"endpoint": REP,
|
|
387
|
+
"region": "auto",
|
|
388
|
+
"domain": f"https://{domain}",
|
|
389
|
+
"fallback": fallback,
|
|
390
|
+
}
|
|
391
|
+
|
|
301
392
|
def match_wildcard_domain(target_domain, pattern):
|
|
302
393
|
if pattern.startswith("*."):
|
|
303
394
|
suffix = pattern[1:] # 去掉 "*." 前缀
|
|
@@ -323,10 +414,19 @@ DOMAIN_CONFIG = {
|
|
|
323
414
|
# "ftp://192.168.50.12/mnt/NAS/mcn/cache": {"type": "ftp", "config": ftp_192_168_50_12},
|
|
324
415
|
# "ftp://183.6.90.205/mnt/NAS/mcn/cache": {"type": "ftp", "config": ftp_219_136_123_179},
|
|
325
416
|
# "ftp://219.136.123.179/mnt/NAS/mcn/cache": {"type": "ftp", "config": ftp_219_136_123_179},
|
|
417
|
+
"app-upload.dalipen.com": {"type": "s3", "config": r2Config("p-app-upload", "app-upload.dalipen.com")},
|
|
418
|
+
"datanet.dalipen.com": {"type": "s3", "config": r2Config("p-crawler", "datanet.dalipen.com", "dalipen_datanet_api")},
|
|
419
|
+
"model.dalipen.com": {"type": "s3", "config": r2Config("p-model", "model.dalipen.com")},
|
|
420
|
+
"r2.dalipen.com": {"type": "s3", "config": r2Config("p-template", "r2.dalipen.com")},
|
|
421
|
+
"upload.dalipen.com": {"type": "s3", "config": r2Config("p-upload", "upload.dalipen.com"), "oversea": True},
|
|
422
|
+
"widget.dalipen.com": {"type": "s3", "config": r2Config("p-widget", "widget.dalipen.com")},
|
|
423
|
+
"app-upload.mekoapp.com": {"type": "s3", "config": r2Config("p-app-upload", "app-upload.mekoapp.com", "meko_api")},
|
|
424
|
+
"m.mekoapp.com": {"type": "s3", "config": r2Config("p-app-upload", "m.mekoapp.com", "meko_api")},
|
|
425
|
+
"upload.mekoapp.com": {"type": "s3", "config": r2Config("p-upload", "upload.mekoapp.com", "meko_api")},
|
|
326
426
|
"res.zjtemplate.com": {"type": "oss", "config": oss_res_config},
|
|
327
|
-
"upload.zjtemplate.com": {"type": "oss", "config": oss_upload_config},
|
|
427
|
+
"upload.zjtemplate.com": {"type": "oss", "config": oss_upload_config, "oversea": False},
|
|
328
428
|
"oss.zjtemplate.com": {"type": "oss", "config": oss_template_config},
|
|
329
|
-
"*.mekoapp.com": {"type": "", "config": {}},
|
|
429
|
+
"*.mekoapp.com": {"type": "meko_api", "config": {}},
|
|
330
430
|
}
|
|
331
431
|
|
|
332
432
|
FTP_REPLACEMENT = {
|
|
@@ -356,9 +456,24 @@ def getOssConfig(targetDomain):
|
|
|
356
456
|
return config["config"]
|
|
357
457
|
return None
|
|
358
458
|
|
|
459
|
+
def isS3ConfigReady(s3_config):
|
|
460
|
+
return all([
|
|
461
|
+
s3_config.get("bucket"),
|
|
462
|
+
s3_config.get("endpoint"),
|
|
463
|
+
s3_config.get("domain"),
|
|
464
|
+
])
|
|
465
|
+
|
|
466
|
+
def getS3Config(targetDomain):
|
|
467
|
+
config = get_domain_config(targetDomain)
|
|
468
|
+
if config and config["type"] == "s3":
|
|
469
|
+
return config["config"]
|
|
470
|
+
return None
|
|
471
|
+
|
|
359
472
|
def isMekoConfig(targetDomain):
|
|
360
473
|
config = get_domain_config(targetDomain)
|
|
361
|
-
if config:
|
|
474
|
+
if config and config["type"] == "meko_api":
|
|
475
|
+
return True
|
|
476
|
+
if config and config.get("config", {}).get("fallback") == "meko_api":
|
|
362
477
|
return True
|
|
363
478
|
return False
|
|
364
479
|
|
|
@@ -385,16 +500,74 @@ def getSubdomain(targetDomain):
|
|
|
385
500
|
return None
|
|
386
501
|
|
|
387
502
|
def getFirstSupportSubdomain():
|
|
388
|
-
def
|
|
503
|
+
def ping_ms(host, timeout=1):
|
|
504
|
+
import platform
|
|
505
|
+
import re
|
|
506
|
+
import subprocess
|
|
507
|
+
try:
|
|
508
|
+
if platform.system() == "Windows":
|
|
509
|
+
cmd = ["ping", "-n", "1", "-w", str(int(timeout * 1000)), host]
|
|
510
|
+
else:
|
|
511
|
+
cmd = ["ping", "-c", "1", host]
|
|
512
|
+
result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
|
|
513
|
+
timeout=timeout + 0.5, text=True)
|
|
514
|
+
if result.returncode != 0:
|
|
515
|
+
return None
|
|
516
|
+
match = re.search(r"(?:time|时间)[=<]\s*([0-9.]+)\s*ms", result.stdout, re.IGNORECASE)
|
|
517
|
+
if match:
|
|
518
|
+
return float(match.group(1))
|
|
519
|
+
except:
|
|
520
|
+
pass
|
|
521
|
+
return None
|
|
522
|
+
|
|
523
|
+
def is_oversea_network():
|
|
524
|
+
baidu_ms = ping_ms("baidu.com", timeout=1)
|
|
525
|
+
if baidu_ms is not None and baidu_ms <= 80:
|
|
526
|
+
return False
|
|
527
|
+
|
|
528
|
+
google_ms = ping_ms("google.com", timeout=1)
|
|
529
|
+
if google_ms is None and baidu_ms is not None:
|
|
530
|
+
return False
|
|
531
|
+
if google_ms is not None and baidu_ms is None:
|
|
532
|
+
return True
|
|
533
|
+
if google_ms is not None and baidu_ms is not None:
|
|
534
|
+
return google_ms < baidu_ms
|
|
535
|
+
return None
|
|
536
|
+
|
|
537
|
+
def get_network_hash(oversea):
|
|
389
538
|
import socket
|
|
390
539
|
from hashlib import md5
|
|
391
540
|
try:
|
|
392
541
|
local_ip = socket.gethostbyname('localhost')
|
|
393
542
|
except socket.gaierror:
|
|
394
543
|
local_ip = '127.0.0.1' # 默认回退到 localhost 地址
|
|
395
|
-
return md5(local_ip.encode('utf-8')).hexdigest()
|
|
396
|
-
|
|
544
|
+
return md5(f"{local_ip}:{oversea}".encode('utf-8')).hexdigest()
|
|
545
|
+
|
|
546
|
+
def configToSupportSubdomain(config):
|
|
547
|
+
if config["type"] == "s3":
|
|
548
|
+
s3_config = config["config"]
|
|
549
|
+
return {"type": "s3", "config": s3_config, "domain": s3_config["domain"]}
|
|
550
|
+
if config["type"] == "oss":
|
|
551
|
+
return {"type": "oss", "config": config["config"], "domain": config["config"]["domain"]}
|
|
552
|
+
if config["type"] == "ftp":
|
|
553
|
+
ftp_config = config["config"]
|
|
554
|
+
if _can_connect_ftp(ftp_config["host"], ftp_config["port"], ftp_config["username"], ftp_config["password"], ftp_config["writepath"]):
|
|
555
|
+
return {"type": "ftp", "config": ftp_config, "domain": ftp_config["readpath"]}
|
|
556
|
+
return None
|
|
557
|
+
|
|
558
|
+
oversea = is_oversea_network()
|
|
559
|
+
network_hash = get_network_hash(oversea)
|
|
560
|
+
|
|
397
561
|
def _getFirstSupportSubdomain():
|
|
562
|
+
if oversea is not None:
|
|
563
|
+
for domain, config in DOMAIN_CONFIG.items():
|
|
564
|
+
if config.get("oversea", None) != oversea:
|
|
565
|
+
continue
|
|
566
|
+
support = configToSupportSubdomain(config)
|
|
567
|
+
if support:
|
|
568
|
+
support["oversea"] = oversea
|
|
569
|
+
return support
|
|
570
|
+
|
|
398
571
|
for domain, config in DOMAIN_CONFIG.items():
|
|
399
572
|
if config["type"] == "oss":
|
|
400
573
|
return {"type": "oss", "config": config["config"], "domain": config["config"]["domain"]}
|
|
@@ -657,4 +830,4 @@ def downloadDir(url, saveDir, useCount=-1, autoDelete=False):
|
|
|
657
830
|
print(f"url {url} not support")
|
|
658
831
|
except Exception as e:
|
|
659
832
|
print(f"downloadDir fail: {e}")
|
|
660
|
-
return None
|
|
833
|
+
return None
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import uuid
|
|
2
2
|
import platform
|
|
3
|
-
import subprocess
|
|
4
|
-
import os
|
|
5
|
-
import sys
|
|
6
|
-
import requests
|
|
7
|
-
import time
|
|
8
|
-
from io import BytesIO
|
|
9
|
-
import psutil
|
|
3
|
+
import subprocess
|
|
4
|
+
import os
|
|
5
|
+
import sys
|
|
6
|
+
import requests
|
|
7
|
+
import time
|
|
8
|
+
from io import BytesIO
|
|
9
|
+
import psutil
|
|
10
10
|
try:
|
|
11
11
|
import pynvml
|
|
12
12
|
except ImportError:
|
|
@@ -120,219 +120,219 @@ def generate_unique_id():
|
|
|
120
120
|
unique_id = uuid.uuid5(uuid.NAMESPACE_DNS, mac + hostname)
|
|
121
121
|
return str(unique_id).replace('-', '')
|
|
122
122
|
|
|
123
|
-
def getOssImageSize(p):
|
|
124
|
-
try:
|
|
125
|
-
s = requests.session()
|
|
123
|
+
def getOssImageSize(p):
|
|
124
|
+
try:
|
|
125
|
+
s = requests.session()
|
|
126
126
|
s.keep_alive = False
|
|
127
127
|
res = s.get(p, timeout=60)
|
|
128
128
|
image = Image.open(BytesIO(res.content), "r")
|
|
129
129
|
s.close()
|
|
130
130
|
return image.size
|
|
131
|
-
except:
|
|
132
|
-
return 0, 0
|
|
133
|
-
|
|
134
|
-
def _round_float(value, digits=2):
|
|
135
|
-
try:
|
|
136
|
-
return round(float(value), digits)
|
|
137
|
-
except:
|
|
138
|
-
return None
|
|
139
|
-
|
|
140
|
-
def _percent(used, total):
|
|
141
|
-
try:
|
|
142
|
-
if not total:
|
|
143
|
-
return 0
|
|
144
|
-
return round((float(used) / float(total)) * 100, 2)
|
|
145
|
-
except:
|
|
146
|
-
return 0
|
|
147
|
-
|
|
148
|
-
def _load_average(logical_count):
|
|
149
|
-
try:
|
|
150
|
-
load1, load5, load15 = os.getloadavg()
|
|
151
|
-
normalized = _percent(load1, logical_count or 1)
|
|
152
|
-
return {
|
|
153
|
-
"1m": _round_float(load1),
|
|
154
|
-
"5m": _round_float(load5),
|
|
155
|
-
"15m": _round_float(load15),
|
|
156
|
-
"percent_1m": normalized
|
|
157
|
-
}
|
|
158
|
-
except:
|
|
159
|
-
return {
|
|
160
|
-
"1m": None,
|
|
161
|
-
"5m": None,
|
|
162
|
-
"15m": None,
|
|
163
|
-
"percent_1m": None
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
def _decode_gpu_name(name):
|
|
167
|
-
try:
|
|
168
|
-
if isinstance(name, bytes):
|
|
169
|
-
return name.decode("utf-8")
|
|
170
|
-
return str(name)
|
|
171
|
-
except:
|
|
172
|
-
return "Unknown GPU"
|
|
173
|
-
|
|
174
|
-
def _collect_gpu_info(G):
|
|
175
|
-
gpu_info = {
|
|
176
|
-
"count": 0,
|
|
177
|
-
"list": [],
|
|
178
|
-
"mem": [],
|
|
179
|
-
"devices": []
|
|
180
|
-
}
|
|
181
|
-
try:
|
|
182
|
-
if pynvml is None:
|
|
183
|
-
raise ImportError("pynvml/nvidia-ml-py not available")
|
|
184
|
-
pynvml.nvmlInit()
|
|
185
|
-
gpu_count = pynvml.nvmlDeviceGetCount()
|
|
186
|
-
gpu_info["count"] = gpu_count
|
|
187
|
-
for i in range(gpu_count):
|
|
188
|
-
handle = pynvml.nvmlDeviceGetHandleByIndex(i)
|
|
189
|
-
name = _decode_gpu_name(pynvml.nvmlDeviceGetName(handle))
|
|
190
|
-
mem_info = pynvml.nvmlDeviceGetMemoryInfo(handle)
|
|
191
|
-
used_gb = _round_float(mem_info.used / G)
|
|
192
|
-
free_gb = _round_float(mem_info.free / G)
|
|
193
|
-
total_gb = _round_float(mem_info.total / G)
|
|
194
|
-
memory_percent = _percent(mem_info.used, mem_info.total)
|
|
195
|
-
utilization_percent = None
|
|
196
|
-
temperature_c = None
|
|
197
|
-
power_w = None
|
|
198
|
-
try:
|
|
199
|
-
utilization_percent = pynvml.nvmlDeviceGetUtilizationRates(handle).gpu
|
|
200
|
-
except:
|
|
201
|
-
pass
|
|
202
|
-
try:
|
|
203
|
-
temperature_c = pynvml.nvmlDeviceGetTemperature(handle, pynvml.NVML_TEMPERATURE_GPU)
|
|
204
|
-
except:
|
|
205
|
-
pass
|
|
206
|
-
try:
|
|
207
|
-
power_w = _round_float(pynvml.nvmlDeviceGetPowerUsage(handle) / 1000)
|
|
208
|
-
except:
|
|
209
|
-
pass
|
|
210
|
-
gpu_info["list"].append(f"GPU{i}: {name}")
|
|
211
|
-
gpu_info["mem"].append(f"GPU{i}: total:{total_gb:.1f} G free:{free_gb:.1f} G")
|
|
212
|
-
gpu_info["devices"].append({
|
|
213
|
-
"index": i,
|
|
214
|
-
"name": name,
|
|
215
|
-
"memory_total_gb": total_gb,
|
|
216
|
-
"memory_used_gb": used_gb,
|
|
217
|
-
"memory_free_gb": free_gb,
|
|
218
|
-
"memory_percent": memory_percent,
|
|
219
|
-
"utilization_percent": utilization_percent,
|
|
220
|
-
"temperature_c": temperature_c,
|
|
221
|
-
"power_w": power_w
|
|
222
|
-
})
|
|
223
|
-
pynvml.nvmlShutdown()
|
|
224
|
-
except Exception as e:
|
|
225
|
-
gpu_info["error"] = str(e)
|
|
226
|
-
try:
|
|
227
|
-
pynvml.nvmlShutdown()
|
|
228
|
-
except:
|
|
229
|
-
pass
|
|
230
|
-
return gpu_info
|
|
231
|
-
|
|
232
|
-
def runtimeInfo():
|
|
233
|
-
G = 1024 * 1024 * 1024
|
|
234
|
-
logical_count = psutil.cpu_count() or 1
|
|
235
|
-
virtual_mem = psutil.virtual_memory()
|
|
236
|
-
disk = psutil.disk_usage("/")
|
|
237
|
-
metrics = {
|
|
238
|
-
"timestamp": int(time.time()),
|
|
239
|
-
"cpu": {
|
|
240
|
-
"percent": _round_float(psutil.cpu_percent(interval=0.1)),
|
|
241
|
-
"logical_count": logical_count,
|
|
242
|
-
"physical_count": psutil.cpu_count(logical=False),
|
|
243
|
-
"load_avg": _load_average(logical_count)
|
|
244
|
-
},
|
|
245
|
-
"memory": {
|
|
246
|
-
"total_gb": _round_float(virtual_mem.total / G),
|
|
247
|
-
"available_gb": _round_float(virtual_mem.available / G),
|
|
248
|
-
"used_gb": _round_float(virtual_mem.used / G),
|
|
249
|
-
"free_gb": _round_float(virtual_mem.free / G),
|
|
250
|
-
"percent": _round_float(virtual_mem.percent)
|
|
251
|
-
},
|
|
252
|
-
"disk": {
|
|
253
|
-
"path": "/",
|
|
254
|
-
"total_gb": _round_float(disk.total / G),
|
|
255
|
-
"used_gb": _round_float(disk.used / G),
|
|
256
|
-
"free_gb": _round_float(disk.free / G),
|
|
257
|
-
"percent": _round_float(disk.percent)
|
|
258
|
-
},
|
|
259
|
-
"gpu": _collect_gpu_info(G),
|
|
260
|
-
"task_slots": {
|
|
261
|
-
"max": 1,
|
|
262
|
-
"cur": 0,
|
|
263
|
-
"idle": 1,
|
|
264
|
-
"usage_percent": 0,
|
|
265
|
-
"widget_power": {}
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
try:
|
|
269
|
-
from ryry.shared_memory import shared_memory_service
|
|
270
|
-
max_counter = shared_memory_service.get_max_counter()
|
|
271
|
-
cur_counter = shared_memory_service.get_cur_counter()
|
|
272
|
-
widget_power = shared_memory_service.get_all_widget_power()
|
|
273
|
-
if max_counter >= 999 and cur_counter == 0 and not widget_power:
|
|
274
|
-
max_counter = 1
|
|
275
|
-
idle_counter = max(0, max_counter - cur_counter)
|
|
276
|
-
metrics["task_slots"] = {
|
|
277
|
-
"max": max_counter,
|
|
278
|
-
"cur": cur_counter,
|
|
279
|
-
"idle": idle_counter,
|
|
280
|
-
"usage_percent": _percent(cur_counter, max_counter),
|
|
281
|
-
"widget_power": widget_power
|
|
282
|
-
}
|
|
283
|
-
except:
|
|
284
|
-
pass
|
|
285
|
-
return metrics
|
|
286
|
-
|
|
287
|
-
def deviceInfo():
|
|
288
|
-
mac = get_mac_address()
|
|
289
|
-
mac = "" if mac == None else mac
|
|
290
|
-
cpu_serial = get_cpu_serial()
|
|
291
|
-
cpu_serial = "" if cpu_serial == None else cpu_serial
|
|
292
|
-
hostname = get_hostname()
|
|
293
|
-
G=1024*1024*1024
|
|
294
|
-
cpu_freq = None
|
|
295
|
-
cpu_cur_freq = None
|
|
296
|
-
try:
|
|
297
|
-
freq = psutil.cpu_freq()
|
|
298
|
-
if freq:
|
|
299
|
-
cpu_freq = freq.max / 1000 if freq.max else None
|
|
300
|
-
cpu_cur_freq = freq.current / 1000 if freq.current else None
|
|
301
|
-
except:
|
|
302
|
-
pass
|
|
303
|
-
|
|
304
|
-
virtual_mem = psutil.virtual_memory()
|
|
305
|
-
disk = psutil.disk_usage("/")
|
|
306
|
-
runtime = runtimeInfo()
|
|
307
|
-
data = {
|
|
308
|
-
"cpu": {
|
|
309
|
-
"logical_count" : psutil.cpu_count(),
|
|
310
|
-
"count" : psutil.cpu_count(logical=False),
|
|
311
|
-
"max_freq" : f"{cpu_freq} GHz" if cpu_freq else "None",
|
|
312
|
-
"current_freq" : f"{cpu_cur_freq} GHz" if cpu_cur_freq else "None",
|
|
313
|
-
"percent" : runtime["cpu"].get("percent"),
|
|
314
|
-
"load_avg": runtime["cpu"].get("load_avg")
|
|
315
|
-
},
|
|
316
|
-
"disk": {
|
|
317
|
-
"total": f"{(disk.total / G):.1f} G",
|
|
318
|
-
"used": f"{(disk.used / G):.1f} G",
|
|
319
|
-
"free": f"{(disk.free / G):.1f} G",
|
|
320
|
-
"percent": f"{disk.percent}%"
|
|
321
|
-
},
|
|
322
|
-
"memory": {
|
|
323
|
-
"total": f"{(virtual_mem.total / G):.1f} G",
|
|
324
|
-
"available": f"{(virtual_mem.available / G):.1f} G",
|
|
325
|
-
"used": f"{(virtual_mem.used / G):.1f} G",
|
|
326
|
-
"free": f"{(virtual_mem.free / G):.1f} G",
|
|
327
|
-
"percent": f"{virtual_mem.percent}%"
|
|
328
|
-
},
|
|
329
|
-
"gpu": runtime["gpu"],
|
|
330
|
-
"device_id": generate_unique_id(),
|
|
331
|
-
"host_name": hostname,
|
|
332
|
-
"task_slots": runtime["task_slots"],
|
|
333
|
-
"timestamp": runtime["timestamp"]
|
|
334
|
-
}
|
|
335
|
-
return data
|
|
131
|
+
except:
|
|
132
|
+
return 0, 0
|
|
133
|
+
|
|
134
|
+
def _round_float(value, digits=2):
|
|
135
|
+
try:
|
|
136
|
+
return round(float(value), digits)
|
|
137
|
+
except:
|
|
138
|
+
return None
|
|
139
|
+
|
|
140
|
+
def _percent(used, total):
|
|
141
|
+
try:
|
|
142
|
+
if not total:
|
|
143
|
+
return 0
|
|
144
|
+
return round((float(used) / float(total)) * 100, 2)
|
|
145
|
+
except:
|
|
146
|
+
return 0
|
|
147
|
+
|
|
148
|
+
def _load_average(logical_count):
|
|
149
|
+
try:
|
|
150
|
+
load1, load5, load15 = os.getloadavg()
|
|
151
|
+
normalized = _percent(load1, logical_count or 1)
|
|
152
|
+
return {
|
|
153
|
+
"1m": _round_float(load1),
|
|
154
|
+
"5m": _round_float(load5),
|
|
155
|
+
"15m": _round_float(load15),
|
|
156
|
+
"percent_1m": normalized
|
|
157
|
+
}
|
|
158
|
+
except:
|
|
159
|
+
return {
|
|
160
|
+
"1m": None,
|
|
161
|
+
"5m": None,
|
|
162
|
+
"15m": None,
|
|
163
|
+
"percent_1m": None
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
def _decode_gpu_name(name):
|
|
167
|
+
try:
|
|
168
|
+
if isinstance(name, bytes):
|
|
169
|
+
return name.decode("utf-8")
|
|
170
|
+
return str(name)
|
|
171
|
+
except:
|
|
172
|
+
return "Unknown GPU"
|
|
173
|
+
|
|
174
|
+
def _collect_gpu_info(G):
|
|
175
|
+
gpu_info = {
|
|
176
|
+
"count": 0,
|
|
177
|
+
"list": [],
|
|
178
|
+
"mem": [],
|
|
179
|
+
"devices": []
|
|
180
|
+
}
|
|
181
|
+
try:
|
|
182
|
+
if pynvml is None:
|
|
183
|
+
raise ImportError("pynvml/nvidia-ml-py not available")
|
|
184
|
+
pynvml.nvmlInit()
|
|
185
|
+
gpu_count = pynvml.nvmlDeviceGetCount()
|
|
186
|
+
gpu_info["count"] = gpu_count
|
|
187
|
+
for i in range(gpu_count):
|
|
188
|
+
handle = pynvml.nvmlDeviceGetHandleByIndex(i)
|
|
189
|
+
name = _decode_gpu_name(pynvml.nvmlDeviceGetName(handle))
|
|
190
|
+
mem_info = pynvml.nvmlDeviceGetMemoryInfo(handle)
|
|
191
|
+
used_gb = _round_float(mem_info.used / G)
|
|
192
|
+
free_gb = _round_float(mem_info.free / G)
|
|
193
|
+
total_gb = _round_float(mem_info.total / G)
|
|
194
|
+
memory_percent = _percent(mem_info.used, mem_info.total)
|
|
195
|
+
utilization_percent = None
|
|
196
|
+
temperature_c = None
|
|
197
|
+
power_w = None
|
|
198
|
+
try:
|
|
199
|
+
utilization_percent = pynvml.nvmlDeviceGetUtilizationRates(handle).gpu
|
|
200
|
+
except:
|
|
201
|
+
pass
|
|
202
|
+
try:
|
|
203
|
+
temperature_c = pynvml.nvmlDeviceGetTemperature(handle, pynvml.NVML_TEMPERATURE_GPU)
|
|
204
|
+
except:
|
|
205
|
+
pass
|
|
206
|
+
try:
|
|
207
|
+
power_w = _round_float(pynvml.nvmlDeviceGetPowerUsage(handle) / 1000)
|
|
208
|
+
except:
|
|
209
|
+
pass
|
|
210
|
+
gpu_info["list"].append(f"GPU{i}: {name}")
|
|
211
|
+
gpu_info["mem"].append(f"GPU{i}: total:{total_gb:.1f} G free:{free_gb:.1f} G")
|
|
212
|
+
gpu_info["devices"].append({
|
|
213
|
+
"index": i,
|
|
214
|
+
"name": name,
|
|
215
|
+
"memory_total_gb": total_gb,
|
|
216
|
+
"memory_used_gb": used_gb,
|
|
217
|
+
"memory_free_gb": free_gb,
|
|
218
|
+
"memory_percent": memory_percent,
|
|
219
|
+
"utilization_percent": utilization_percent,
|
|
220
|
+
"temperature_c": temperature_c,
|
|
221
|
+
"power_w": power_w
|
|
222
|
+
})
|
|
223
|
+
pynvml.nvmlShutdown()
|
|
224
|
+
except Exception as e:
|
|
225
|
+
gpu_info["error"] = str(e)
|
|
226
|
+
try:
|
|
227
|
+
pynvml.nvmlShutdown()
|
|
228
|
+
except:
|
|
229
|
+
pass
|
|
230
|
+
return gpu_info
|
|
231
|
+
|
|
232
|
+
def runtimeInfo():
|
|
233
|
+
G = 1024 * 1024 * 1024
|
|
234
|
+
logical_count = psutil.cpu_count() or 1
|
|
235
|
+
virtual_mem = psutil.virtual_memory()
|
|
236
|
+
disk = psutil.disk_usage("/")
|
|
237
|
+
metrics = {
|
|
238
|
+
"timestamp": int(time.time()),
|
|
239
|
+
"cpu": {
|
|
240
|
+
"percent": _round_float(psutil.cpu_percent(interval=0.1)),
|
|
241
|
+
"logical_count": logical_count,
|
|
242
|
+
"physical_count": psutil.cpu_count(logical=False),
|
|
243
|
+
"load_avg": _load_average(logical_count)
|
|
244
|
+
},
|
|
245
|
+
"memory": {
|
|
246
|
+
"total_gb": _round_float(virtual_mem.total / G),
|
|
247
|
+
"available_gb": _round_float(virtual_mem.available / G),
|
|
248
|
+
"used_gb": _round_float(virtual_mem.used / G),
|
|
249
|
+
"free_gb": _round_float(virtual_mem.free / G),
|
|
250
|
+
"percent": _round_float(virtual_mem.percent)
|
|
251
|
+
},
|
|
252
|
+
"disk": {
|
|
253
|
+
"path": "/",
|
|
254
|
+
"total_gb": _round_float(disk.total / G),
|
|
255
|
+
"used_gb": _round_float(disk.used / G),
|
|
256
|
+
"free_gb": _round_float(disk.free / G),
|
|
257
|
+
"percent": _round_float(disk.percent)
|
|
258
|
+
},
|
|
259
|
+
"gpu": _collect_gpu_info(G),
|
|
260
|
+
"task_slots": {
|
|
261
|
+
"max": 1,
|
|
262
|
+
"cur": 0,
|
|
263
|
+
"idle": 1,
|
|
264
|
+
"usage_percent": 0,
|
|
265
|
+
"widget_power": {}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
try:
|
|
269
|
+
from ryry.shared_memory import shared_memory_service
|
|
270
|
+
max_counter = shared_memory_service.get_max_counter()
|
|
271
|
+
cur_counter = shared_memory_service.get_cur_counter()
|
|
272
|
+
widget_power = shared_memory_service.get_all_widget_power()
|
|
273
|
+
if max_counter >= 999 and cur_counter == 0 and not widget_power:
|
|
274
|
+
max_counter = 1
|
|
275
|
+
idle_counter = max(0, max_counter - cur_counter)
|
|
276
|
+
metrics["task_slots"] = {
|
|
277
|
+
"max": max_counter,
|
|
278
|
+
"cur": cur_counter,
|
|
279
|
+
"idle": idle_counter,
|
|
280
|
+
"usage_percent": _percent(cur_counter, max_counter),
|
|
281
|
+
"widget_power": widget_power
|
|
282
|
+
}
|
|
283
|
+
except:
|
|
284
|
+
pass
|
|
285
|
+
return metrics
|
|
286
|
+
|
|
287
|
+
def deviceInfo():
|
|
288
|
+
mac = get_mac_address()
|
|
289
|
+
mac = "" if mac == None else mac
|
|
290
|
+
cpu_serial = get_cpu_serial()
|
|
291
|
+
cpu_serial = "" if cpu_serial == None else cpu_serial
|
|
292
|
+
hostname = get_hostname()
|
|
293
|
+
G=1024*1024*1024
|
|
294
|
+
cpu_freq = None
|
|
295
|
+
cpu_cur_freq = None
|
|
296
|
+
try:
|
|
297
|
+
freq = psutil.cpu_freq()
|
|
298
|
+
if freq:
|
|
299
|
+
cpu_freq = freq.max / 1000 if freq.max else None
|
|
300
|
+
cpu_cur_freq = freq.current / 1000 if freq.current else None
|
|
301
|
+
except:
|
|
302
|
+
pass
|
|
303
|
+
|
|
304
|
+
virtual_mem = psutil.virtual_memory()
|
|
305
|
+
disk = psutil.disk_usage("/")
|
|
306
|
+
runtime = runtimeInfo()
|
|
307
|
+
data = {
|
|
308
|
+
"cpu": {
|
|
309
|
+
"logical_count" : psutil.cpu_count(),
|
|
310
|
+
"count" : psutil.cpu_count(logical=False),
|
|
311
|
+
"max_freq" : f"{cpu_freq} GHz" if cpu_freq else "None",
|
|
312
|
+
"current_freq" : f"{cpu_cur_freq} GHz" if cpu_cur_freq else "None",
|
|
313
|
+
"percent" : runtime["cpu"].get("percent"),
|
|
314
|
+
"load_avg": runtime["cpu"].get("load_avg")
|
|
315
|
+
},
|
|
316
|
+
"disk": {
|
|
317
|
+
"total": f"{(disk.total / G):.1f} G",
|
|
318
|
+
"used": f"{(disk.used / G):.1f} G",
|
|
319
|
+
"free": f"{(disk.free / G):.1f} G",
|
|
320
|
+
"percent": f"{disk.percent}%"
|
|
321
|
+
},
|
|
322
|
+
"memory": {
|
|
323
|
+
"total": f"{(virtual_mem.total / G):.1f} G",
|
|
324
|
+
"available": f"{(virtual_mem.available / G):.1f} G",
|
|
325
|
+
"used": f"{(virtual_mem.used / G):.1f} G",
|
|
326
|
+
"free": f"{(virtual_mem.free / G):.1f} G",
|
|
327
|
+
"percent": f"{virtual_mem.percent}%"
|
|
328
|
+
},
|
|
329
|
+
"gpu": runtime["gpu"],
|
|
330
|
+
"device_id": generate_unique_id(),
|
|
331
|
+
"host_name": hostname,
|
|
332
|
+
"task_slots": runtime["task_slots"],
|
|
333
|
+
"timestamp": runtime["timestamp"]
|
|
334
|
+
}
|
|
335
|
+
return data
|
|
336
336
|
|
|
337
337
|
def process_is_alive(pid: int) -> bool:
|
|
338
338
|
try:
|
|
@@ -385,6 +385,9 @@ def begin_restart(reason, update_cli=False, simple="https://pypi.python.org/simp
|
|
|
385
385
|
|
|
386
386
|
K1 = "TFRBSTV0UkR3NXhocHc1eDlVdkZaUWsy"
|
|
387
387
|
K2 = "TFVuYlRuZFRQMHpxYmU3TjVJSGw0YlVvdlJNQkR6"
|
|
388
|
+
RK11 = "NjM2OTJhNjIyYTc3MWZlY2ZmMDkxYmM5OGUxMzBjNGE="
|
|
389
|
+
RK22 = "MGUxM2E2MGQ0YjBiMDk3Yzc0NzIwOWNiZjdhM2I3ZjgxZWM3ODk1NTQzOGJmMjc1ZWJiY2QwMzM5ZjY0YmFjNw=="
|
|
390
|
+
RK23 = "aHR0cHM6Ly8xMTg2NDlkOGY5ZDA0MGFhN2M1NWU4ZGE5NWRlYWE0OS5yMi5jbG91ZGZsYXJlc3RvcmFnZS5jb20="
|
|
388
391
|
def _decode_key(encoded_key):
|
|
389
392
|
import base64
|
|
390
393
|
try:
|
|
@@ -415,7 +418,6 @@ def _encode_key(raw_input):
|
|
|
415
418
|
raise TypeError("Input must be str or bytes")
|
|
416
419
|
return encoded.decode('utf-8')
|
|
417
420
|
|
|
418
|
-
|
|
419
421
|
def check_restart():
|
|
420
422
|
restart_file = os.path.join(constant.base_path, "restart")
|
|
421
423
|
if os.path.exists(restart_file) == False:
|
|
@@ -495,4 +497,4 @@ nohup {restart_command} &''')
|
|
|
495
497
|
result = subprocess.run(f"at now + 1 minutes -f {time_task_file} > {ot}", stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
|
496
498
|
print(f"{result.stdout}\n{result.stderr}")
|
|
497
499
|
os.remove(restart_file)
|
|
498
|
-
print("one minute later must be start!")
|
|
500
|
+
print("one minute later must be start!")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|