w22
This commit is contained in:
@@ -4,7 +4,8 @@
|
|||||||
"Bash(.venv\\\\Scripts\\\\python.exe 10_collect_metadata.py --source demo_fotky --limit 3 --dry-run)",
|
"Bash(.venv\\\\Scripts\\\\python.exe 10_collect_metadata.py --source demo_fotky --limit 3 --dry-run)",
|
||||||
"Bash(PGPASSWORD=\"\" psql -h 192.168.1.76 -p 5432 -U vladimir.buzalka -d fotky_buzalkovi -c \"\\\\dt\")",
|
"Bash(PGPASSWORD=\"\" psql -h 192.168.1.76 -p 5432 -U vladimir.buzalka -d fotky_buzalkovi -c \"\\\\dt\")",
|
||||||
"PowerShell($env:PGPASSWORD = \"\"; psql -h 192.168.1.76 -p 5432 -U vladimir.buzalka -d fotky_buzalkovi -c \"\\\\dt\" 2>&1)",
|
"PowerShell($env:PGPASSWORD = \"\"; psql -h 192.168.1.76 -p 5432 -U vladimir.buzalka -d fotky_buzalkovi -c \"\\\\dt\" 2>&1)",
|
||||||
"PowerShell(python -c \"import psycopg2; conn = psycopg2.connect\\(host='192.168.1.76', port=5432, user='vladimir.buzalka', password='', dbname='fotky_buzalkovi'\\); cur = conn.cursor\\(\\); cur.execute\\(\\\\\"SELECT table_name FROM information_schema.tables WHERE table_schema='public' ORDER BY table_name\\\\\"\\); rows = cur.fetchall\\(\\); print\\([r[0] for r in rows]\\); conn.close\\(\\)\" 2>&1)"
|
"PowerShell(python -c \"import psycopg2; conn = psycopg2.connect\\(host='192.168.1.76', port=5432, user='vladimir.buzalka', password='', dbname='fotky_buzalkovi'\\); cur = conn.cursor\\(\\); cur.execute\\(\\\\\"SELECT table_name FROM information_schema.tables WHERE table_schema='public' ORDER BY table_name\\\\\"\\); rows = cur.fetchall\\(\\); print\\([r[0] for r in rows]\\); conn.close\\(\\)\" 2>&1)",
|
||||||
|
"PowerShell(Rename-Item -Path \"C:\\\\Users\\\\vlado\\\\PycharmProjects\\\\fotkyBuzalkovi\\\\00 PictureCollector\\\\collect_pictures.py\" -NewName \"collect_pictures_linux.py\")"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+31
-1
@@ -11,6 +11,21 @@ Tabulky:
|
|||||||
|
|
||||||
Bezpečné pro opakované spuštění (pokračuje tam, kde skončilo).
|
Bezpečné pro opakované spuštění (pokračuje tam, kde skončilo).
|
||||||
Bezpečné pro souběžný běh na více strojích (ON CONFLICT v SQL).
|
Bezpečné pro souběžný běh na více strojích (ON CONFLICT v SQL).
|
||||||
|
|
||||||
|
Předpoklad pro hostname a ukládání cest do DB:
|
||||||
|
Skript běží na dvou Unraid serverech s různým přístupem k zálohovacímu share:
|
||||||
|
|
||||||
|
hostname = Tower1 (druhý Unraid server — vlastník zálohy):
|
||||||
|
Zálohovací share je nativní: /mnt/user/ZalohaVsechObrazku/
|
||||||
|
Cesta se ukládá do DB beze změny — je již v kanonickém tvaru.
|
||||||
|
|
||||||
|
hostname = tower (první Unraid server — zálohu zapisuje přes remote mount):
|
||||||
|
Zálohovací share je mountován jako: /mnt/remotes/TOWER1.LAN_ZalohaVsechObrazku/
|
||||||
|
Fyzické kopírování probíhá přes tento remote mount, ale do DB se ukládá
|
||||||
|
vždy nativní Tower1 cesta: /mnt/user/ZalohaVsechObrazku/...
|
||||||
|
(PATH_NORMALIZE_MAP zajistí přepis prefixu před INSERTem).
|
||||||
|
|
||||||
|
Tím jsou cesty v DB jednotné bez ohledu na to, který server zálohu pořídil.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@@ -45,6 +60,12 @@ ZALOHA_DIR_MAP = {
|
|||||||
}
|
}
|
||||||
ZALOHA_DIR_DEFAULT = Path("/mnt/remotes/TOWER1.LAN_ZalohaVsechObrazku")
|
ZALOHA_DIR_DEFAULT = Path("/mnt/remotes/TOWER1.LAN_ZalohaVsechObrazku")
|
||||||
|
|
||||||
|
# Normalizace cesty pro DB — vždy ukládáme nativní Tower1 cestu,
|
||||||
|
# bez ohledu na to, přes jaký mount skript soubor fyzicky zapsal.
|
||||||
|
PATH_NORMALIZE_MAP = {
|
||||||
|
"/mnt/remotes/TOWER1.LAN_ZalohaVsechObrazku": "/mnt/user/ZalohaVsechObrazku",
|
||||||
|
}
|
||||||
|
|
||||||
EXCLUDED_DIR_NAMES_LOWER = {"zalohavsechobrazku", "zálohavsechobrázku", "zálohavsechobrazku"}
|
EXCLUDED_DIR_NAMES_LOWER = {"zalohavsechobrazku", "zálohavsechobrázku", "zálohavsechobrazku"}
|
||||||
|
|
||||||
BATCH_SIZE = 500
|
BATCH_SIZE = 500
|
||||||
@@ -119,6 +140,15 @@ def compute_blake3(path: Path, chunk: int = 1 << 20) -> str:
|
|||||||
return h.hexdigest()
|
return h.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_path_for_db(path: Path) -> str:
|
||||||
|
"""Převede fyzickou cestu zálohy na nativní Tower1 cestu pro uložení do DB."""
|
||||||
|
s = str(path)
|
||||||
|
for remote, native in PATH_NORMALIZE_MAP.items():
|
||||||
|
if s.startswith(remote):
|
||||||
|
return native + s[len(remote):]
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
def dest_path_for(source: Path, hostname: str) -> Path:
|
def dest_path_for(source: Path, hostname: str) -> Path:
|
||||||
try:
|
try:
|
||||||
relative = source.relative_to(SOURCE_BASE)
|
relative = source.relative_to(SOURCE_BASE)
|
||||||
@@ -237,7 +267,7 @@ def process(conn, hostname):
|
|||||||
t_copy = time.perf_counter()
|
t_copy = time.perf_counter()
|
||||||
|
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
cur.execute(SQL_INSERT_ZALOHA, (hash_val, str(dest), source.name, velikost))
|
cur.execute(SQL_INSERT_ZALOHA, (hash_val, normalize_path_for_db(dest), source.name, velikost))
|
||||||
row = cur.fetchone()
|
row = cur.fetchone()
|
||||||
if row:
|
if row:
|
||||||
zaloha_id = row[0]
|
zaloha_id = row[0]
|
||||||
@@ -10,6 +10,14 @@ Příklad: \\Tower1\ZalohaVsechObrazku\JMENO-PC\D\Foto\2023\img.jpg
|
|||||||
|
|
||||||
Bezpečné pro opakované spuštění (pokračuje tam kde skončilo).
|
Bezpečné pro opakované spuštění (pokračuje tam kde skončilo).
|
||||||
Bezpečné pro souběžný běh na více strojích (ON CONFLICT v SQL).
|
Bezpečné pro souběžný běh na více strojích (ON CONFLICT v SQL).
|
||||||
|
|
||||||
|
Předpoklad pro ukládání cest do DB:
|
||||||
|
Ať už je hostname Windows stroje jakýkoliv, Tower1 (druhý Unraid server)
|
||||||
|
je vždy dostupný jako \\Tower1\ZalohaVsechObrazku\...
|
||||||
|
Fyzické kopírování probíhá přes tuto UNC cestu, ale do DB se ukládá
|
||||||
|
vždy nativní Linux cesta Tower1, tj. /mnt/user/ZalohaVsechObrazku/...
|
||||||
|
(\\Tower1 → /mnt/user, zpětná lomítka → dopředná lomítka).
|
||||||
|
Tím jsou cesty v DB jednotné bez ohledu na to, který stroj zálohu pořídil.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@@ -39,6 +47,19 @@ DB_CONFIG = {
|
|||||||
|
|
||||||
ZALOHA_DIR = Path(r"\\Tower1\ZalohaVsechObrazku")
|
ZALOHA_DIR = Path(r"\\Tower1\ZalohaVsechObrazku")
|
||||||
|
|
||||||
|
# Normalizace cesty pro DB — Windows UNC cestu převedeme na nativní Tower1 Linux cestu.
|
||||||
|
# \\Tower1\ZalohaVsechObrazku\... → /mnt/user/ZalohaVsechObrazku/...
|
||||||
|
WINDOWS_UNC_PREFIX = r"\\Tower1"
|
||||||
|
LINUX_NATIVE_PREFIX = "/mnt/user"
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_path_for_db(path: Path) -> str:
|
||||||
|
"""Převede \\Tower1\ZalohaVsechObrazku\... na /mnt/user/ZalohaVsechObrazku/..."""
|
||||||
|
s = str(path)
|
||||||
|
if s.startswith(WINDOWS_UNC_PREFIX):
|
||||||
|
return LINUX_NATIVE_PREFIX + s[len(WINDOWS_UNC_PREFIX):].replace("\\", "/")
|
||||||
|
return s
|
||||||
|
|
||||||
JPEG_EXTENSIONS = {".jpg", ".jpeg"}
|
JPEG_EXTENSIONS = {".jpg", ".jpeg"}
|
||||||
|
|
||||||
EXCLUDED_DIR_NAMES_LOWER = {
|
EXCLUDED_DIR_NAMES_LOWER = {
|
||||||
@@ -244,7 +265,7 @@ def process(conn, hostname, drives):
|
|||||||
t_copy = time.perf_counter()
|
t_copy = time.perf_counter()
|
||||||
|
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
cur.execute(SQL_INSERT_ZALOHA, (hash_val, str(dest), source.name, velikost))
|
cur.execute(SQL_INSERT_ZALOHA, (hash_val, normalize_path_for_db(dest), source.name, velikost))
|
||||||
row = cur.fetchone()
|
row = cur.fetchone()
|
||||||
if row:
|
if row:
|
||||||
zaloha_id = row[0]
|
zaloha_id = row[0]
|
||||||
|
|||||||
@@ -347,7 +347,13 @@ def iter_photos(source: Path):
|
|||||||
dirs[:] = [d for d in dirs if not d.startswith(".")]
|
dirs[:] = [d for d in dirs if not d.startswith(".")]
|
||||||
for fname in files:
|
for fname in files:
|
||||||
if Path(fname).suffix.lower() in SUPPORTED_EXTENSIONS:
|
if Path(fname).suffix.lower() in SUPPORTED_EXTENSIONS:
|
||||||
yield Path(root) / fname
|
p = Path(root) / fname
|
||||||
|
# Přeskočit symlinky které vedou mimo share (WinError 3 - \\mnt\user\...)
|
||||||
|
try:
|
||||||
|
p.stat()
|
||||||
|
except OSError:
|
||||||
|
continue
|
||||||
|
yield p
|
||||||
|
|
||||||
|
|
||||||
def count_photos(source: Path) -> int:
|
def count_photos(source: Path) -> int:
|
||||||
|
|||||||
@@ -63,8 +63,14 @@ DB_CONFIG = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Překlad: Linux NFS cesta (jak je uložena v DB) → Windows UNC
|
# Překlad: Linux NFS cesta (jak je uložena v DB) → Windows UNC
|
||||||
LINUX_PREFIX = "/mnt/remotes/TOWER1.LAN_ZalohaVsechObrazku"
|
# Záznamy v DB mohou mít různé Linux prefixy podle toho, odkud byl scan spuštěn.
|
||||||
WINDOWS_UNC = "//Tower1/ZalohaVsechObrazku"
|
PATH_MAPPINGS = [
|
||||||
|
("/mnt/remotes/TOWER1.LAN_ZalohaVsechObrazku", "//Tower1/ZalohaVsechObrazku"),
|
||||||
|
("/mnt/user/ZalohaVsechObrazku", "//Tower1/ZalohaVsechObrazku"),
|
||||||
|
]
|
||||||
|
# Zpětná kompatibilita
|
||||||
|
LINUX_PREFIX = PATH_MAPPINGS[0][0]
|
||||||
|
WINDOWS_UNC = PATH_MAPPINGS[0][1]
|
||||||
|
|
||||||
SUPPORTED_EXTENSIONS = {".jpg", ".jpeg", ".png", ".heic", ".tiff", ".tif", ".webp", ".bmp"}
|
SUPPORTED_EXTENSIONS = {".jpg", ".jpeg", ".png", ".heic", ".tiff", ".tif", ".webp", ".bmp"}
|
||||||
|
|
||||||
@@ -93,10 +99,11 @@ MIME_MAP = {
|
|||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
def linux_to_windows(linux_path: str) -> Path:
|
def linux_to_windows(linux_path: str) -> Path:
|
||||||
"""Převede /mnt/remotes/TOWER1.LAN_ZalohaVsechObrazku/... na //Tower1/ZalohaVsechObrazku/..."""
|
"""Převede Linux NFS cestu na Windows UNC podle tabulky PATH_MAPPINGS."""
|
||||||
if linux_path.startswith(LINUX_PREFIX):
|
for linux_prefix, windows_unc in PATH_MAPPINGS:
|
||||||
rel = linux_path[len(LINUX_PREFIX):] # začíná /
|
if linux_path.startswith(linux_prefix):
|
||||||
return Path(WINDOWS_UNC + rel)
|
rel = linux_path[len(linux_prefix):] # začíná /
|
||||||
|
return Path(windows_unc + rel)
|
||||||
return Path(linux_path)
|
return Path(linux_path)
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user