xref: /openbmc/openbmc-tools/rootfs_size/rootfs_size.py (revision a3db66b3874e5139ad3497681c2bb52859f365ce)
1cf3c1e67SAndrew Jeffery#!/usr/bin/python3
2cf3c1e67SAndrew Jeffery
3cf3c1e67SAndrew Jefferyimport argparse
4*a3db66b3SPatrick Williamsimport os
5d97f2f15SEd Tanousimport shutil
6*a3db66b3SPatrick Williamsimport subprocess
7d97f2f15SEd Tanousimport sys
8*a3db66b3SPatrick Williamsimport tempfile
9*a3db66b3SPatrick Williamsfrom multiprocessing import Pool, cpu_count
10*a3db66b3SPatrick Williamsfrom os.path import getsize
11cf3c1e67SAndrew Jeffery
12cf3c1e67SAndrew Jeffery# Set command line arguments
13cf3c1e67SAndrew Jefferyparser = argparse.ArgumentParser(
14*a3db66b3SPatrick Williams    formatter_class=argparse.ArgumentDefaultsHelpFormatter
15*a3db66b3SPatrick Williams)
16cf3c1e67SAndrew Jeffery
17*a3db66b3SPatrick Williamsparser.add_argument(
18*a3db66b3SPatrick Williams    "-b",
19*a3db66b3SPatrick Williams    "--build_dir",
20cf3c1e67SAndrew Jeffery    dest="BUILD_DIR",
21cf3c1e67SAndrew Jeffery    default="/home/ed/openbmc-openbmc",
22*a3db66b3SPatrick Williams    help="Build directory path.",
23*a3db66b3SPatrick Williams)
24cf3c1e67SAndrew Jeffery
25*a3db66b3SPatrick Williamsparser.add_argument(
26*a3db66b3SPatrick Williams    "-s",
27*a3db66b3SPatrick Williams    "--squashfs_file",
28cf3c1e67SAndrew Jeffery    dest="SQUASHFS_FILE",
29*a3db66b3SPatrick Williams    default="/build/tmp/deploy/images/wolfpass"
30*a3db66b3SPatrick Williams    + "/intel-platforms-wolfpass.squashfs-xz",
31*a3db66b3SPatrick Williams    help="Squashfs file.",
32*a3db66b3SPatrick Williams)
33cf3c1e67SAndrew Jeffery
34*a3db66b3SPatrick Williamsparser.add_argument(
35*a3db66b3SPatrick Williams    "-t",
36*a3db66b3SPatrick Williams    "--threads",
37d97f2f15SEd Tanous    dest="threads",
38d97f2f15SEd Tanous    default=int(cpu_count()),
39d97f2f15SEd Tanous    type=int,
40*a3db66b3SPatrick Williams    help="Number of threads to use (defaults to cpu count)",
41*a3db66b3SPatrick Williams)
42d97f2f15SEd Tanous
43cf3c1e67SAndrew Jefferyargs = parser.parse_args()
44cf3c1e67SAndrew Jeffery
45cf3c1e67SAndrew Jeffery# files below this size wont be attempted
46cf3c1e67SAndrew JefferyFILE_SIZE_LIMIT = 0
47cf3c1e67SAndrew Jeffery
48d97f2f15SEd TanousSQUASHFS = args.SQUASHFS_FILE
49d97f2f15SEd Tanousif not os.path.isabs(args.SQUASHFS_FILE):
50cf3c1e67SAndrew Jeffery    SQUASHFS = args.BUILD_DIR + args.SQUASHFS_FILE
51cf3c1e67SAndrew Jeffery
52cf3c1e67SAndrew Jefferyoriginal_size = getsize(SQUASHFS)
53cf3c1e67SAndrew Jefferyprint("squashfs size: {}".format(original_size))
54cf3c1e67SAndrew Jeffery
55cf3c1e67SAndrew Jefferyresults = []
56cf3c1e67SAndrew Jeffery
57d97f2f15SEd Tanous
58d97f2f15SEd Tanousdef get_unsquash_results(filepath):
59d97f2f15SEd Tanous    with tempfile.TemporaryDirectory() as newsquashfsroot:
60d97f2f15SEd Tanous        input_path = os.path.join(newsquashfsroot, "input")
61*a3db66b3SPatrick Williams        shutil.copytree(
62*a3db66b3SPatrick Williams            squashfsdir,
63*a3db66b3SPatrick Williams            input_path,
64*a3db66b3SPatrick Williams            symlinks=True,
65*a3db66b3SPatrick Williams            ignore_dangling_symlinks=True,
66*a3db66b3SPatrick Williams        )
67d97f2f15SEd Tanous        file_to_remove = os.path.join(input_path, filepath)
68d97f2f15SEd Tanous        try:
69d97f2f15SEd Tanous            os.remove(file_to_remove)
70d97f2f15SEd Tanous        except IsADirectoryError:
71d97f2f15SEd Tanous            shutil.rmtree(file_to_remove)
72d97f2f15SEd Tanous        subprocess.check_output(
73*a3db66b3SPatrick Williams            [
74*a3db66b3SPatrick Williams                "mksquashfs",
75*a3db66b3SPatrick Williams                input_path,
76*a3db66b3SPatrick Williams                newsquashfsroot + "/test",
77*a3db66b3SPatrick Williams                "-comp",
78*a3db66b3SPatrick Williams                "xz",
79*a3db66b3SPatrick Williams                "-processors",
80*a3db66b3SPatrick Williams                "1",
81*a3db66b3SPatrick Williams            ]
82*a3db66b3SPatrick Williams        )
83d97f2f15SEd Tanous
84*a3db66b3SPatrick Williams        return (
85*a3db66b3SPatrick Williams            filepath.replace(squashfsdir, ""),
86*a3db66b3SPatrick Williams            original_size - getsize(newsquashfsroot + "/test"),
87*a3db66b3SPatrick Williams        )
88d97f2f15SEd Tanous
89d97f2f15SEd Tanous
90cf3c1e67SAndrew Jefferywith tempfile.TemporaryDirectory() as tempsquashfsdir:
91cf3c1e67SAndrew Jeffery    print("writing to " + tempsquashfsdir)
92d97f2f15SEd Tanous    squashfsdir = os.path.join(tempsquashfsdir, "squashfs-root")
93d97f2f15SEd Tanous    # squashfsdir = os.path.join("/tmp", "squashfs-root")
94d97f2f15SEd Tanous    command = ["unsquashfs", "-d", squashfsdir, SQUASHFS]
95cf3c1e67SAndrew Jeffery    print(" ".join(command))
96cf3c1e67SAndrew Jeffery    subprocess.check_call(command)
97cf3c1e67SAndrew Jeffery
98cf3c1e67SAndrew Jeffery    files_to_test = []
99cf3c1e67SAndrew Jeffery    for root, dirs, files in os.walk(squashfsdir):
100cf3c1e67SAndrew Jeffery        for name in files + dirs:
101cf3c1e67SAndrew Jeffery            filepath = os.path.join(root, name)
102cf3c1e67SAndrew Jeffery            if not os.path.islink(filepath):
103cf3c1e67SAndrew Jeffery                if getsize(filepath) > FILE_SIZE_LIMIT:
104d97f2f15SEd Tanous                    files_to_test.append(
105*a3db66b3SPatrick Williams                        os.path.relpath(filepath, squashfsdir)
106*a3db66b3SPatrick Williams                    )
107cf3c1e67SAndrew Jeffery
108cf3c1e67SAndrew Jeffery    print("{} files to attempt removing".format(len(files_to_test)))
109cf3c1e67SAndrew Jeffery
110d97f2f15SEd Tanous    print("Using {} threads".format(args.threads))
111d97f2f15SEd Tanous    with Pool(args.threads) as p:
112*a3db66b3SPatrick Williams        for i, res in enumerate(
113*a3db66b3SPatrick Williams            p.imap_unordered(get_unsquash_results, files_to_test)
114*a3db66b3SPatrick Williams        ):
115d97f2f15SEd Tanous            results.append(res)
116*a3db66b3SPatrick Williams            sys.stderr.write(
117*a3db66b3SPatrick Williams                "\rdone {:.1f}%".format(100 * (i / len(files_to_test)))
118*a3db66b3SPatrick Williams            )
119cf3c1e67SAndrew Jeffery
120cf3c1e67SAndrew Jefferyresults.sort(key=lambda x: x[1], reverse=True)
121cf3c1e67SAndrew Jeffery
122*a3db66b3SPatrick Williamswith open("results.txt", "w") as result_file:
123cf3c1e67SAndrew Jeffery    for filepath, size in results:
124cf3c1e67SAndrew Jeffery        result = "{:>10}: {}".format(size, filepath)
125cf3c1e67SAndrew Jeffery        print(result)
126cf3c1e67SAndrew Jeffery        result_file.write(result + "\n")
127