Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🎨 重构部分代码 #7

Merged
merged 6 commits into from
Mar 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<<<<<<< HEAD
container/.ssl/
container/bmclapi/
container/cache/
container/config/
container/__pycache__/
.vscode/
.lh/
test/
=======
config/config.properties
__pycache__
.venv
>>>>>>> 1821e9a699e53437109088d3d8cf4bb4a1bf9a50
logs
config/config.yaml
bmclapi
bmclapi_dashboard
cache
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ WORKDIR /python-openbmclapi
ADD . .

RUN pip install -r requirements.txt --no-deps
VOLUME /python-openbmclapi/cache
ENV web_port=8080
VOLUME /python-openbmclapi/bmclapi
ENV web_port=8800
EXPOSE $web_port
CMD ["python", "./container/main.py"]
27 changes: 22 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@

🎉 __*新增功能!*__基于 Echart 的 OpenBMCLAPI 仪表盘(Dashboard)。

🎉 __*新增功能!*__基于 loguru 的**日志器**。


</div>

# 简介
Expand Down Expand Up @@ -53,7 +56,7 @@
python ./container/main.py
```

4. 在 `config.properties` 中,填写你的 `cluster.id`(即 `CLUSTER_ID`)和 `cluster.secret`(即 `CLUSTER_SECRET`)。
4. 在 `config.yaml` 中,填写你的 `cluster_id`(即 `CLUSTER_ID`)和 `cluster_secret`(即 `CLUSTER_SECRET`)。

5. 重新启动程序。

Expand All @@ -69,8 +72,8 @@

```sh
docker run -d \
-v ${/data/python-openbmclapi}:/python-openbmclapi/container/cache \
-v ${/path/to/your/config}:/python-openbmclapi/config/config.properties \
-v ${/data/python-openbmclapi}:/python-openbmclapi/bmclapi \
-v ${/path/to/your/config}:/python-openbmclapi/config/config.yaml \
-p ${web.port}:${web.port} \
--restart always \
--name python-openbmclapi \
Expand All @@ -81,9 +84,23 @@

`web.port` - 对外开放的端口。

`/path/to/your/config` - 配置文件(你需要从此仓库中下载 `config/config.properties.example` 并重命名为 `config.properties` 来进行配置)的存放路径。
`/path/to/your/config` - 配置文件(你需要从此仓库中下载 `config/config.yaml.example` 并重命名为 `config.yaml` 来进行配置)的存放路径。

`/data/python-openbmclapi` - `bmclapi` 文件夹(即缓存 `cache` 文件夹)挂载的路径。

# 配置文件

```yaml
byoc: ''
cluster_id: ''
cluster_secret: ''
download_threads: 64
timeout: 30
web_host: ''
web_port: 8800
web_publicport: 8800

`/data/python-openbmclapi` - `cache` 文件夹挂载的路径。
```

# 鸣谢

Expand Down
8 changes: 0 additions & 8 deletions config/config.properties.example

This file was deleted.

8 changes: 8 additions & 0 deletions config/config.yaml.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
byoc: false
cluster_id: ''
cluster_secret: ''
download_threads: 64
timeout: 30
web_host: ''
web_port: 8800
web_publicport: 8800
2 changes: 1 addition & 1 deletion container/bmclapi_dashboard/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta charset="utf-8"/>
<title>OPENBMCLAPI - TTB Network</title>
<title>Python OpenBMCLAPI Dashboard</title>
</head>
<body>
</body>
Expand Down
6 changes: 2 additions & 4 deletions container/bmclapi_dashboard/static/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ const calc_more_bytes = (...values) => {
".container .vcmp-status-bar:hover":"color: #8dcffc;",
".container .vcmp-status-online":"width: 12px;height: 12px;border-radius: 50%;background-color: #0FC6C2;margin: 8px;",
".container .vcmp-status-offline":"width: 12px;height: 12px;border-radius: 50%;background-color: rgba(0, 0, 0, 0.5);margin: 8px;margin-right: 0;",
"h1, h2, h3":"font-family: Microsoft Yahei UI"
}
set_styles(default_styles)
Extendi18nSets("zh_cn", {
Expand Down Expand Up @@ -266,10 +267,7 @@ const calc_more_bytes = (...values) => {
ExtendFlex().append(
ExtendFlex().css("domain", "extend-flex-auto").append(
ExtendElement("span").append(
ExtendElement("h2").text("Python OpenBMCLAPI Dashboard").valueOf(),
ExtendElement("span").text("Built by ").append(
ExtendElement("a").text("TTB Network").setAttr("href", "https://github.com/TTB-Network/python-openbmclapi/").valueOf()
).id("dashboard-geo").valueOf()
ExtendElement("h3").text("Python OpenBMCLAPI Dashboard").valueOf(),
).valueOf(),
).valueOf(),
).css("header-bar").valueOf(),
Expand Down
35 changes: 19 additions & 16 deletions container/cluster.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import asyncio
from dataclasses import dataclass
import glob
import hashlib
import hmac
import io
Expand All @@ -18,6 +17,8 @@
import utils
import stats
import web
from logger import logger
from tqdm import tqdm

PY_VERSION = "1.0.0"
VERSION = "1.9.7"
Expand Down Expand Up @@ -60,7 +61,7 @@ async def fetchToken(self):
Timer.delay(self.fetchToken, delay=float(content['ttl']) / 1000.0 - 600)

except aiohttp.ClientError as e:
print(f"Error fetching token: {e}")
logger.error(f"Error fetching token: {e}.")
async def getToken(self) -> str:
if not self.token:
await self.fetchToken()
Expand Down Expand Up @@ -120,29 +121,30 @@ async def download(self, session: aiohttp.ClientSession):
self.download_bytes.add(-size)
await self.files.put(file)
async def check_file(self):
print("Requesting files...")
logger.info("Requesting filelist...")
filelist = await self.get_file_list()
filesize = sum((file.size for file in filelist))
total = len(filelist)
byte = 0
miss = []
pbar = tqdm(total=total, unit=' file(s)', unit_scale=True)
pbar.set_description("Checking files")
for i, file in enumerate(filelist):
filepath = str(self.dir) + f"/{file.hash[:2]}/{file.hash}"
if not os.path.exists(filepath) or os.path.getsize(filepath) != file.size:
miss.append(file)
...
await asyncio.sleep(0)
byte += file.size
b = utils.calc_more_bytes(byte, filesize)
print(f"<<<flush>>>Check file {i}/{total} ({b[0]}/{b[1]})")
pbar.update(1)
if not miss:
print(f"<<<flush>>>Checked all files!")
logger.info("Checked all files!")
await self.start_service()
return
filelist = miss
filesize = sum((file.size for file in filelist))
total = len(filelist)
print(f"<<<flush>>>Missing files: {total}({utils.calc_bytes(filesize)})")
logger.info(f"Missing files: {total}({utils.calc_bytes(filesize)}).")
for file in filelist:
await self.files.put(file)
self.download_bytes = utils.Progress(5, filesize)
Expand All @@ -154,16 +156,17 @@ async def check_file(self):
"User-Agent": UA,
"Authorization": f"Bearer {await token.getToken()}"
}), )))
pbar = tqdm(total=total, unit=' file(s)', unit_scale=True)
pre = 0
while any([not timer.called for timer in timers]):
b = utils.calc_more_bytes(self.download_bytes.get_cur(), filesize)
bits = self.download_bytes.get_cur_speeds() or [0]
minbit = min(bits)
bit = utils.calc_more_bit(minbit, bits[-1], max(bits))
eta = self.download_bytes.get_eta()
print(f"<<<flush>>>Downloading files... {self.download_files.get_cur()}/{total} {b[0]}/{b[1]}, eta: {utils.format_time(eta if eta != -1 else None)}, total: {utils.format_time(self.download_bytes.get_total())}, Min: {bit[0]}, Cur: {bit[2]}, Max: {bit[1]}, Files: {self.download_files.get_cur_speed()}/s")
pbar.set_description(f"Downloading files | Curent speed: {bit[2]}")
await asyncio.sleep(1)
for timer in timers:
del timer
pbar.update(self.download_files.get_cur() - pre)
pre = self.download_files.get_cur()
await self.start_service()
async def start_service(self):
tokens = await token.getToken()
Expand All @@ -185,11 +188,11 @@ async def enable(self):
if not web.get_ssl() and not (Path(".ssl/cert.pem").exists() and Path(".ssl/key.pem").exists()):
await self.emit("request-cert")
self.cur_counter = stats.Counters()
print("Connected Main Server.")
logger.info("Connected to the Main Server.")
async def message(self, type, data):
if type == "request-cert":
cert = data[1]
print("Requested cert!")
logger.info("Requested cert!")
cert_file = Path(".ssl/cert.pem")
key_file = Path(".ssl/key.pem")
for file in (cert_file, key_file):
Expand All @@ -206,9 +209,9 @@ async def message(self, type, data):
self.keepalive.block()
self.keepalive = Timer.delay(self.keepaliveTimer, (), 5)
if len(data) == 2 and data[1] == True:
print("Checked! Can service")
logger.info("Checked! Starting the service")
return
print("Error:" + data[0]['message'])
logger.error("Error:" + data[0]['message'])
Timer.delay(self.enable)
elif type == "keep-alive":
COUNTER.hit -= self.cur_counter.hit
Expand All @@ -234,7 +237,7 @@ async def get_file_list(self):
"cache": ""
}) as req:
req.raise_for_status()
print("Requested files")
logger.info("Requested filelist.")

parser = avro_io.DatumReader(schema.parse(
'''
Expand Down
81 changes: 29 additions & 52 deletions container/config.py
Original file line number Diff line number Diff line change
@@ -1,62 +1,39 @@
from pathlib import Path
import yaml
from typing import Union

class CFG:
def __init__(self, path: str) -> None:
self.file = Path(path)
self.cfg = {}
if self.file.exists():
self.load()

class Property:
def __init__(self, config: str, exists_ok: bool = True) -> None:
self.file = Path(config)
self.properties = {}
if self.file.exists():
self.parse_file()
self.exists_ok = exists_ok

def parse_file(self):
def load(self):
with open(self.file, "r", encoding="utf-8") as f:
for line in f.readlines():
line = line.strip()
if not line or line.startswith('#'):
continue
key, value = line.split('=', 1)
value = value.strip('"')
self.properties[key] = value
def set(self, key, value):
self.properties[key] = str(value)
self.cfg = yaml.load(f.read(), Loader=yaml.FullLoader)

def get(self, key, default=None):
val = self.properties.get(key, None)
if not self.exists_ok and val is None:
self.set(key, default or "")
self.save()
return val or str(default)
def getBoolean(self, key, def_: bool = False):
val = self.get(key, def_)
return val.lower() in ("true", "1", "t", "yes", "y")
def getInteger(self, key, def_: int = 0):
val = self.get(key, def_)
return int(val) if val.isnumeric() else def_
def __getitem__(self, key):
return self.properties.get(key)
def __setitem__(self, key, value):
self.set(key, value)

def save(self):
sorted_dict = sorted(self.properties.items())
self.file.parent.mkdir(exist_ok=True, parents=True)
with open(self.file, 'w', encoding="utf-8") as file:
for key, value in sorted_dict:
if "\n" in value:
value = f'"{value}"'
file.write(f"{key}={value}\n")
def get(self, key, default_):
value = self.cfg.get(key, default_)
if value is None:
self.write(key, default_)
return value

Config: Property = Property("./config/config.properties", False)
def write(self, key, value):
self.cfg[key] = value
with open(self.file, "w", encoding="utf-8") as f:
yaml.dump(data=self.cfg, stream=f, allow_unicode=True)

CLUSTER_ID = Config.get("cluster.id", None) or ""
CLUSTER_SECRET = Config.get("cluster.secret", None) or ""
MAX_DOWNLOAD = Config.getInteger("download.threads", 64)
PORT = Config.getInteger("web.port", 8800)
PUBLICPORT = Config.getInteger("web.publicport", 8800)
PUBLICHOST = Config.get("web.host", "")
BYOC = False
TIMEOUT = 30
Config: CFG = CFG("./config/config.yaml")

CLUSTER_ID: str = Config.get("cluster_id", "")
CLUSTER_SECRET: str = Config.get("cluster_secret", "")
MAX_DOWNLOAD: int = Config.get("download_threads", 64)
PORT: int = Config.get("web_port", 8800)
PUBLICPORT: int = Config.get("web_publicport", 8800)
PUBLICHOST: int = Config.get("web_host", "")
BYOC: bool = Config.get("byoc", False)
TIMEOUT: int = Config.get("timeout", 30)
MIN_RATE_TIMESTAMP = 1000
MIN_RATE = 500
REQUEST_BUFFER = 1024 * 8
Expand Down
4 changes: 4 additions & 0 deletions container/logger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from loguru import logger
from pathlib import Path

logger.add(Path("./logs/{time}.log"), rotation="3 hours")
5 changes: 3 additions & 2 deletions container/timer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import inspect
import time
import traceback
from logger import logger


class Task:
Expand Down Expand Up @@ -44,15 +45,15 @@ def block(self):
self.blocked = True
async def callback_error(self):
if not self.error:
print(traceback.format_exc())
logger.debug(traceback.format_exc())
return
try:
if inspect.iscoroutinefunction(self.error):
await self.error()
else:
self.error()
except:
print(traceback.format_exc())
logger.debug(traceback.format_exc())
class TimerManager:
def delay(self, target, args = (), delay: float = 0, callback = None):
task = Task(target=target, args=args, delay=delay, back=callback)
Expand Down
Loading
Loading