blob: b33e40f4f9f4f98265ba9df1ac14c3af269015d3 [file] [log] [blame] [edit]
#!/usr/bin/env python3
# Copyright 2023 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Ensure rootdev_base entry have a glob as basename:
rootdev_base contains globs that represent possible hardware paths
of the fixed SSD. They are used to find the fixed SSD to installit to
from an external device, at recovery time for instance.
The basename of these globs should not be a constant (like "nvme0n1"
instead of "nvme*n1").
The linux kernel indices for block devices may not remain constant
depending on the device initialization ordering. If for instance a
removable device is detected before the fixed device, the name of the
fixed device could become nvme1n1 sometimes.
Thus, these paths should identify devices by relatively unchanging
hardware-specific identifiers earlier in the path, while the last
component (a kernel-specific naming detail) should be a glob of some kind.
"""
import argparse
import json
import os
import re
import sys
from typing import List, Optional
def CheckRootDevBase(file_path: str) -> bool:
"""Check the metadata.rootdev_base entries have enough wildcards.
Check the basename of the globs do have wildcard to handle variable
indices given by the linux kernel to block devices accross boots.
Args:
file_path: a json file
Returns:
True if all the rootdevs have a wildcard in their basename.
"""
with open(file_path, "r", encoding="utf-8") as f:
content = f.read()
# Remove all comments from the JSON file, otherwise the compiler
# will not work.
content = re.sub(r"#.*", "", content)
data = json.loads(content)
metadata = data.get("metadata")
if not metadata:
return True
rootdev_base = metadata.get("rootdev_base")
if not rootdev_base:
return True
for disk in rootdev_base.split(" "):
if not re.search(r"[\*?]", os.path.basename(disk)):
print(f"In {file_path}: Basename of {disk} should have a wildcard")
return False
return True
def CheckDiskLayoutJson(file_paths: List[str]) -> bool:
"""Check if a disk_layout.json is being modified.
Args:
file_paths: Files modified in this commit.
Returns:
True when all changes are correct.
"""
DISK_LAYOUT_PATH = "disk_layout.json"
for path in file_paths:
if os.path.basename(path) == DISK_LAYOUT_PATH:
if not CheckRootDevBase(path):
return False
return True
def get_parser():
"""Return an argument parser."""
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("files", nargs="*", help="Files to check.")
return parser
def main(argv: Optional[List[str]] = None) -> Optional[int]:
parser = get_parser()
opts = parser.parse_args(argv)
return 0 if CheckDiskLayoutJson(opts.files) else 1
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))