|
1 | 1 | #!/usr/bin/env python3 |
2 | | -# Auto-generated single-file MachineState (2025-10-20 14:37:15) |
| 2 | +# Auto-generated single-file MachineState (2025-10-30 13:22:30) |
3 | 3 | # Do not edit manually; edit sources and re-run build_single_py.py |
4 | 4 |
|
5 | 5 |
|
@@ -1571,24 +1571,82 @@ def __init__(self, extended=False, anonymous=False): |
1571 | 1571 |
|
1572 | 1572 |
|
1573 | 1573 | ################################################################################ |
1574 | | -# Infos about CGroups |
| 1574 | +# Helper: detect cgroup v2 and compute base path |
1575 | 1575 | ################################################################################ |
1576 | | -class CgroupInfo(InfoGroup): |
1577 | | - def __init__(self, extended=False, anonymous=False): |
1578 | | - super(CgroupInfo, self).__init__(name="Cgroups", extended=extended, anonymous=anonymous) |
| 1576 | +def _v2_path(): |
| 1577 | + """ |
| 1578 | + Return (is_v2, base_path) for the current process. |
| 1579 | + For v2, /proc/self/cgroup has a unified line like '0::/system.slice/...'. |
| 1580 | + """ |
| 1581 | + try: |
| 1582 | + with open("/proc/self/cgroup", "r", encoding="utf-8", errors="ignore") as f: |
| 1583 | + lines = f.read().splitlines() |
| 1584 | + except Exception: |
| 1585 | + return False, "/sys/fs/cgroup" |
| 1586 | + |
| 1587 | + rel = "/" |
| 1588 | + is_v2 = False |
| 1589 | + for line in lines: |
| 1590 | + parts = line.split(":", 2) |
| 1591 | + # unified v2 line: controllers field empty, OR hierarchy id "0" |
| 1592 | + if len(parts) == 3 and (parts[1] == "" or parts[0] == "0"): |
| 1593 | + is_v2 = True |
| 1594 | + rel = parts[2] |
| 1595 | + break |
| 1596 | + base = pjoin("/sys/fs/cgroup", rel.strip("/")) if rel else "/sys/fs/cgroup" |
| 1597 | + return is_v2, base |
| 1598 | + |
| 1599 | + |
| 1600 | +################################################################################ |
| 1601 | +# v1: keep your original logic (renamed to CgroupV1Info) |
| 1602 | +################################################################################ |
| 1603 | +class CgroupV1Info: |
| 1604 | + """Registrar for cgroup v1 cpuset info (your original logic).""" |
| 1605 | + @staticmethod |
| 1606 | + def register(into: InfoGroup, extended: bool): |
1579 | 1607 | csetmat = re.compile(r"\d+\:cpuset\:([/\w\d\-\._]*)") |
1580 | 1608 | cset = process_file(("/proc/self/cgroup", csetmat)) |
1581 | | - if cset is not None: |
1582 | | - base = pjoin("/sys/fs/cgroup/cpuset", cset.strip("/")) |
1583 | | - self.addf("CPUs", pjoin(base, "cpuset.cpus"), r"(.+)", tointlist) |
1584 | | - self.addf("Mems", pjoin(base, "cpuset.mems"), r"(.+)", tointlist) |
1585 | | - self.required("CPUs", "Mems") |
1586 | | - if extended: |
1587 | | - names = ["CPUs.effective", "Mems.effective"] |
1588 | | - files = ["cpuset.effective_cpus", "cpuset.effective_mems"] |
1589 | | - for key, fname in zip(names, files): |
1590 | | - self.addf(key, pjoin(base, fname), r"(.+)", tointlist) |
1591 | | - self.required(key) |
| 1609 | + if not cset: |
| 1610 | + return |
| 1611 | + base = pjoin("/sys/fs/cgroup/cpuset", cset.strip("/")) |
| 1612 | + into.addf("CPUs", pjoin(base, "cpuset.cpus"), r"(.+)", tointlist) |
| 1613 | + into.addf("Mems", pjoin(base, "cpuset.mems"), r"(.+)", tointlist) |
| 1614 | + into.required("CPUs", "Mems") |
| 1615 | + if extended: |
| 1616 | + into.addf("CPUs.effective", pjoin(base, "cpuset.effective_cpus"), r"(.+)", tointlist) |
| 1617 | + into.addf("Mems.effective", pjoin(base, "cpuset.effective_mems"), r"(.+)", tointlist) |
| 1618 | + into.required("CPUs.effective", "Mems.effective") |
| 1619 | + |
| 1620 | + |
| 1621 | +################################################################################ |
| 1622 | +# v2: unified hierarchy (correct filenames) |
| 1623 | +################################################################################ |
| 1624 | +class CgroupV2Info: |
| 1625 | + @staticmethod |
| 1626 | + def register(into: InfoGroup, extended: bool): |
| 1627 | + _, base = _v2_path() |
| 1628 | + # Primary = effective (v2 leaf cpus/mems can be empty otherwise) |
| 1629 | + into.addf("CPUs", pjoin(base, "cpuset.cpus.effective"), r"(.+)", tointlist) |
| 1630 | + into.addf("Mems", pjoin(base, "cpuset.mems.effective"), r"(.+)", tointlist) |
| 1631 | + into.required("CPUs", "Mems") |
| 1632 | + if extended: |
| 1633 | + # expose the same files under explicit names too (optional) |
| 1634 | + into.addf("CPUs.effective", pjoin(base, "cpuset.cpus.effective"), r"(.+)", tointlist) |
| 1635 | + into.addf("Mems.effective", pjoin(base, "cpuset.mems.effective"), r"(.+)", tointlist) |
| 1636 | + # no extra required() needed |
| 1637 | + |
| 1638 | + |
| 1639 | +################################################################################ |
| 1640 | +# Public dispatcher: keeps external API the same |
| 1641 | +################################################################################ |
| 1642 | +class CgroupInfo(InfoGroup): |
| 1643 | + def __init__(self, extended: bool = False, anonymous: bool = False): |
| 1644 | + super().__init__(name="Cgroups", extended=extended, anonymous=anonymous) |
| 1645 | + is_v2, _ = _v2_path() |
| 1646 | + if is_v2: |
| 1647 | + CgroupV2Info.register(self, extended) |
| 1648 | + else: |
| 1649 | + CgroupV1Info.register(self, extended) |
1592 | 1650 |
|
1593 | 1651 |
|
1594 | 1652 | ################################################################################ |
@@ -3851,9 +3909,9 @@ def read_cli(cliargs): |
3851 | 3909 | # Check if compare file exists and readable |
3852 | 3910 | if pargs["compare"] is not None: |
3853 | 3911 | if not pexists(pargs["compare"]): |
3854 | | - raise ValueError("State file '{}' does not exist".format(pargs["json"])) |
| 3912 | + raise ValueError("State file '{}' does not exist".format(pargs["compare"])) |
3855 | 3913 | if not os.access(pargs["compare"], os.R_OK): |
3856 | | - raise ValueError("State file '{}' is not readable".format(pargs["json"])) |
| 3914 | + raise ValueError("State file '{}' is not readable".format(pargs["compare"])) |
3857 | 3915 | # Check if configuration file exists and is readable |
3858 | 3916 | if pargs["configfile"] is not None: |
3859 | 3917 | if not pexists(pargs["configfile"]): |
@@ -4089,10 +4147,6 @@ def main(): |
4089 | 4147 | print("[probe] OSError while probing:", e) |
4090 | 4148 | traceback.print_exc() |
4091 | 4149 | sys.exit(1) |
4092 | | - # Generate subclasses of MachineState |
4093 | | - mstate.generate() |
4094 | | - # Update the current state |
4095 | | - mstate.update() |
4096 | 4150 |
|
4097 | 4151 | # Compare current state to a saved file |
4098 | 4152 | if cliargs["compare"] is not None: |
|
0 commit comments