feat(upgrade): implement seamless json to mongodb migration
This commit is contained in:
70
core/scripts/db/migrate_users.py
Normal file
70
core/scripts/db/migrate_users.py
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
||||||
|
from db.database import db
|
||||||
|
|
||||||
|
def migrate():
|
||||||
|
users_json_path = Path("/etc/hysteria/users.json")
|
||||||
|
|
||||||
|
if not users_json_path.exists():
|
||||||
|
print("users.json not found, no migration needed.")
|
||||||
|
return
|
||||||
|
|
||||||
|
if db is None:
|
||||||
|
print("Error: Database connection failed. Cannot perform migration.", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
try:
|
||||||
|
with users_json_path.open('r') as f:
|
||||||
|
users_data = json.load(f)
|
||||||
|
except (json.JSONDecodeError, IOError) as e:
|
||||||
|
print(f"Error reading or parsing users.json: {e}", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
print(f"Found {len(users_data)} users in users.json to migrate.")
|
||||||
|
migrated_count = 0
|
||||||
|
|
||||||
|
for username, data in users_data.items():
|
||||||
|
try:
|
||||||
|
user_doc = {
|
||||||
|
"_id": username.lower(),
|
||||||
|
"password": data.get("password"),
|
||||||
|
"max_download_bytes": data.get("max_download_bytes", 0),
|
||||||
|
"expiration_days": data.get("expiration_days", 0),
|
||||||
|
"account_creation_date": data.get("account_creation_date"),
|
||||||
|
"blocked": data.get("blocked", False),
|
||||||
|
"unlimited_user": data.get("unlimited_user", False),
|
||||||
|
"status": data.get("status", "Offline"),
|
||||||
|
"upload_bytes": data.get("upload_bytes", 0),
|
||||||
|
"download_bytes": data.get("download_bytes", 0),
|
||||||
|
}
|
||||||
|
|
||||||
|
if user_doc["password"] is None:
|
||||||
|
print(f"Warning: User '{username}' has no password, skipping.", file=sys.stderr)
|
||||||
|
continue
|
||||||
|
|
||||||
|
db.collection.update_one(
|
||||||
|
{'_id': user_doc['_id']},
|
||||||
|
{'$set': user_doc},
|
||||||
|
upsert=True
|
||||||
|
)
|
||||||
|
migrated_count += 1
|
||||||
|
print(f" - Migrated user: {username}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error migrating user '{username}': {e}", file=sys.stderr)
|
||||||
|
|
||||||
|
print(f"Migration complete. {migrated_count} users successfully migrated to MongoDB.")
|
||||||
|
|
||||||
|
try:
|
||||||
|
migrated_file_path = users_json_path.with_name("users.json.migrated")
|
||||||
|
users_json_path.rename(migrated_file_path)
|
||||||
|
print(f"Renamed old user file to: {migrated_file_path}")
|
||||||
|
except OSError as e:
|
||||||
|
print(f"Warning: Could not rename users.json: {e}", file=sys.stderr)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
migrate()
|
||||||
127
upgrade.sh
127
upgrade.sh
@ -11,7 +11,7 @@ REPO_URL="https://github.com/ReturnFI/Blitz"
|
|||||||
REPO_BRANCH="beta"
|
REPO_BRANCH="beta"
|
||||||
GEOSITE_URL="https://raw.githubusercontent.com/Chocolate4U/Iran-v2ray-rules/release/geosite.dat"
|
GEOSITE_URL="https://raw.githubusercontent.com/Chocolate4U/Iran-v2ray-rules/release/geosite.dat"
|
||||||
GEOIP_URL="https://raw.githubusercontent.com/Chocolate4U/Iran-v2ray-rules/release/geoip.dat"
|
GEOIP_URL="https://raw.githubusercontent.com/Chocolate4U/Iran-v2ray-rules/release/geoip.dat"
|
||||||
USERS_FILE="$HYSTERIA_INSTALL_DIR/users.json"
|
MIGRATE_SCRIPT_PATH="$HYSTERIA_INSTALL_DIR/core/scripts/db/migrate_users.py"
|
||||||
|
|
||||||
# ========== Color Setup ==========
|
# ========== Color Setup ==========
|
||||||
GREEN=$(tput setaf 2)
|
GREEN=$(tput setaf 2)
|
||||||
@ -25,28 +25,6 @@ success() { echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')] [OK] - ${RESET} $1";
|
|||||||
warn() { echo -e "${YELLOW}[$(date '+%Y-%m-%d %H:%M:%S')] [WARN] - ${RESET} $1"; }
|
warn() { echo -e "${YELLOW}[$(date '+%Y-%m-%d %H:%M:%S')] [WARN] - ${RESET} $1"; }
|
||||||
error() { echo -e "${RED}[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] - ${RESET} $1"; }
|
error() { echo -e "${RED}[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] - ${RESET} $1"; }
|
||||||
|
|
||||||
# ========== Capture Active Services ==========
|
|
||||||
declare -a ACTIVE_SERVICES_BEFORE_UPGRADE=()
|
|
||||||
ALL_SERVICES=(
|
|
||||||
hysteria-caddy.service
|
|
||||||
hysteria-server.service
|
|
||||||
hysteria-auth.service
|
|
||||||
hysteria-scheduler.service
|
|
||||||
hysteria-telegram-bot.service
|
|
||||||
hysteria-normal-sub.service
|
|
||||||
hysteria-caddy-normalsub.service
|
|
||||||
hysteria-webpanel.service
|
|
||||||
hysteria-ip-limit.service
|
|
||||||
)
|
|
||||||
|
|
||||||
info "Checking for active services before upgrade..."
|
|
||||||
for SERVICE in "${ALL_SERVICES[@]}"; do
|
|
||||||
if systemctl is-active --quiet "$SERVICE"; then
|
|
||||||
ACTIVE_SERVICES_BEFORE_UPGRADE+=("$SERVICE")
|
|
||||||
info "Service '$SERVICE' is active and will be restarted."
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# ========== Install MongoDB ==========
|
# ========== Install MongoDB ==========
|
||||||
install_mongodb() {
|
install_mongodb() {
|
||||||
info "Checking for MongoDB..."
|
info "Checking for MongoDB..."
|
||||||
@ -77,8 +55,8 @@ install_mongodb() {
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
apt-get update -qq >/dev/null
|
apt-get update -qq
|
||||||
apt-get install -y mongodb-org >/dev/null
|
apt-get install -y mongodb-org
|
||||||
systemctl start mongod
|
systemctl start mongod
|
||||||
systemctl enable mongod
|
systemctl enable mongod
|
||||||
success "MongoDB installed and started successfully."
|
success "MongoDB installed and started successfully."
|
||||||
@ -87,73 +65,53 @@ install_mongodb() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# ========== Migrate users.json to MongoDB ==========
|
# ========== New Function to Migrate Data ==========
|
||||||
migrate_users_to_mongodb() {
|
migrate_json_to_mongo() {
|
||||||
info "Checking for user data to migrate..."
|
info "Checking for user data migration..."
|
||||||
if [ ! -f "$USERS_FILE" ]; then
|
if [[ -f "$HYSTERIA_INSTALL_DIR/users.json" ]]; then
|
||||||
warn "users.json not found. No data to migrate."
|
info "Found users.json. Proceeding with migration to MongoDB."
|
||||||
return
|
if python3 "$MIGRATE_SCRIPT_PATH"; then
|
||||||
|
success "Data migration completed successfully."
|
||||||
|
else
|
||||||
|
error "Data migration script failed. Please check the output above."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
info "No users.json found. Skipping migration."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
info "Starting user data migration from users.json to MongoDB..."
|
|
||||||
python3 - <<EOF
|
|
||||||
import json
|
|
||||||
import os
|
|
||||||
import pymongo
|
|
||||||
|
|
||||||
users_json_path = "$USERS_FILE"
|
|
||||||
db_name = "blitz_panel"
|
|
||||||
collection_name = "users"
|
|
||||||
|
|
||||||
try:
|
|
||||||
client = pymongo.MongoClient("mongodb://localhost:27017/")
|
|
||||||
db = client[db_name]
|
|
||||||
collection = db[collection_name]
|
|
||||||
client.server_info()
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error connecting to MongoDB: {e}")
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
with open(users_json_path, 'r') as f:
|
|
||||||
users_data = json.load(f)
|
|
||||||
|
|
||||||
migrated_count = 0
|
|
||||||
for username, data in users_data.items():
|
|
||||||
user_doc = {
|
|
||||||
"password": data.get("password"),
|
|
||||||
"max_download_bytes": data.get("max_download_bytes", 0),
|
|
||||||
"expiration_days": data.get("expiration_days", 0),
|
|
||||||
"account_creation_date": data.get("account_creation_date"),
|
|
||||||
"blocked": data.get("blocked", False),
|
|
||||||
"unlimited_user": data.get("unlimited_user", False),
|
|
||||||
"status": data.get("status", "Offline"),
|
|
||||||
"upload_bytes": data.get("upload_bytes", 0),
|
|
||||||
"download_bytes": data.get("download_bytes", 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
user_doc = {k: v for k, v in user_doc.items() if v is not None}
|
# ========== Capture Active Services ==========
|
||||||
|
declare -a ACTIVE_SERVICES_BEFORE_UPGRADE=()
|
||||||
collection.update_one(
|
ALL_SERVICES=(
|
||||||
{"_id": username.lower()},
|
hysteria-caddy.service
|
||||||
{"$set": user_doc},
|
hysteria-server.service
|
||||||
upsert=True
|
hysteria-auth.service
|
||||||
|
hysteria-scheduler.service
|
||||||
|
hysteria-telegram-bot.service
|
||||||
|
hysteria-normal-sub.service
|
||||||
|
hysteria-caddy-normalsub.service
|
||||||
|
hysteria-webpanel.service
|
||||||
|
hysteria-ip-limit.service
|
||||||
)
|
)
|
||||||
migrated_count += 1
|
|
||||||
|
|
||||||
print(f"Successfully migrated {migrated_count} users to MongoDB.")
|
info "Checking for active services before upgrade..."
|
||||||
|
for SERVICE in "${ALL_SERVICES[@]}"; do
|
||||||
|
if systemctl is-active --quiet "$SERVICE"; then
|
||||||
|
ACTIVE_SERVICES_BEFORE_UPGRADE+=("$SERVICE")
|
||||||
|
info "Service '$SERVICE' is active and will be restarted."
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
EOF
|
# ========== Install MongoDB Prerequisite ==========
|
||||||
|
install_mongodb
|
||||||
mv "$USERS_FILE" "${USERS_FILE}.migrated"
|
|
||||||
success "users.json has been migrated and renamed to users.json.migrated."
|
|
||||||
}
|
|
||||||
|
|
||||||
# ========== Install Go and Compile Auth Binary ==========
|
# ========== Install Go and Compile Auth Binary ==========
|
||||||
install_go_and_compile_auth() {
|
install_go_and_compile_auth() {
|
||||||
info "Checking for Go and compiling authentication binary..."
|
info "Checking for Go and compiling authentication binary..."
|
||||||
if ! command -v go &>/dev/null; then
|
if ! command -v go &>/dev/null; then
|
||||||
warn "Go is not installed. Attempting to install..."
|
warn "Go is not installed. Attempting to install..."
|
||||||
apt-get install golang-go -y >/dev/null
|
apt-get install -y golang-go
|
||||||
success "Go installed successfully."
|
success "Go installed successfully."
|
||||||
else
|
else
|
||||||
success "Go is already installed."
|
success "Go is already installed."
|
||||||
@ -249,8 +207,7 @@ chmod 640 "$HYSTERIA_INSTALL_DIR/ca.key" "$HYSTERIA_INSTALL_DIR/ca.crt"
|
|||||||
chown -R hysteria:hysteria "$HYSTERIA_INSTALL_DIR/core/scripts/telegrambot"
|
chown -R hysteria:hysteria "$HYSTERIA_INSTALL_DIR/core/scripts/telegrambot"
|
||||||
chmod +x "$HYSTERIA_INSTALL_DIR/core/scripts/hysteria2/kick.py"
|
chmod +x "$HYSTERIA_INSTALL_DIR/core/scripts/hysteria2/kick.py"
|
||||||
|
|
||||||
# ========== Install Dependencies ==========
|
# ========== Virtual Environment ==========
|
||||||
install_mongodb
|
|
||||||
info "Setting up virtual environment and installing dependencies..."
|
info "Setting up virtual environment and installing dependencies..."
|
||||||
cd "$HYSTERIA_INSTALL_DIR"
|
cd "$HYSTERIA_INSTALL_DIR"
|
||||||
python3 -m venv "$HYSTERIA_VENV_DIR"
|
python3 -m venv "$HYSTERIA_VENV_DIR"
|
||||||
@ -259,8 +216,10 @@ pip install --upgrade pip >/dev/null
|
|||||||
pip install -r requirements.txt >/dev/null
|
pip install -r requirements.txt >/dev/null
|
||||||
success "Python environment ready."
|
success "Python environment ready."
|
||||||
|
|
||||||
# ========== Migrate Data and Compile Go Binary ==========
|
# ========== Data Migration ==========
|
||||||
migrate_users_to_mongodb
|
migrate_json_to_mongo
|
||||||
|
|
||||||
|
# ========== Compile Go Binary ==========
|
||||||
install_go_and_compile_auth
|
install_go_and_compile_auth
|
||||||
|
|
||||||
# ========== Systemd Services ==========
|
# ========== Systemd Services ==========
|
||||||
|
|||||||
Reference in New Issue
Block a user