95 lines
4.4 KiB
Python
95 lines
4.4 KiB
Python
|
|
"""Fresh-install initialization and non-destructive version upgrades."""
|
||
|
|
import json
|
||
|
|
import os
|
||
|
|
import shutil
|
||
|
|
import sqlite3
|
||
|
|
from datetime import datetime
|
||
|
|
from monitor_runtime.paths import data, resource, atomic_json
|
||
|
|
|
||
|
|
def prepare_files():
|
||
|
|
data('').mkdir(parents=True, exist_ok=True)
|
||
|
|
for name in ('.runtime', 'log', 'backups', 'static/upload/weight', 'static/upload/audio',
|
||
|
|
'static/storage', '.runtime/zlm', '.runtime/ultralytics/Ultralytics', '.runtime/matplotlib'):
|
||
|
|
data(name).mkdir(parents=True, exist_ok=True)
|
||
|
|
for target, source in (('config.json', 'deploy/windows/default-config.json'),
|
||
|
|
('settings.json', 'deploy/windows/default-settings.json'),
|
||
|
|
('zlm-template.ini', 'deploy/windows/zlm-template.ini')):
|
||
|
|
if not data(target).exists():
|
||
|
|
shutil.copyfile(resource(source), data(target))
|
||
|
|
os.environ['YOLO_CONFIG_DIR'] = str(data('.runtime/ultralytics'))
|
||
|
|
os.environ['MPLCONFIGDIR'] = str(data('.runtime/matplotlib'))
|
||
|
|
os.environ['YOLO_OFFLINE'] = 'true'
|
||
|
|
os.environ['YOLO_AUTOINSTALL'] = 'false'
|
||
|
|
os.environ['CI'] = 'true'
|
||
|
|
|
||
|
|
def initialize_database():
|
||
|
|
import django
|
||
|
|
os.environ['DJANGO_SETTINGS_MODULE'] = 'framework.settings'
|
||
|
|
os.environ['MONITOR_SERVICE_MODE'] = 'disabled'
|
||
|
|
os.environ['MONITOR_BOOTSTRAP_SERVICES'] = 'false'
|
||
|
|
django.setup()
|
||
|
|
from django.core.management import call_command
|
||
|
|
from django.db import connection
|
||
|
|
from django.db.migrations.executor import MigrationExecutor
|
||
|
|
executor = MigrationExecutor(connection)
|
||
|
|
plan = executor.migration_plan(executor.loader.graph.leaf_nodes())
|
||
|
|
db = data('monitor.sqlite3')
|
||
|
|
if plan and db.exists() and db.stat().st_size:
|
||
|
|
backup = data('backups') / datetime.now().strftime('%Y%m%d-%H%M%S-%f')
|
||
|
|
backup.mkdir()
|
||
|
|
with sqlite3.connect(str(db)) as src, sqlite3.connect(str(backup / db.name)) as dst:
|
||
|
|
src.backup(dst)
|
||
|
|
for name in ('config.json', 'settings.json', 'network.json', '.runtime-secrets.json', 'license.json'):
|
||
|
|
if data(name).exists():
|
||
|
|
shutil.copyfile(data(name), backup / name)
|
||
|
|
call_command('migrate', interactive=False, verbosity=0)
|
||
|
|
from django.contrib.auth.models import Group
|
||
|
|
for role in ('system_admin', 'algorithm_admin', 'operator', 'viewer'):
|
||
|
|
Group.objects.get_or_create(name=role)
|
||
|
|
from app.utils.Credentials import migrate_existing_credentials
|
||
|
|
migrate_existing_credentials()
|
||
|
|
|
||
|
|
def has_admin():
|
||
|
|
from django.contrib.auth import get_user_model
|
||
|
|
marker = data('.runtime/initialized.json')
|
||
|
|
if marker.exists():
|
||
|
|
return True
|
||
|
|
exists = get_user_model().objects.filter(is_superuser=True).exists()
|
||
|
|
if exists:
|
||
|
|
atomic_json(marker, {'schema_version': 1, 'initialized': True})
|
||
|
|
return exists
|
||
|
|
|
||
|
|
def local_addresses():
|
||
|
|
import socket
|
||
|
|
import psutil
|
||
|
|
return sorted({a.address for values in psutil.net_if_addrs().values() for a in values
|
||
|
|
if a.family == socket.AF_INET and not a.address.startswith(('127.', '169.254.'))
|
||
|
|
and a.address != '0.0.0.0'})
|
||
|
|
|
||
|
|
def finish_setup(username, password, address):
|
||
|
|
from django.contrib.auth import get_user_model
|
||
|
|
from django.contrib.auth.password_validation import validate_password
|
||
|
|
from django.db import transaction
|
||
|
|
from monitor_runtime.licensing import require_license
|
||
|
|
require_license()
|
||
|
|
if address not in local_addresses():
|
||
|
|
raise ValueError('请选择本机有效的局域网 IPv4 地址')
|
||
|
|
if len(password) < 12:
|
||
|
|
raise ValueError('管理员密码至少 12 位')
|
||
|
|
username = username.strip()
|
||
|
|
if not username or len(username) > 150:
|
||
|
|
raise ValueError('管理员用户名无效')
|
||
|
|
user = get_user_model()(username=username)
|
||
|
|
validate_password(password, user)
|
||
|
|
with transaction.atomic():
|
||
|
|
if has_admin():
|
||
|
|
raise ValueError('初始化已完成')
|
||
|
|
cfg = json.loads(data('config.json').read_text(encoding='utf-8'))
|
||
|
|
cfg['host'] = address
|
||
|
|
cfg.setdefault('sipServer', {})['sipServerIp'] = address
|
||
|
|
atomic_json(data('config.json'), cfg)
|
||
|
|
atomic_json(data('network.json'), {'allowed_hosts': [address], 'address': address})
|
||
|
|
get_user_model().objects.create_superuser(username=username, password=password)
|
||
|
|
transaction.on_commit(lambda: atomic_json(data('.runtime/initialized.json'),
|
||
|
|
{'schema_version': 1, 'initialized': True}))
|