mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-09-28 19:06:52 +03:00
own every directory level created for a recording segment
This commit is contained in:
@@ -929,7 +929,12 @@ class RecordingMaintainer(threading.Thread):
|
|||||||
)
|
)
|
||||||
|
|
||||||
os.makedirs(directory, exist_ok=True)
|
os.makedirs(directory, exist_ok=True)
|
||||||
chown_to_runtime(directory)
|
# makedirs creates the date and hour levels too; own every level so
|
||||||
|
# the host user can prune old recordings
|
||||||
|
level = directory
|
||||||
|
while level != RECORD_DIR:
|
||||||
|
chown_to_runtime(level)
|
||||||
|
level = os.path.dirname(level)
|
||||||
|
|
||||||
# file will be in utc due to path_time being in utc
|
# file will be in utc due to path_time being in utc
|
||||||
file_name = f"{path_time.strftime('%M.%S.mp4')}"
|
file_name = f"{path_time.strftime('%M.%S.mp4')}"
|
||||||
|
|||||||
@@ -442,6 +442,71 @@ class TestSegmentPathTime(unittest.IsolatedAsyncioTestCase):
|
|||||||
self.assertTrue(paths[1].endswith("30.23.mp4"), paths[1])
|
self.assertTrue(paths[1].endswith("30.23.mp4"), paths[1])
|
||||||
|
|
||||||
|
|
||||||
|
class TestMoveSegmentOwnership(unittest.IsolatedAsyncioTestCase):
|
||||||
|
"""Every directory level makedirs creates must be handed to the runtime user."""
|
||||||
|
|
||||||
|
def _build_maintainer(self) -> RecordingMaintainer:
|
||||||
|
camera_config = MagicMock()
|
||||||
|
camera_config.record.enabled = True
|
||||||
|
camera_config.record.continuous.days = 1
|
||||||
|
camera_config.record.motion.days = 0
|
||||||
|
|
||||||
|
config = MagicMock()
|
||||||
|
config.cameras = {"test_cam": camera_config}
|
||||||
|
|
||||||
|
maintainer = RecordingMaintainer.__new__(RecordingMaintainer)
|
||||||
|
maintainer.config = config
|
||||||
|
maintainer.end_time_cache = {}
|
||||||
|
maintainer.object_recordings_info = defaultdict(list)
|
||||||
|
maintainer.audio_recordings_info = defaultdict(list)
|
||||||
|
maintainer.recordings_publisher = MagicMock()
|
||||||
|
maintainer.last_segment_end = {("test_cam", "main"): 0.0}
|
||||||
|
return maintainer
|
||||||
|
|
||||||
|
async def test_move_segment_chowns_all_created_levels(self):
|
||||||
|
maintainer = self._build_maintainer()
|
||||||
|
maintainer.config.ffmpeg.ffmpeg_path = "ffmpeg"
|
||||||
|
|
||||||
|
start_time = datetime.datetime(2026, 6, 10, 14, 30, 22, tzinfo=datetime.UTC)
|
||||||
|
|
||||||
|
proc = MagicMock()
|
||||||
|
proc.returncode = 0
|
||||||
|
proc.wait = AsyncMock(return_value=0)
|
||||||
|
chown = MagicMock()
|
||||||
|
|
||||||
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
|
record_dir = os.path.join(tmpdir, "recordings")
|
||||||
|
cache_path = os.path.join(tmpdir, "test_cam@20260610143022+0000.mp4")
|
||||||
|
with open(cache_path, "wb") as f:
|
||||||
|
f.write(b"\x00" * 16)
|
||||||
|
|
||||||
|
with (
|
||||||
|
patch("frigate.record.maintainer.RECORD_DIR", record_dir),
|
||||||
|
patch(
|
||||||
|
"frigate.record.maintainer.asyncio.create_subprocess_exec",
|
||||||
|
AsyncMock(return_value=proc),
|
||||||
|
),
|
||||||
|
patch("frigate.record.maintainer.chown_to_runtime", chown),
|
||||||
|
):
|
||||||
|
result = await maintainer.move_segment(
|
||||||
|
"test_cam",
|
||||||
|
"main",
|
||||||
|
start_time,
|
||||||
|
start_time + datetime.timedelta(seconds=10),
|
||||||
|
10.0,
|
||||||
|
cache_path,
|
||||||
|
SegmentInfo(0, 0, 0, 0),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertIsNotNone(result)
|
||||||
|
camera_dir = os.path.join(record_dir, "2026-06-10", "14", "test_cam")
|
||||||
|
hour_dir = os.path.dirname(camera_dir)
|
||||||
|
date_dir = os.path.dirname(hour_dir)
|
||||||
|
file_path = os.path.join(camera_dir, "30.22.mp4")
|
||||||
|
chowned = [call.args[0] for call in chown.call_args_list]
|
||||||
|
self.assertEqual(chowned, [camera_dir, hour_dir, date_dir, file_path])
|
||||||
|
|
||||||
|
|
||||||
class TestSegmentStartChaining(unittest.IsolatedAsyncioTestCase):
|
class TestSegmentStartChaining(unittest.IsolatedAsyncioTestCase):
|
||||||
"""Contiguous segments must chain start times across filename truncation.
|
"""Contiguous segments must chain start times across filename truncation.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user