PNG  IHDR* pHYs+ IDATx]n#; cdLb Ǚ[at¤_:uP}>!Usă cag޿ ֵNu`ݼTâabO7uL&y^wFٝA"l[|ŲHLN밪4*sG3|Dv}?+y߉{OuOAt4Jj.u]Gz*҉sP'VQKbA1u\`& Af;HWj hsO;ogTu uj7S3/QzUr&wS`M$X_L7r2;aE+ώ%vikDA:dR+%KzƉo>eOth$z%: :{WwaQ:wz%4foɹE[9<]#ERINƻv溂E%P1i01 |Jvҗ&{b?9g=^wζXn/lK::90KwrюO\!ջ3uzuGv^;騢wq<Iatv09:tt~hEG`v;3@MNZD.1]L:{ծI3`L(÷ba")Y.iljCɄae#I"1 `3*Bdz>j<fU40⨬%O$3cGt]j%Fߠ_twJ;ABU8vP3uEԑwQ V:h%))LfraqX-ۿX]v-\9I gl8tzX ]ecm)-cgʒ#Uw=Wlێn(0hPP/ӨtQ“&J35 $=]r1{tLuǮ*i0_;NƝ8;-vݏr8+U-kruȕYr0RnC]*ެ(M:]gE;{]tg(#ZJ9y>utRDRMdr9㪩̞zֹb<ģ&wzJM"iI( .ꮅX)Qw:9,i좜\Ԛi7&N0:asϓc];=ΗOӣ APqz93 y $)A*kVHZwBƺnWNaby>XMN*45~ղM6Nvm;A=jֲ.~1}(9`KJ/V F9[=`~[;sRuk]rєT!)iQO)Y$V ی ۤmzWz5IM Zb )ˆC`6 rRa}qNmUfDsWuˤV{ Pݝ'=Kֳbg,UҘVz2ﴻnjNgBb{? ߮tcsͻQuxVCIY۠:(V뺕 ٥2;t`@Fo{Z9`;]wMzU~%UA蛚dI vGq\r82iu +St`cR.6U/M9IENDB` REDROOM
PHP 5.6.40
Preview: dmi.py Size: 6.77 KB
//lib/python3.6/site-packages/cloudinit/dmi.py

# This file is part of cloud-init. See LICENSE file for license information.
import logging
import os
import re
from collections import namedtuple
from typing import Optional

from cloudinit import subp
from cloudinit.util import is_container, is_FreeBSD

LOG = logging.getLogger(__name__)

# Path for DMI Data
DMI_SYS_PATH = "/sys/class/dmi/id"

KernelNames = namedtuple("KernelNames", ["linux", "freebsd"])
KernelNames.__new__.__defaults__ = (None, None)

# FreeBSD's kenv(1) and Linux /sys/class/dmi/id/* both use different names from
# dmidecode. The values are the same, and ultimately what we're interested in.
# These tools offer a "cheaper" way to access those values over dmidecode.
# This is our canonical translation table. If we add more tools on other
# platforms to find dmidecode's values, their keys need to be put in here.
DMIDECODE_TO_KERNEL = {
    "baseboard-asset-tag": KernelNames("board_asset_tag", "smbios.planar.tag"),
    "baseboard-manufacturer": KernelNames(
        "board_vendor", "smbios.planar.maker"
    ),
    "baseboard-product-name": KernelNames(
        "board_name", "smbios.planar.product"
    ),
    "baseboard-serial-number": KernelNames(
        "board_serial", "smbios.planar.serial"
    ),
    "baseboard-version": KernelNames("board_version", "smbios.planar.version"),
    "bios-release-date": KernelNames("bios_date", "smbios.bios.reldate"),
    "bios-vendor": KernelNames("bios_vendor", "smbios.bios.vendor"),
    "bios-version": KernelNames("bios_version", "smbios.bios.version"),
    "chassis-asset-tag": KernelNames(
        "chassis_asset_tag", "smbios.chassis.tag"
    ),
    "chassis-manufacturer": KernelNames(
        "chassis_vendor", "smbios.chassis.maker"
    ),
    "chassis-serial-number": KernelNames(
        "chassis_serial", "smbios.chassis.serial"
    ),
    "chassis-version": KernelNames(
        "chassis_version", "smbios.chassis.version"
    ),
    "system-manufacturer": KernelNames("sys_vendor", "smbios.system.maker"),
    "system-product-name": KernelNames(
        "product_name", "smbios.system.product"
    ),
    "system-serial-number": KernelNames(
        "product_serial", "smbios.system.serial"
    ),
    "system-uuid": KernelNames("product_uuid", "smbios.system.uuid"),
    "system-version": KernelNames("product_version", "smbios.system.version"),
}


def _read_dmi_syspath(key: str) -> Optional[str]:
    """
    Reads dmi data from /sys/class/dmi/id
    """
    kmap = DMIDECODE_TO_KERNEL.get(key)
    if kmap is None or kmap.linux is None:
        return None
    dmi_key_path = "{0}/{1}".format(DMI_SYS_PATH, kmap.linux)
    LOG.debug("querying dmi data %s", dmi_key_path)
    if not os.path.exists(dmi_key_path):
        LOG.debug("did not find %s", dmi_key_path)
        return None

    try:
        with open(dmi_key_path, "rb") as fp:
            key_data = fp.read()
    except PermissionError:
        LOG.debug("Could not read %s", dmi_key_path)
        return None

    # uninitialized dmi values show as all \xff and /sys appends a '\n'.
    # in that event, return empty string.
    if key_data == b"\xff" * (len(key_data) - 1) + b"\n":
        key_data = b""

    try:
        return key_data.decode("utf8").strip()
    except UnicodeDecodeError as e:
        LOG.error(
            "utf-8 decode of content (%s) in %s failed: %s",
            dmi_key_path,
            key_data,
            e,
        )

    return None


def _read_kenv(key: str) -> Optional[str]:
    """
    Reads dmi data from FreeBSD's kenv(1)
    """
    kmap = DMIDECODE_TO_KERNEL.get(key)
    if kmap is None or kmap.freebsd is None:
        return None

    LOG.debug("querying dmi data %s", kmap.freebsd)

    try:
        cmd = ["kenv", "-q", kmap.freebsd]
        (result, _err) = subp.subp(cmd)
        result = result.strip()
        LOG.debug("kenv returned '%s' for '%s'", result, kmap.freebsd)
        return result
    except subp.ProcessExecutionError as e:
        LOG.debug("failed kenv cmd: %s\n%s", cmd, e)

    return None


def _call_dmidecode(key: str, dmidecode_path: str) -> Optional[str]:
    """
    Calls out to dmidecode to get the data out. This is mostly for supporting
    OS's without /sys/class/dmi/id support.
    """
    try:
        cmd = [dmidecode_path, "--string", key]
        (result, _err) = subp.subp(cmd)
        result = result.strip()
        LOG.debug("dmidecode returned '%s' for '%s'", result, key)
        if result.replace(".", "") == "":
            return ""
        return result
    except subp.ProcessExecutionError as e:
        LOG.debug("failed dmidecode cmd: %s\n%s", cmd, e)
        return None


def read_dmi_data(key: str) -> Optional[str]:
    """
    Wrapper for reading DMI data.

    If running in a container return None.  This is because DMI data is
    assumed to be not useful in a container as it does not represent the
    container but rather the host.

    This will do the following (returning the first that produces a
    result):
        1) Use a mapping to translate `key` from dmidecode naming to
           sysfs naming and look in /sys/class/dmi/... for a value.
        2) Use `key` as a sysfs key directly and look in /sys/class/dmi/...
        3) Fall-back to passing `key` to `dmidecode --string`.

    If all of the above fail to find a value, None will be returned.
    """

    if is_container():
        return None

    if is_FreeBSD():
        return _read_kenv(key)

    syspath_value = _read_dmi_syspath(key)
    if syspath_value is not None:
        return syspath_value

    def is_x86(arch):
        return arch == "x86_64" or (arch[0] == "i" and arch[2:] == "86")

    # running dmidecode can be problematic on some arches (LP: #1243287)
    uname_arch = os.uname()[4]
    if not (is_x86(uname_arch) or uname_arch in ("aarch64", "amd64")):
        LOG.debug("dmidata is not supported on %s", uname_arch)
        return None

    dmidecode_path = subp.which("dmidecode")
    if dmidecode_path:
        return _call_dmidecode(key, dmidecode_path)

    LOG.debug("did not find either path %s or dmidecode command", DMI_SYS_PATH)
    return None


def sub_dmi_vars(src: str) -> str:
    """Replace __dmi.VARNAME__ with DMI values from either sysfs or kenv."""
    if "__" not in src:
        return src
    valid_dmi_keys = DMIDECODE_TO_KERNEL.keys()
    for match in re.findall(r"__dmi\.([^_]+)__", src):
        if match not in valid_dmi_keys:
            LOG.warning(
                "Ignoring invalid __dmi.%s__ in %s. Expected one of: %s.",
                match,
                src,
                valid_dmi_keys,
            )
            continue
        dmi_value = read_dmi_data(match)
        if not dmi_value:
            dmi_value = ""
        LOG.debug(
            "Replacing __dmi.%s__ in '%s' with '%s'.",
            match,
            src,
            dmi_value,
        )
        src = src.replace(f"__dmi.{match}__", dmi_value)
    return src

Directory Contents

Dirs: 11 × Files: 29

Name Size Perms Modified Actions
analyze DIR
- drwxr-xr-x 2026-01-24 23:01:14
Edit Download
cmd DIR
- drwxr-xr-x 2026-01-24 23:01:14
Edit Download
config DIR
- drwxr-xr-x 2026-01-24 23:01:14
Edit Download
distros DIR
- drwxr-xr-x 2026-01-24 23:01:14
Edit Download
filters DIR
- drwxr-xr-x 2026-01-24 23:01:14
Edit Download
handlers DIR
- drwxr-xr-x 2026-01-24 23:01:14
Edit Download
mergers DIR
- drwxr-xr-x 2026-01-24 23:01:14
Edit Download
net DIR
- drwxr-xr-x 2026-01-24 23:01:14
Edit Download
reporting DIR
- drwxr-xr-x 2026-01-24 23:01:14
Edit Download
sources DIR
- drwxr-xr-x 2026-01-24 23:01:14
Edit Download
- drwxr-xr-x 2026-01-24 23:01:14
Edit Download
7.05 KB lrw-r--r-- 2023-12-04 11:47:40
Edit Download
2.45 KB lrw-r--r-- 2023-12-04 11:47:40
Edit Download
3.22 KB lrw-r--r-- 2023-12-04 11:47:40
Edit Download
6.77 KB lrw-r--r-- 2023-12-04 11:47:40
Edit Download
2.00 KB lrw-r--r-- 2023-12-04 11:47:40
Edit Download
3.38 KB lrw-r--r-- 2023-12-04 11:47:40
Edit Download
4.28 KB lrw-r--r-- 2023-12-04 11:47:40
Edit Download
16.41 KB lrw-r--r-- 2023-12-04 11:47:40
Edit Download
2.43 KB lrw-r--r-- 2023-12-04 11:47:40
Edit Download
5.47 KB lrw-r--r-- 2023-12-04 11:47:40
Edit Download
22.97 KB lrw-r--r-- 2023-12-04 11:47:40
Edit Download
2.52 KB lrw-r--r-- 2023-12-04 11:47:40
Edit Download
1022 B lrw-r--r-- 2023-12-04 11:47:40
Edit Download
10.28 KB lrw-r--r-- 2023-12-04 11:47:40
Edit Download
2.02 KB lrw-r--r-- 2026-01-23 08:56:46
Edit Download
1.74 KB lrw-r--r-- 2023-12-04 11:47:40
Edit Download
1.93 KB lrw-r--r-- 2023-12-04 11:47:40
Edit Download
22.28 KB lrw-r--r-- 2026-01-23 08:56:47
Edit Download
38.88 KB lrw-r--r-- 2026-01-23 08:56:46
Edit Download
13.23 KB lrw-r--r-- 2023-12-04 11:47:40
Edit Download
5.95 KB lrw-r--r-- 2023-12-04 11:47:40
Edit Download
3.15 KB lrw-r--r-- 2023-12-04 11:47:40
Edit Download
703 B lrw-r--r-- 2023-12-04 11:47:40
Edit Download
27.32 KB lrw-r--r-- 2023-12-04 11:47:40
Edit Download
14.43 KB lrw-r--r-- 2023-12-04 11:47:40
Edit Download
96.43 KB lrw-r--r-- 2023-12-04 11:47:40
Edit Download
566 B lrw-r--r-- 2026-01-23 08:56:50
Edit Download
3.76 KB lrw-r--r-- 2023-12-04 11:47:40
Edit Download
0 B lrw-r--r-- 2023-12-04 11:47:40
Edit Download

If ZipArchive is unavailable, a .tar will be created (no compression).
© 2026 REDROOM — Secure File Manager. All rights reserved. Built with ❤️ & Red Dark UI