当前位置: 首页 > 工具软件 > ipa-build > 使用案例 >

自定义ironic-python-agent镜像 ipa ramdisk and kernel

西门磊
2023-12-01

一、配置系统环境

配置一台服务器(虚拟机)能访问外部网络,使用CentOS7.6系统
升级内核

uname -r
5.10.3-1.el7.elrepo.x86_64

二、修改IPA

cd /root
git clone https://github.com/openstack/ironic-python-agent.git
cd ironic-python-agent/ironic_python_agent/
git checkout rocky
vim hardware.py (修改hardware.py 定制配置RAID)

若是在ramdisk中,则直接编辑修改
/opt/ironic-python-agent/lib/python2.7/site-packages/ironic_python_agent/hardware.py
    def get_clean_steps(self, node, ports):
        return [
            {   
                'step': 'erase_devices',
                'priority': 10,
                'interface': 'deploy',
                'reboot_requested': False,
                'abortable': True
            },
            {   
                'step': 'erase_devices_metadata',
                'priority': 99,
                'interface': 'deploy',
                'reboot_requested': False,
                'abortable': True
            },
            # ankele add
            {    
                'step': 'delete_configuration',
                'priority': 30,
                'interface': 'raid',
                'reboot_requested': False,
                'abortable': True
            },
            # ankele add
            {    
                'step': 'create_configuration',
                'priority': 20,
                'interface': 'raid',
                'reboot_requested': False,
                'abortable': True
            }
        ]

    # ankele add
    def create_configuration(self, node, ports):
        """ Create a RAID configuration.
        This method will create a custom RAID by storcli with configuration
        as read from the node's 'target_raid_config'.
        :param node: A dictionary of the node object.
        :param ports: A list of dictionaries containing information
                      of ports for the node.
        :returns: The current RAID configuration in the usual format.
        :raises:
        """
        raid_config = node.get('target_raid_config', {})
        if not raid_config:
            LOG.warning('----ankele warn---- No target_raid_config found')
            return {}
        #return self._do_create_configuration(node, ports, raid_config)
        return self.create_raid(node, ports, raid_config)  

    # ankele add 3rd
    def create_raid(self, node, ports, raid_config):
        """
        size: (string) unit of MB,GB,TB or 'all'.
        raid_level: (string) '0', '1', '5'.
        pd_count: (int) count of physical disks.
        """
        logical_disks = raid_config.get('logical_disks', {})
        for ld in logical_disks:
            size = ld.get('size') or 'all'
            controller = ld.get('controller') or self.get_controller()
            raid_level = ld.get('raid_level')
            is_root_volume = ld.get('is_root_volume', False)
            pd_count = int(ld.get('pd_count'))
            physical_disks = ld.get('physical_disks') or self.get_physical_disks(pd_count)
            drives = ','.join(physical_disks)
            args = 'storcli /%s add vd r%s Size=%s drives=%s' % (controller,
                                                                 raid_level,
                                                                 size,
                                                                 drives)
            print '----ankele---- create_raid args: ', args
            status, output = commands.getstatusoutput(args)
        return raid_config

    # ankele add 3rd
    def get_all_info(self):
        status, output = commands.getstatusoutput('storcli /call show J')
        if status != 0:
            print 'error in get_all_info'
        info = json.loads(output)
        return info

    # ankele add 3rd
    def get_controller(self):
        info = self.get_all_info()
        controller = info.get('Controllers')[0].get('Command Status').get('Controller')
        return 'c%s' % controller

    # ankele add 3rd
    def get_physical_disks(self, pd_count, size=None, raid_level=None):
        """ Get pd in order to the raid_level and size.
        If raid1, size of all pd must be same.
        If raid5, at least 3 pds.
        While there are spares, need more pd.
        """
        ret = []
        info = self.get_all_info()
        pd_list = info.get('Controllers')[0].get('Response Data').get('PD LIST')
        for pd in pd_list:
            if pd.get('State') != 'UGood':
                continue
            ret.append(pd.get('EID:Slt'))
        return ret[:pd_count]

三、准备部署镜像

准备一个centos7的虚拟机qcow2格式镜像,要求在此镜像中安装有 storcli 工具,最好是用户密码直接可以登录的。加入此qcow2镜像名称为 centos7.qcow2

xz -z centos7.qcow2 #生成 centos7.qcow2.xz
mv centos7.qcow2.xz CentOS-7-x86_64-7.qcow2.xz #修改名称

四、修改ipab工具

1.requirements

从https://opendev.org/openstack/requirements 或
从https://github.com.cnpmjs.org/openstack/requirements 下载
requirements
搞个本地git仓库,比如放在/home/git/git_repo/requirements.git/
修改
/usr/local/share/ironic-python-agent-builder/dib/ironic-python-agent-ramdisk/source-repository-requirements

requirements git /tmp/requirements https://opendev.org/openstack/requirements
改为
requirements git /tmp/requirements git@127.0.0.1:/home/git/git_repo/requirements.git

2.ipab

pip install ironic-python-agent-builder

在本地搞一个git仓库,比如放在/home/git/git_repo下,名称叫做ironic-python-agent.git
将地二步中修改的 hardware.py push到此仓库

编辑
/usr/local/share/ironic-python-agent-builder/dib/ironic-python-agent-ramdisk/source-repository-ironic-python-agent

ironic-python-agent git /tmp/ironic-python-agent https://opendev.org/openstack/ironic-python-agent

改为
ironic-python-agent git /tmp/ironic-python-agent git@127.0.0.1:/home/git/git_repo/ironic-python-agent.git

五、执行构建

创建一个脚本 before_build

export DIB_CLOUD_IMAGES=file:///root
export DIB_DEV_USER_USERNAME=demo
export DIB_DEV_USER_PWDLESS_SUDO=yes
export DIB_DEV_USER_PASSWORD=123456
export DIB_CLOUD_INIT_DATASOURCES="ConfigDrive,OpenStack"

cd /root
source before_build
mkdir my-ipa-7
cd !$
ironic-python-agent-builder -o my-ipa-7 -e stable-interface-names -e devuser --release 7 centos7 2>&1 | tee log

首次创建过程比较缓慢,大约需要一个小时。

六、创建完成后

访问http://{{prefix}}/baremetals/{{node_id}}/provision_state/来完成clean操作
参数传递为

{
    "target_state": "clean",
    "cleansteps": [
        {
            "interface": "raid",
            "step": "delete_configuration"
        },
        {
            "interface": "raid",
            "step": "create_configuration"
        }
    ],
    "target_raid_config": {
        "logical_disks": [
            {
                "size_gb": "8TB",
                "raid_level": "0",
                "controller": "c0", # 非必填
                "physical_disks": ["9:12", "9:13", "9:14"], # 非必填
                "is_root_volume": false, #非必填
                "pd_count": 3
            }
        ]
        "logical_disks": [{
            "size": "7TB",
            "raid_level": "5",
            "pd_count": 3
        }]
    }
}
 类似资料: