组件和产品定制化rootfs镜像指导

说明

openUBMC支持组件或产品在构建镜像时定制rootfs,本指导用于帮助开发者理解相关功能。

组件定制化配置权限

组件构建时看不到rootfs,无法在cmake或conanfile中执行产品级定制,定制的场景示例:

rootfs运行在一个只读文件系统中,iam组件需要维护/etc/passwd文件,需要能够读写该文件。因此,需要将/etc/passwd文件变更成一个软链接,指向数据区的可读写的文件。该步骤无法在组件自身构建时完成,必须在rootfs集成阶段运行。

组件定制化功能为组件提供了在rootfs集成阶段运行组件python代码的能力,基本原理是由组件将customization.py文件打包到package目录的include/customization.py,产品构建时会搜索该文件并执行。

组件定制化脚本包含post_image(只集成了conan组件,未集成rootfs)和post_rootfs(集成了conan组件和rootfs)两个阶段,定制化脚本示例:

import subprocess


# 定制化脚本,由manifest构建时调用
class Customization(object):

    def __init__(self, board_name, rootfs_path):
        self.board_name = board_name
        self.rootfs_path = rootfs_path

    def post_image(self):
        pass

    def post_rootfs(self):
        pass

定制化脚本建议放在组件仓的build目录,bingo在构建组件时会自动打包build目录下的所有文件,详见自动生成的conanbase.py

以下示例用于演示了一种场景:某一组件要求/etc/passwd文件权限必须为600,该文件实际由rootfs基础镜像带入,为确保权限正确性,需要组件在post_rootfs(rootfs制作完成后)执行一段定制化脚本完成赋权。

import subprocess

# 定制化脚本,由manifest构建时调用
class Customization(object):

    def __init__(self, board_name, rootfs_path):
        self.board_name = board_name
        self.rootfs_path = rootfs_path

    def post_rootfs(self):
        subprocess.run(['/usr/bin/sudo', '/usr/bin/chmod', '600', '/etc/passwd'], check=True)

产品定制化配置权限

产品有对openubmc集成的rootfs镜像定制化述求时,可以由产品manifest.yml文件记录的customization定制化脚本完成。

该脚本有多个阶段执行,包括rootfs_common(基础定制,仅集成所有conan包,未集成rootfs、kernel drivers)、rootfs_cust(集成rootfs和kernel drivers后)、datafs_cust(入参是数据区,定制烧片时使用的数据文件)、rootfs_debug_cust(debug包定制化)、rootfs_release_cust(release包定制化)。

产品定制化脚本模板:

#!/usr/bin/env python
# coding:utf-8
import os
import sys
from bmcgo.logger import Logger

log = Logger("default")

class BaseCustomization():
    def __init__(self, work, config):
        self.config = config
        self.work = work

    def rootfs_cust(self, rootfs_path):
        log.info("empty rootfs_cust")
        pass

    def datafs_cust(self, rootfs_path):
        log.info("empty datafs_cust")
        pass

    def rootfs_debug_cust(self, rootfs_path):
        log.info("empty rootfs_debug_cust")
        pass

    def rootfs_release_cust(self, rootfs_path):
        log.info("empty rootfs_release_cust")
        pass

    def rootfs_common(self, rootfs_path):
        log.info("empty rootfs_common")
        pass
2 个赞