#!/usr/bin/env/ python
# coding: utf-8
# Copyright (c) 2024 Huawei Technologies Co., Ltd.
# openUBMC is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
# http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
"""
功 能：work_build_qemu_rootfs脚本，该脚本为qemu构建测试包
"""

import os
import subprocess
import logging
import shutil
import json

from functools import wraps

from bmcgo.tasks.task import Task
 

def log(text):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kw):
            logging.info(f"================== Start: {text} =========================")
            res = func(*args, **kw)
            logging.info(f"================== End: {text} =========================")
            logging.info(f"")
            return res
        return wrapper
    return decorator


class QemuCi(object):
    def __init__(self, src, des, lua_src, rtos_version, tool):
        self.src = src
        self.des = des
        self.lua_src = lua_src
        self.rtos_version = rtos_version
        self.tool = tool

    @log("sed -i HARDWARE_ROOTKEY_ENABLE in configs")
    def __sed_config_files(self):
        cfg_files = []
        cfg_files.append("{}/opt/bmc/apps/iam/config.cfg".format(self.des))
        cfg_files.append("{}/opt/bmc/apps/event_policy/config.cfg".format(self.des))
        cfg_files.append("{}/opt/bmc/apps/firmware_mgmt/config.cfg".format(self.des))
        cfg_files.append("{}/opt/bmc/apps/key_mgmt/config.cfg".format(self.des))
        cfg_files.append("{}/opt/bmc/apps/hica/subsys/bmc_core/config.cfg".format(self.des))
        cfg_files.append("{}/opt/bmc/apps/hica/subsys/security/config.cfg".format(self.des))
        cfg_files.append("{}/opt/bmc/apps/hica/subsys/framework/config.cfg".format(self.des))
        cfg_files.append("{}/opt/bmc/apps/hica/subsys/om/config.cfg".format(self.des))
        # change value of HARDWARE_ROOTKEY_ENABLE to false, for key_mgmt start success.
        for cfg in cfg_files:
            if not self.check_path_is_existed(cfg):
                continue
            self.tool.run_command(
                "sed -i 's/HARDWARE_ROOTKEY_ENABLE = true/HARDWARE_ROOTKEY_ENABLE = false/g' {}".format(cfg), sudo=True)

    # 关闭健康状态检查功能
    @log("sed /opt/bmc/apps/hica/subsys/framework/config.cfg")
    def __sed_framework_config(self):
        des = "{}/opt/bmc/apps/hica/subsys/framework/config.cfg".format(self.des)

        if not self.check_path_is_existed(des):
            return
        self.tool.run_command('sed -i "$aIGNORE_STARTUP_CHECK_RESULT=true" {}'.format(des), sudo=True)
        self.tool.run_command('sed -i "$aIGNORE_HEALTH_CHECK_RESULT=true" {}'.format(des), sudo=True)
        self.tool.run_command('sed -i "$aCONTINUOUS_OFFLINE_TIMES=999" {}'.format(des), sudo=True)

    # 关闭remote_console的启动，移除remote_console组件代码，仿真不支持该组件
    @log("sed /opt/bmc/apps/hica/subsys/om/config.cfg")
    def __sed_om_config(self):
        des = "{}/opt/bmc/apps/hica/subsys/om/config.cfg".format(self.des)
        if not self.check_path_is_existed(des):
            return
        self.tool.run_command('sed -i "/config:include_app(\\\"remote_console\\\")/d" {}'.format(des), sudo=True)
        app_path = "{}/opt/bmc/apps/remote_console".format(self.des)
        self.tool.run_command("rm -rf {}".format(app_path), sudo=True)     
    
    def __cp_virt(self):
        src = "{}/kernel/{}".format(self.src, self.rtos_version)
        des = "{}/lib/modules/qemu".format(self.des)

        if not self.check_path_is_existed(src):
            return 

        shutil.copytree(src, des, dirs_exist_ok=True)
    
    @log("cp -r bmc_hispor_drv.ko ")
    def __cp_hisport_ko(self):
        src = "{}/kernel/{}/bmc_hisport_drv.ko".format(self.src, self.rtos_version)
        des = "{}/lib/modules/ko/bmc_hisport_drv.ko".format(self.des)

        if not self.check_path_is_existed(src):
            return
        
        self.tool.run_command("cp -rf {} {}".format(src, des), sudo=True)
    
    @log("cp -r mctp_drv.ko ")
    def __cp_mctp_ko(self):
        src = "{}/kernel/{}/mctp_drv.ko".format(self.src, self.rtos_version)
        des = "{}/lib/modules/ko/mctp_drv.ko".format(self.des)

        if not self.check_path_is_existed(src):
            return
        
        self.tool.run_command("cp -rf {} {}".format(src, des), sudo=True)


    @log("cp /root/insmod_9p_vfs.sh /root/pkg_new/opt/bmc/")
    def __cp_insmod_9p_vfs_sh(self):
        src = "{}/script/insmod_9p_vfs.sh".format(self.src)
        des = "{}/opt/bmc/".format(self.des)
        if not self.check_path_is_existed(src):
            return
        self.tool.run_command("cp {} {}".format(src, des), sudo=True)


    @log("cp /insmod_drv.sh /lib/modules")
    def __cp_insmod_drv_sh(self):
        des = "{}/lib/modules/".format(self.des)
        src = "{}/script/insmod_drv.sh".format(self.src)
        if not self.check_path_is_existed(des):
            return
        if not self.check_path_is_existed(src):
            return
        self.tool.run_command("cp {} {}".format(src, des), sudo=True)   
        
    @log("cp /data /data")
    def __cp_origin_data(self):
        src = "{}/data/".format(self.src)
        des = "{}/data/".format(self.des)

        if not self.check_path_is_existed("{}".format(src)):
            return 
        self.tool.run_command("rm -rf {}".format(des), sudo=True)
        self.tool.run_command("\cp -rf {} {}".format(src, des), sudo=True)

    def parse_node(self, node, des_dir):
        """递归处理每个节点,  创建层级目录"""
        os.makedirs(des_dir, exist_ok=True)
        if 'Data' in node:
            src_mock_data_path = os.path.join(self.des, 'data', 'mockdata')
            for filename, source_file in node['Data'].items():
                full_dest_path = os.path.join(des_dir, filename)
                full_source_path = os.path.join(src_mock_data_path, source_file)
                if not source_file or not os.path.exists(full_source_path):
                    logging.warning(f"qemu mock data source file not exist")
                    continue
                shutil.copy2(full_source_path, full_dest_path)
        if 'Address' in node:
            for address, address_node in node['Address'].items():
                address_path = os.path.join(des_dir, address)
                self.parse_node(address_node, address_path)
        if 'Channel' in node:
            for channel, channel_node in node['Channel'].items():
                channel_path = os.path.join(des_dir, channel)
                self.parse_node(channel_node, channel_path)
    
    @log("mv mock data")
    def __mv_mock_data(self):
        des_data_path = os.path.join(self.des, 'mockdata')
        mapping_file = "works/packet/qemu_shells/mockdata_mapping.json"
        mapping_path = os.path.join(self.tool.config.code_path, mapping_file)
        """解析映射配置文件, 并创建目录结构"""
        try:
            with open(mapping_path, 'r') as f:
                data = json.load(f)
        except Exception as _:
            logging.error(f"mapping file not exist: {mapping_file}")
            return

        i2c_data = data.get('i2c', {})
        if not i2c_data:
            logging.error("i2c data not exist")
            return
        i2c_root_dir = os.path.join(des_data_path, 'i2c')
        # 创建i2c根目录
        os.makedirs(i2c_root_dir, exist_ok=True)
        # 处理每个i2c总线数据
        for bus, bus_node in i2c_data.items():
            bus_path = os.path.join(i2c_root_dir, bus)
            self.parse_node(bus_node, bus_path)
        # 处理hisport
        hisport_data = data.get('hisport', {})
        for h_bus, bus_node in hisport_data.items():
            if h_bus == 'description':
                continue
            h_bus = str(int(h_bus) + 12) # 转换为i2c总线(从12开始)
            bus_path = os.path.join(i2c_root_dir, h_bus)
            self.parse_node(bus_node, bus_path)
        # 移除data下mockdata
        # 处理IMU数据
        imu_data = data.get('imu', {})
        if not imu_data:
            logging.error("imu data not exist")
            return
        imu_root_dir = os.path.join(des_data_path, 'IMU')
        self.parse_node(imu_data, imu_root_dir)
        # 处理pciecard数据
        pcie_data = data.get('pciecard', {})
        if not pcie_data:
            logging.error("pcie card data not exist")
            return
        pcie_root_dir = os.path.join(des_data_path, 'pciecard')
        self.parse_node(pcie_data, pcie_root_dir)
        self.tool.run_command(f'rm -rf {os.path.join(self.des, 'data', 'mockdata')}')

    @log("cp gpio.lua ")
    def _cp_gpio_lua(self):
        src = "{}/data/lua/gpio.lua".format(self.src)
        des = "{}/opt/bmc/apps/hwproxy/lualib/stream/gpio.lua".format(self.des)
        if not self.check_path_is_existed(src):
            return
        if not self.check_path_is_existed(des):
            return
        self.tool.run_command("cp {} {}".format(src, des), sudo=True)
    
    @log("cp jtag_base.lua ")
    def _cp_jtag_base_lua(self):
        src = "{}/data/lua/jtag_base.lua".format(self.src)
        des = "{}/opt/bmc/apps/hwproxy/lualib/stream/jtag_base.lua".format(self.des)
        if not self.check_path_is_existed(src):
            return
        if not self.check_path_is_existed(des):
            return
        self.tool.run_command("cp {} {}".format(src, des), sudo=True)
    
    @log("cp jtag.lua ")
    def _cp_jtag_lua(self):
        src = "{}/data/lua/jtag.lua".format(self.src)
        des = "{}/opt/bmc/apps/hwproxy/lualib/stream/jtag.lua".format(self.des)
        if not self.check_path_is_existed(src):
            return
        if not self.check_path_is_existed(des):
            return
        self.tool.run_command("cp {} {}".format(src, des), sudo=True)
    
    @log("cp jtag_over_gpio.lua ")
    def _cp_jtag_over_gpio_lua(self):
        src = "{}/data/lua/jtag_over_gpio.lua".format(self.src)
        des = "{}/opt/bmc/apps/hwproxy/lualib/stream/jtag_over_gpio.lua".format(self.des)
        if not self.check_path_is_existed(src):
            return
        if not self.check_path_is_existed(des):
            return
        self.tool.run_command("cp {} {}".format(src, des), sudo=True)
    
    @log("cp jtag_over_localbus.lua ")
    def _cp_jtag_over_localbus_lua(self):
        src = "{}/data/lua/jtag_over_localbus.lua".format(self.src)
        des = "{}/opt/bmc/apps/hwproxy/lualib/stream/jtag_over_localbus.lua".format(self.des)
        if not self.check_path_is_existed(src):
            return
        if not self.check_path_is_existed(des):
            return
        self.tool.run_command("cp {} {}".format(src, des), sudo=True)


    @log("sed /etc/rc.d/rc.sysinit lua")
    def __sed_rc_sysinit(self):
        des = "{}/etc/rc.d/rc.sysinit".format(self.des)
        
        if not self.check_path_is_existed(des):
            return
        self.tool.run_command("sed -i '/rtos_snapshot.ko/s/^/#/g' {}".format(des), sudo=True)

        # 此处需要调用原生命令,否则只会执行>>之前
        subprocess.run(["echo", "\"chmod 755 /data/home/busybox_x\"", ">>", des], 
                       shell=False, capture_output=True, check=False)
        subprocess.run(["echo", "\"/data/home/busybox_x telnetd &\"", ">>", des], 
                       shell=False, capture_output=True, check=False)
        subprocess.run(["echo", "\"chmod 755 /data/home/busybox1711\"", ">>", des], 
                       shell=False, capture_output=True, check=False)
        subprocess.run(["echo", "\"chmod -R 755 /data/opt/bmc\"", ">>", des], 
                       shell=False, capture_output=True, check=False)
        subprocess.run(["echo", "\"chown -R apache:apache /opt/bmc/web\"", ">>", des], 
                       shell=False, capture_output=True, check=False) 
        subprocess.run(["echo", "\"chown -R secbox:secbox /data/opt/bmc/persistence.local/cooling.db\"", ">>", des], 
                       shell=False, capture_output=True, check=False)
        subprocess.run(["echo", "\"chown -R secbox:secbox /data/opt/bmc/persistence.local/power_strategy.db\"", des], 
                       shell=False, capture_output=True, check=False)
        subprocess.run(["echo", "\"chown -R secbox:secbox /data/opt/bmc/env_web_view.dat\"", ">>", des], 
                       shell=False, capture_output=True, check=False)
        subprocess.run(["echo", "\"chown -R secbox:secbox /data/opt/bmc/ps_web_view.dat\"", ">>", des], 
                       shell=False, capture_output=True, check=False)
        subprocess.run(["echo", "\"chown -R secbox:secbox /data/opt/bmc/powerview.txt\"", ">>", des], 
                       shell=False, capture_output=True, check=False)
        subprocess.run(["echo", "\"touch /dev/uart_connect\"", ">>", des], 
                       shell=False, capture_output=True, check=False)
        # 9p.sh在此行之前调用
        self.tool.run_command("sed -i '/rm -rf \/var\/lib/i sh \/opt\/bmc\/insmod_9p_vfs.sh' {}".format(des), 
                              sudo=True)
        subprocess.run(["echo", "\"#增加软连接\"", ">>", des], shell=False, capture_output=True, check=False)
        subprocess.run(["echo", "\"rm /etc/shadow\"", ">>", des], shell=False, capture_output=True, check=False)
        subprocess.run(["echo", "\"ln -s /data/trust/shadow /etc/shadow\"", ">>", des], 
                       shell=False, capture_output=True, check=False)

    @log("chown -R 96:96 /opt/bmc/apps/rmcpd")
    def __chown_rmcpd(self):
        des = "{}/opt/bmc/apps/rmcpd".format(self.des)

        if not self.check_path_is_existed(des):
            return
        self.tool.run_command("chown -R 96:96 {}".format(des), sudo=True)

    # 打桩进入沙箱的组件
    @log("sed /etc/sysytemd/system")
    def __sed_rc_system(self):
        cfg_files = []
        cfg_files.append("{}/etc/systemd/system/alarm.service".format(self.des))
        cfg_files.append("{}/etc/systemd/system/energy.service".format(self.des))
        cfg_files.append("{}/etc/systemd/system/hardware.service".format(self.des))
        cfg_files.append("{}/etc/systemd/system/ras.service".format(self.des))
        cfg_files.append("{}/etc/systemd/system/interface.service".format(self.des))

        for cfg in cfg_files:
            if not self.check_path_is_existed(cfg):
                continue
            self.tool.run_command(
                "sed -i 's/AmbientCapabilities=CAP_SYS_ADMIN/AmbientCapabilities=CAP_SYS_ADMIN CAP_FOWNER "
                "CAP_SYS_MODULE CAP_DAC_OVERRIDE CAP_SYS_CHROOT CAP_NET_BIND_SERVICE CAP_MKNOD CAP_NET_ADMIN "
                "CAP_NET_RAW CAP_SYS_RAWIO CAP_CHOWN/g' {}".format(cfg), sudo=True)
        
        des = "{}/etc/systemd/system/om.service".format(self.des)
        if not self.check_path_is_existed(des):
            return
        self.tool.run_command(
            'sed -i "s/AmbientCapabilities=CAP_DAC_OVERRIDE CAP_NET_BIND_SERVICE/AmbientCapabilities='
            'CAP_SYS_ADMIN CAP_FOWNER CAP_SYS_MODULE CAP_DAC_OVERRIDE CAP_SYS_CHROOT CAP_NET_BIND_SERVICE '
            'CAP_MKNOD CAP_NET_ADMIN CAP_NET_RAW CAP_SYS_RAWIO CAP_CHOWN/g" {}'.format(des), sudo=True)
        
        #ssdp组件更新后进入沙箱，仿真不支持，修改启动命令
        des = "{}/lib/systemd/system/bmc_ssdp.service".format(self.des)
        if not self.check_path_is_existed(des):
            return
        self.tool.run_command(
            'sed -i "s/ExecStart=\/usr\/sbin\/secbox -f \/opt\/bmc\/apps\/ssdp\/secbox.cfg '
            '\/opt\/bmc\/apps\/ssdp\/ssdp/ExecStart=\/opt\/bmc\/apps\/ssdp\/ssdp/g" {}'.format(des), sudo=True)
        
    def __mock_pcie(self):
        des = "{}/etc/systemd/system/interface.service".format(self.des)
        self.tool.run_command("sed -i '/ExecStartPost/a ExecStartPost=/bin/bash /data/mdb_set_pcie.sh &' {}".format(des), sudo=True)


    @log("run qemu_action")
    def qemu_action(self):
        self.__cp_virt()
        self.__cp_hisport_ko()
        self.__cp_mctp_ko()
        self.__cp_insmod_9p_vfs_sh()
        self.__cp_insmod_drv_sh()
        self.__sed_rc_sysinit()
        self.__mock_pcie()
        self.__sed_config_files()
        self.__cp_origin_data()
        self.__mv_mock_data()
        self._cp_gpio_lua()
        self._cp_jtag_base_lua()
        self._cp_jtag_lua()
        self._cp_jtag_over_gpio_lua()
        self._cp_jtag_over_localbus_lua()
        self.__chown_rmcpd()
        self.__sed_om_config()
        self.__sed_rc_system()
        self.__sed_framework_config()
        self.__sed_mc_config()
        self.__sed_service_config()
        self.__sed_etc_system_conf()
        self.__sed_etc_systemd_journald_conf()
        self.__sed_S11Eventinit_sh()
        self.__sed_S11FrudataInit_sh()
        self.__sed_S11SensorInit_sh()
        self.__sed_S12BiosInit_sh()
        self.__sed_S12ComputeInit_sh()
        self.__sed_S12GeneralHardwareInit_sh()
        self.__sed_S12ManufactureInit_sh()
        self.__sed_S12NetworkAdapterInit_sh()
        self.__sed_S12PcieDeviceInit_sh()
        self.__sed_S12StorageInit_sh()
        self.__sed_S16FileTransferInit_sh()
        self.__sed_S16SsdpInit_sh()
        self.__sed_ipmi_core_start()
        self.__sed_S16UmsInit_sh()
        self.__sed_data_fs_check_sh()
        self.__sed_log_partition_check_sh()
        self.__sed_partition_migrate_sh()
        self.__sed_trust_partition_check_sh()
        self.__sed_ensure_exist_sh()

    def check_path_is_existed(self, path):
        if os.path.exists(path):
            return True
        logging.error("path not exist: {}".format(path))
        return False

    @log("del ve_libs_temp")
    def rm_ve_libs(self):
        virtio_des = "{}/virtio/".format(self.des)
        lua_code_des = "{}/lua_code/".format(self.des)
        scripts_des = "{}/scripts/".format(self.des)
        qemu_des = "{}/qemu/".format(self.des)
        qemu_luas_des = "{}/qemu_luas/".format(self.des)
        sr_des = "{}/sr/".format(self.des) 

        if self.check_path_is_existed(virtio_des):
            self.tool.run_command("\\rm -rf {}".format(virtio_des), sudo=True)
        else:
            logging.info(f"{ virtio_des } not exist")
        
        if self.check_path_is_existed(lua_code_des):
            self.tool.run_command("\\rm -rf {}".format(lua_code_des), sudo=True)
        else:
            logging.info(f"{ lua_code_des } not exist")

        if self.check_path_is_existed(scripts_des):
            self.tool.run_command("\\rm -rf {}".format(scripts_des), sudo=True)
        else:
            logging.info(f"{ scripts_des } not exist")

        if self.check_path_is_existed(qemu_des):
            self.tool.run_command("\\rm -rf {}".format(qemu_des), sudo=True)
        else:
            logging.info(f"{ qemu_des } not exist")
    
        if self.check_path_is_existed(qemu_luas_des):
            self.tool.run_command("\\rm -rf {}".format(qemu_luas_des), sudo=True)
        else:
            logging.info(f"{ qemu_luas_des } not exist")

        if self.check_path_is_existed(sr_des):
            self.tool.run_command("\\rm -rf {}".format(sr_des), sudo=True)
        else:
            logging.info(f"{ sr_des } not exist")

    @log("sed /opt/bmc/conf/mc_control.json")
    def __sed_mc_config(self):
        des = "{}/opt/bmc/conf/mc_control.json".format(self.des)
        # 关闭maca检查机制，防止因环境配置太低导致的反复maca重启
        self.tool.run_command('sed -i "s/true/false/g" {}'.format(des), sudo=True)
        timeout_mins = 2
        interval_mins = 1
        time_window_mins = 10
        max_num = 99
        self.tool.run_command('sed -i "s/: {}/: {}/g" {}'.format(timeout_mins, max_num, des), sudo=True)
        self.tool.run_command('sed -i "s/: {}/: {}/g" {}'.format(time_window_mins, max_num, des), sudo=True)
        self.tool.run_command('sed -i "s/: {}/: {}/g" {}'.format(interval_mins, max_num, des), sudo=True)

    @log("sed /etc/systemd/system/secbox")
    def __sed_service_config(self):
        cfg_files = []
        cfg_files.append("{}/etc/systemd/system/alarm.service".format(self.des))
        cfg_files.append("{}/etc/systemd/system/energy.service".format(self.des))
        cfg_files.append("{}/etc/systemd/system/hardware.service".format(self.des))
        cfg_files.append("{}/etc/systemd/system/interface.service".format(self.des))
        cfg_files.append("{}/etc/systemd/system/om.service".format(self.des))
        cfg_files.append("{}/etc/systemd/system/ras.service".format(self.des))

        for cfg in cfg_files:
            if not self.check_path_is_existed(cfg):
                continue
            self.tool.run_command('sed -i "s/User=secbox/User=root/g" {}'.format(cfg), sudo=True)
            self.tool.run_command('sed -i "s/ExecStart=secbox -f .* -c /ExecStart=bash -c /g" {}'
                                    .format(cfg), sudo=True)
            self.tool.run_command('sed -i "/Group=secbox/d" {}'.format(cfg), sudo=True) 
    
    @log("sed /etc/systemd/system.conf")
    def __sed_etc_system_conf(self):
        system_files = "{}/etc/systemd/system.conf".format(self.des)
        self.tool.run_command('sed -i "s/#LogLevel=info/LogLevel=debug/g" {}'.format(system_files), sudo=True)
        self.tool.run_command('sed -i "s/#LogTarget=journal-or-kmsg/LogTarget=journalctl/g" {}'.format(system_files), sudo=True)
    
    @log("sed /etc/systemd/rc.d/rc.sysint")
    def __sed_etc_system_rc_sysint(self):
        rc_sysinit = "{}/etc/rc.d/rc.sysinit".format(self.des)
        self.tool.run_command('sed -i "558,563d" {}'.format(rc_sysinit), sudo=True)
        self.tool.run_command('sed -i "s/logpart_mount_time=0/logpart_mount_time=4/g" {}'.format(rc_sysinit), sudo=True)
        self.tool.run_command('sed -i "522,523d" {}'.format(rc_sysinit), sudo=True)
        self.tool.run_command('sed -i "522i\dev_files=\\"/dev/sys_info /dev/trng /dev/mem /dev/dfx /dev/uart_connect /dev/mdio /dev/mctp\\"" {}'.format(rc_sysinit), sudo=True)
        self.tool.run_command('sed -i "394d" {}'.format(rc_sysinit), sudo=True)
        self.tool.run_command('sed -i "391d" {}'.format(rc_sysinit), sudo=True)
        self.tool.run_command('sed -i "384d" {}'.format(rc_sysinit), sudo=True)
        self.tool.run_command('sed -i "349,351d" {}'.format(rc_sysinit), sudo=True)
        self.tool.run_command('sed -i "311,316d" {}'.format(rc_sysinit), sudo=True)
        self.tool.run_command('sed -i "307d" {}'.format(rc_sysinit), sudo=True)
        self.tool.run_command('sed -i "146d" {}'.format(rc_sysinit), sudo=True)
        self.tool.run_command('sed -i "144d" {}'.format(rc_sysinit), sudo=True)
        self.tool.run_command('sed -i "133d" {}'.format(rc_sysinit), sudo=True)
        self.tool.run_command('sed -i "336d" {}'.format(rc_sysinit), sudo=True)
        self.tool.run_command('sed -i "326,328d" {}'.format(rc_sysinit), sudo=True)
        self.tool.run_command('sed -i "244d" {}'.format(rc_sysinit), sudo=True)
        self.tool.run_command('sed -i "197d" {}'.format(rc_sysinit), sudo=True)
        self.tool.run_command('sed -i "154d" {}'.format(rc_sysinit), sudo=True)
        self.tool.run_command('sed -i "84,85d" {}'.format(rc_sysinit), sudo=True)
    
    @log("sed /etc/systemd/journald_conf")
    def __sed_etc_systemd_journald_conf(self):
        journald_conf = "{}/etc/systemd/journald.conf".format(self.des)
        self.tool.run_command('sed -i "s/SystemMaxUse=8M/SystemMaxUse=25M/g" {}'.format(journald_conf), sudo=True)
        self.tool.run_command('sed -i "s/RuntimeMaxUse=8M/RuntimeMaxUse=25M/g" {}'.format(journald_conf), sudo=True)
        self.tool.run_command('sed -i "s/    sleep 1/    sleep 0.1/g" {}'.format(journald_conf), sudo=True)
    
    @log("sed /etc/rc.d/rc.start/S11EventInit.sh")
    def __sed_S11Eventinit_sh(self):
        S11EventInit_file = "{}/etc/rc.d/rc.start/S11EventInit.sh".format(self.des)
        self.tool.run_command('sed -i "5,7d" {}'.format(S11EventInit_file), sudo=True)
    
    @log("sed /etc/rc.d/rc.start/S11FrudataInit.sh")
    def __sed_S11FrudataInit_sh(self):
        S11FrudataInit_file = "{}/etc/rc.d/rc.start/S11FrudataInit.sh".format(self.des)
        self.tool.run_command('sed -i "5d" {}'.format(S11FrudataInit_file), sudo=True)
    
    @log("sed /etc/rc.d/rc.start/S11SensorInit.sh")
    def __sed_S11SensorInit_sh(self):
        S11SensorInit_file = "{}/etc/rc.d/rc.start/S11SensorInit.sh".format(self.des)
        self.tool.run_command('sed -i "14,17d" {}'.format(S11SensorInit_file), sudo=True)
    
    @log("sed /etc/rc.d/rc.start/S12BiosInit.sh")
    def __sed_S12BiosInit_sh(self):
        S12BiosInit_file = "{}/etc/rc.d/rc.start/S12BiosInit.sh".format(self.des)
        self.tool.run_command('sed -i "4,12d" {}'.format(S12BiosInit_file), sudo=True)
    
    @log("sed /etc/rc.d/rc.start/S12ComputeInit.sh")
    def __sed_S12ComputeInit_sh(self):
        S12ComputeInit_file = "{}/etc/rc.d/rc.start/S12ComputeInit.sh".format(self.des)
        self.tool.run_command('sed -i "5,6d" {}'.format(S12ComputeInit_file), sudo=True)
    
    @log("sed /etc/rc.d/rc.start/S12GeneralHardwareInit.sh")
    def __sed_S12GeneralHardwareInit_sh(self):
        S12GeneralHardwareInit_file = "{}/etc/rc.d/rc.start/S12GeneralHardwareInit.sh".format(self.des)
        self.tool.run_command('sed -i "14,21d" {}'.format(S12GeneralHardwareInit_file), sudo=True)
    
    @log("sed /etc/rc.d/rc.start/S12ManufactureInit.sh")
    def __sed_S12ManufactureInit_sh(self):
        S12ManufactureInit_file = "{}/etc/rc.d/rc.start/S12ManufactureInit.sh".format(self.des)
        self.tool.run_command('sed -i "14,15d" {}'.format(S12ManufactureInit_file), sudo=True)
    
    @log("sed /etc/rc.d/rc.start/S12NetworkAdapterInit.sh")
    def __sed_S12NetworkAdapterInit_sh(self):
        S12NetworkAdapterInit_file = "{}/etc/rc.d/rc.start/S12NetworkAdapterInit.sh".format(self.des)
        self.tool.run_command('sed -i "13,16d" {}'.format(S12NetworkAdapterInit_file), sudo=True)
    
    @log("sed /etc/rc.d/rc.start/S12PcieDeviceInit.sh")
    def __sed_S12PcieDeviceInit_sh(self):
        S12PcieDeviceInit_file = "{}/etc/rc.d/rc.start/S12PcieDeviceInit.sh".format(self.des)
        self.tool.run_command('sed -i "5d" {}'.format(S12PcieDeviceInit_file), sudo=True)
    
    @log("sed /etc/rc.d/rc.start/S12StorageInit.sh")
    def __sed_S12StorageInit_sh(self):
        S12StorageInit_file = "{}/etc/rc.d/rc.start/S12StorageInit.sh".format(self.des)
        self.tool.run_command('sed -i "14,19d" {}'.format(S12StorageInit_file), sudo=True)
    
    @log("sed /etc/rc.d/rc.start/S16FileTransferInit.sh")
    def __sed_S16FileTransferInit_sh(self):
        S16FileTransferInit_file = "{}/etc/rc.d/rc.start/S16FileTransferInit.sh".format(self.des)
        self.tool.run_command('sed -i "5d" {}'.format(S16FileTransferInit_file), sudo=True)
        self.tool.run_command('sed -i "1,3d" {}'.format(S16FileTransferInit_file), sudo=True)
    
    @log("sed /etc/rc.d/rc.start/S16SsdpInit.sh")
    def __sed_S16SsdpInit_sh(self):
        S16SsdpInit_file = "{}/etc/rc.d/rc.start/S16SsdpInit.sh".format(self.des)
        self.tool.run_command('sed -i "1d" {}'.format(S16SsdpInit_file), sudo=True)
    
    @log("sed /etc/rc.d/rc.start/ipmi_core.start")
    def __sed_ipmi_core_start(self):
        ipmi_core_start_file = "{}/etc/rc.d/rc.start/ipmi_core.start".format(self.des)
        self.tool.run_command('sed -i "2,4d" {}'.format(ipmi_core_start_file), sudo=True)
    
    @log("sed /etc/rc.d/rc.start/S16UmsInit.sh")
    def __sed_S16UmsInit_sh(self):
        S16UmsInit_file = "{}/etc/rc.d/rc.start/S16UmsInit.sh".format(self.des)
        self.tool.run_command('sed -i "2,4d" {}'.format(S16UmsInit_file), sudo=True)
        self.tool.run_command('sed -i "6,7d" {}'.format(S16UmsInit_file), sudo=True)
    
    @log("sed /opt/bmc/script/data_fs_check.sh")
    def __sed_data_fs_check_sh(self):
        data_fs_check_file = "{}/opt/bmc/script/data_fs_check.sh".format(self.des)
        self.tool.run_command('sed -i "49d" {}'.format(data_fs_check_file), sudo=True)
    
    @log("sed /opt/bmc/script/log_partition_check.sh")
    def __sed_log_partition_check_sh(self):
        log_partition_check_file = "{}/opt/bmc/script/log_partition_check.sh".format(self.des)
        self.tool.run_command('sed -i "17d" {}'.format(log_partition_check_file), sudo=True)
        self.tool.run_command('sed -i "17i\logpart_sectors_num=0" {}'.format(log_partition_check_file), sudo=True)
    
    @log("sed /opt/bmc/script/partition_migrate.sh")
    def __sed_partition_migrate_sh(self):
        partition_migrate_file = "{}/opt/bmc/script/partition_migrate.sh".format(self.des)
        self.tool.run_command('sed -i "18,20d" {}'.format(partition_migrate_file), sudo=True)
        self.tool.run_command('sed -i "18i\logpart_sectors_num=0" {}'.format(partition_migrate_file), sudo=True)
        self.tool.run_command('sed -i "18i\permanent_sectors_num=0" {}'.format(partition_migrate_file), sudo=True)
        self.tool.run_command('sed -i "18i\ reserved_sectors_num=0" {}'.format(partition_migrate_file), sudo=True)
    
    @log("sed /opt/bmc/script/trust_partition_check.sh")
    def __sed_trust_partition_check_sh(self):
        trust_partition_check_file = "{}/opt/bmc/script/trust_partition_check.sh".format(self.des)
        self.tool.run_command('sed -i "17d" {}'.format(trust_partition_check_file), sudo=True)
        self.tool.run_command('sed -i "17i\ trustpart_sectors_num=0" {}'.format(trust_partition_check_file), sudo=True)
    
    @log("sed /etc/rc.d/rc.start/ensure_exist.sh")
    def __sed_ensure_exist_sh(self):
        ensure_exist_file = "{}/etc/rc.d/rc.start/ensure_exist.sh".format(self.des)
        self.tool.run_command('sed -i "153d" {}'.format(ensure_exist_file), sudo=True)
        self.tool.run_command('sed -i "143d" {}'.format(ensure_exist_file), sudo=True)
        self.tool.run_command('sed -i "133d" {}'.format(ensure_exist_file), sudo=True)
        self.tool.run_command('sed -i "122d" {}'.format(ensure_exist_file), sudo=True)

class TaskClass(Task):
    @staticmethod
    def copy_folder(source_path, target_path):
        # 确保目标路径存在
        os.makedirs(target_path, exist_ok=True)
        # 遍历源文件夹
        for item in os.listdir(source_path):
            source_item = os.path.join(source_path, item)
            target_item = os.path.join(target_path, item)
            # 如果是文件，直接复制
            if os.path.isfile(source_item):
                shutil.copy2(source_item, target_item)
            # 如果是文件夹，递归复制
            elif os.path.isdir(source_item):
                shutil.copytree(source_item, target_item, dirs_exist_ok=True)

    def mv_web_backend(self, qemu_rootfs_path):
        """
        将源文件夹中的文件复制到目标文件夹中
        :param qemu_rootfs_path: 目标文件夹路径
        """
        # 源文件夹路径
        web_backend_path = "mock/mock/data/interface/web_backend/interface_config/mapping_config"
        source_path = os.path.join(self.config.temp_path, "qemu", web_backend_path)

        # 目标文件夹路径
        rootfs_web_backend_path = '/opt/bmc/apps/web_backend/interface_config/mapping_config'
        target_path = os.path.join(qemu_rootfs_path, rootfs_web_backend_path.lstrip('/'))

        # 确保目标路径存在
        os.makedirs(os.path.dirname(target_path), exist_ok=True)

        self.copy_folder(source_path, target_path)
        

    def clone_lua(self, work_path, trunk_path, trunk_name, src_path, tag = None):
        self.chdir(work_path)
        self.run_command(f'rm -rf {os.path.join(work_path, trunk_name)}')
        self.run_command(f'git init {trunk_name}')
        self.chdir(os.path.join(work_path, trunk_name))
        self.run_command(f'git remote add origin {trunk_path}')
        self.run_command(f'git config core.sparseCheckout true')
        subprocess.run(['echo', src_path], stdout=open('.git/info/sparse-checkout', 'a'), check=False)
        self.run_command(f'git pull origin main')

        if tag:
            # 先获取远程信息，但不检出文件
            self.run_command('git fetch --tags origin')
            # 检出特定的tag
            self.run_command(f'git checkout tags/{tag}')
        else:
            # 如果没有指定tag，则使用原来的main分支
            self.run_command(f'git pull origin main')

    def get_luas(self, tag=None):
        qemu_mock_dir = f"{self.config.temp_path}/qemu"
        os.makedirs(qemu_mock_dir, exist_ok=True)
        self.clone_lua(qemu_mock_dir, 'https://gitcode.com/openUBMC/qemu.git', 'mock', "mock", tag=tag)
        return qemu_mock_dir

    def qemu_rootfs_deploy(self, inner_path, qemu_name, qemu_tag, qemu_rtos_version):
        # 打包原有的rootfs目录
        os.makedirs(f"{self.config.temp_path}/qemu", exist_ok=True)
        src_rootfs_path = f"{self.config.buildimg_dir}/rtos_with_driver/rootfs"
        qemu_rootfs_path = f"{self.config.temp_path}/qemu/qemu_rootfs"
        self.run_command(f"rm -rf {self.config.temp_path}/qemu/", sudo=True)
        os.makedirs(f"{self.config.temp_path}/qemu/")
        self.run_command(f"cp -a {src_rootfs_path} {qemu_rootfs_path}", sudo=True)

        os.makedirs(inner_path, exist_ok=True)

        qemu_luas_dir = os.path.join(self.get_luas(tag=qemu_tag), "mock", "mock")
        self.mv_web_backend(qemu_rootfs_path)
        QemuCi(qemu_luas_dir, qemu_rootfs_path, qemu_luas_dir, qemu_rtos_version, self).qemu_action()
        QemuCi(qemu_luas_dir, qemu_rootfs_path, qemu_luas_dir, qemu_rtos_version, self).rm_ve_libs()

        self.chdir(f"{qemu_rootfs_path}/data/script")
        self.run_command(f"make", sudo=True)
        
        self.chdir(f"{self.config.temp_path}/qemu")

        self.run_command(f"rm -rf {qemu_name}", sudo=True)
        qemu_path = f"../{qemu_name}"
        self.chdir(f"{qemu_rootfs_path}")
        # 使用相对目录压缩
        self.pipe_command([f"sudo find .", " sudo cpio -H newc --quiet -o"], qemu_path)
        self.run_command(f"pwd", sudo=True)
        self.run_command(f"gzip -k {qemu_path}", sudo=True)
        self.run_command(f"cp -dfr {qemu_path}.gz {inner_path}", sudo=True)
        # 移动zImage
        self.run_command(f"dd if={src_rootfs_path}/boot/uImage of={inner_path}/zImage_openUBMC bs=1 skip=64", sudo=True)

        # 将仿真镜像、zImage和dtb压缩为总包
        data_name = qemu_name.split('.')[0]
        self.run_command(f"rm -rf {self.config.temp_path}/{data_name}/", sudo=True)
        # 创建新目录
        os.makedirs(f"{self.config.temp_path}/{data_name}/")
        # 复制文件
        self.run_command(f"cp -dfr {qemu_path}.gz {self.config.temp_path}/{data_name}", sudo=True)
        self.run_command(f"cp -dfr {inner_path}/zImage_openUBMC {self.config.temp_path}/{data_name}", sudo=True)
        self.run_command(f"cp -dfr {self.config.temp_path}/qemu/mock/mock/data/dtb/hi1711_9p8c.dtb {self.config.temp_path}/{data_name}", sudo=True)
        # 打包压缩
        self.run_command(f"tar -czf {self.config.temp_path}/{data_name}.data.gz -C {self.config.temp_path} {data_name}", sudo=True)
        self.run_command(f"cp -dfr {self.config.temp_path}/{data_name}.data.gz {self.config.output_path}", sudo=True)

    def run(self):
        qemu_dir = os.path.join(self.config.output_path, "packet/inner")
        qemu_name = f"{self.config.board_name}_qemu_default.cpio"
        # tosupporte场景，在manifest.yml中配置了qemu_image字段的版本才会执行qemu构建
        if self.config.tosupporte_code == 'qemu':
            tosupporte_qemu_image = self.get_manufacture_config(f"tosupporte/{self.config.tosupporte_code}/qemu_image")
            if tosupporte_qemu_image is not None:
                qemu_dir = os.path.join(self.config.output_path, "packet", tosupporte_qemu_image.split("/")[0])
                qemu_tag = self.get_manufacture_config(f"tosupporte/{self.config.tosupporte_code}/qemu_tag")
                qemu_rtos_version = self.get_manufacture_config(f"tosupporte/{self.config.tosupporte_code}/qemu_rtos_version")
                qemu_name = tosupporte_qemu_image.split("/")[-1]
                logging.info(f"tosupport qemu image dir: {qemu_dir}, name: {qemu_name}, qemu_tag: {qemu_tag}, qemu_rtos_version: {qemu_rtos_version}.")
                self.qemu_rootfs_deploy(qemu_dir, qemu_name, qemu_tag, qemu_rtos_version)
            else:
                logging.info(f"tosupporte: { self.config.tosupporte_code } no need build qemu package!!!")
            return