diff --git a/isocut/isocut.py b/isocut/isocut.py
index bd946764558ec17ca30539e82fc6df116e4f48e9..c727c5fa85ffd68d0292fda68eee47e13216c6f1 100644
--- a/isocut/isocut.py
+++ b/isocut/isocut.py
@@ -12,7 +12,9 @@ PURPOSE.
See the Mulan PSL v2 for more details.
Author: zhuchunyi
Create: 2021-03-17
-Description: Used for iso tailoring at the rpm package level
+Description: Used for iso tailoring at the rpm package level.
+
+Updated by Octopus at 2023-07-26 : add product.xml support
"""
import argparse
@@ -24,6 +26,7 @@ import signal
import xml.etree.cElementTree as ET
import shlex
import traceback
+import re
# 工具清单
NECESSARY_TOOLS = (
@@ -80,6 +83,8 @@ class IConfig(object):
self.cache_path = "/var/run/isocut"
self.yum_conf = self.cache_path + "/yum.conf"
self.repo_conf = self.cache_path + "/repo.d/isocut.repo"
+ self.product_xml = None
+ self.verbose = False
self.mkdir_flag = False
self.src_iso = None
self.dest_iso = None
@@ -105,6 +110,8 @@ class IConfig(object):
@classmethod
def run_cmd(cls, cmd):
+ if ICONFIG.verbose:
+ print(cmd)
cmd = shlex.split(cmd)
res = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
sout = res.communicate()
@@ -136,7 +143,6 @@ def parse_old_treeinfo():
#treeinfo文件第3行为version信息
version_line = treeinfo_content[3].strip()
ICONFIG.old_version_number = version_line.split('=')[1].strip()
-
#treeinfo文件第6行为arch信息
version_line = treeinfo_content[6].strip()
ICONFIG.src_iso_arch = version_line.split('=')[1].strip()
@@ -203,20 +209,24 @@ def check_input():
parser.add_argument("dest_iso", help="destination iso image")
parser.add_argument("-temp", metavar="temporary_workspace", default="/tmp", help="temporary path")
parser.add_argument("-rpms", metavar="rpm_path", help="extern rpm packages path")
+ parser.add_argument("-xml", metavar="product_xml", help="provide an anaconda product.xml and disable rpmlist")
parser.add_argument("-install_pic", metavar="install_picture_path", help="install bg picture path")
parser.add_argument("-kickstart", metavar="kickstart_file_path", help="kickstart file path")
parser.add_argument("-product", metavar="product_name", help="product name")
parser.add_argument("-version", metavar="version_number", help="version number")
+ parser.add_argument("-verbose", action='store_true', default=False, help="print all cmdline")
args = parser.parse_args()
ICONFIG.src_iso = args.source_iso
ICONFIG.dest_iso = args.dest_iso
ICONFIG.temp_path = args.temp
ICONFIG.rpm_path = args.rpms
+ ICONFIG.product_xml = args.xml
ICONFIG.install_pic_path = args.install_pic
ICONFIG.ks_file = args.kickstart
ICONFIG.input_product_name = args.product
ICONFIG.input_version_number = args.version
+ ICONFIG.verbose = args.verbose
if ICONFIG.src_iso is None or ICONFIG.dest_iso is None:
print("Must specify source iso image and destination iso image")
@@ -227,6 +237,7 @@ def check_input():
return 3
if ICONFIG.rpm_path is not None:
+ print("RPM path is setted")
if not os.path.exists(ICONFIG.rpm_path):
print("RPM path do not exist!!")
return 3
@@ -364,15 +375,21 @@ def select_rpm():
ret = create_repo_conf()
if ret != 0:
return 5
-
- rpm_list_file = open(ICONFIG.config_rpm_list, "r+")
rpm_list = ""
- for line in rpm_list_file:
- if not (line is None or line.strip() == ""):
- rpm_list += " %s" % line[:-1].strip()
- cmd = "yumdownloader -y --resolve -c {0} --installroot {1} --destdir {2}/{3} {4}".format(
- ICONFIG.yum_conf, ICONFIG.cache_path, ICONFIG.temp_path_new_image,
- EXCLUDE_DIR_PACKAGES, rpm_list)
+ if ICONFIG.product_xml is None:
+ rpm_list_file = open(ICONFIG.config_rpm_list, "r+")
+ for line in rpm_list_file:
+ if not (line is None or line.strip() == ""):
+ rpm_list += " %s" % line[:-1].strip()
+ else:
+ with open(ICONFIG.product_xml, 'r') as file:
+ xml_content = file.read()
+ package_names = re.findall(r'(.*?)', xml_content)
+ rpm_list = ' '.join(package_names)
+ cmd = "dnf download -y --resolve --alldeps -c {0} --installroot {1} --destdir {2}/{3} \
+ --releasever {4} {5}".format(
+ ICONFIG.yum_conf, ICONFIG.cache_path, ICONFIG.temp_path_new_image, EXCLUDE_DIR_PACKAGES,
+ ICONFIG.old_version_number, rpm_list)
ret = ICONFIG.run_cmd(cmd)
if ret[0] != 0 or "conflicting requests" in ret[1]:
print("Select rpm failed!!")
@@ -401,45 +418,59 @@ def indent(elem, level=0):
def regen_repodata():
product_xml = ICONFIG.temp_path_new_image + \
"/" + EXCLUDE_DIR_REPODATA + "/product.xml"
- tree = ET.parse(ICONFIG.config_repodata_template)
- root = tree.getroot()
- packlist = root.find('group/packagelist')
- if packlist is None:
- print("Can't find packagelist, illegal template!!")
- return 6
- with open(ICONFIG.config_rpm_list) as fp_rpm:
- for line in fp_rpm:
- if line is None or line.strip() == "":
- continue
- pack = ET.SubElement(packlist, 'packagereq', type='default')
- pack.text = line[:-1].strip()
- if os.uname()[-1].strip() == 'x86_64':
- pack.text = pack.text.split(".x86_64")[0]
- elif os.uname()[-1].strip() == 'aarch64':
- pack.text = pack.text.split(".aarch64")[0]
- elif os.uname()[-1].strip() == 'loongarch64':
- pack.text = pack.text.split(".loongarch64")[0]
- pack.text = pack.text.split(".noarch")[0]
- fp_rpm.close()
-
- indent(root)
- tree.write(product_xml, encoding="UTF-8", xml_declaration=True)
- with open(product_xml, 'r+') as f_product:
- contents = f_product.readlines()
- contents.insert(1,
- "\n")
- contents_str = "".join(contents)
- f_product.seek(0, 0)
- f_product.write(contents_str)
- f_product.close()
- cmd = "createrepo -g {0} {1}".format(product_xml, ICONFIG.temp_path_new_image)
- ret = ICONFIG.run_cmd(cmd)
- if ret[0] != 0:
- print("Regenerate repodata failed!!")
- print(ret[1])
- return 6
-
+ if ICONFIG.product_xml is None:
+ tree = ET.parse(ICONFIG.config_repodata_template)
+ root = tree.getroot()
+ packlist = root.find('group/packagelist')
+ if packlist is None:
+ print("Can't find packagelist, illegal template!!")
+ return 6
+ with open(ICONFIG.config_rpm_list) as fp_rpm:
+ for line in fp_rpm:
+ if line is None or line.strip() == "":
+ continue
+ pack = ET.SubElement(packlist, 'packagereq', type='default')
+ pack.text = line[:-1].strip()
+ if os.uname()[-1].strip() == 'x86_64':
+ pack.text = pack.text.split(".x86_64")[0]
+ elif os.uname()[-1].strip() == 'aarch64':
+ pack.text = pack.text.split(".aarch64")[0]
+ elif os.uname()[-1].strip() == 'loongarch64':
+ pack.text = pack.text.split(".loongarch64")[0]
+ pack.text = pack.text.split(".noarch")[0]
+ fp_rpm.close()
+
+ indent(root)
+ tree.write(product_xml, encoding="UTF-8", xml_declaration=True)
+ with open(product_xml, 'r+') as f_product:
+ contents = f_product.readlines()
+ contents.insert(1,
+ "\n")
+ contents_str = "".join(contents)
+ f_product.seek(0, 0)
+ f_product.write(contents_str)
+ f_product.close()
+ cmd = "createrepo -g {0} {1}".format(product_xml, ICONFIG.temp_path_new_image)
+ ret = ICONFIG.run_cmd(cmd)
+ if ret[0] != 0:
+ print("Regenerate repodata failed!!")
+ print(ret[1])
+ return 6
+ else:
+ with open(ICONFIG.product_xml, 'r+') as f_product:
+ contents = f_product.readlines()
+ contents_str = "".join(contents)
+ with open(product_xml, 'w+') as tmp_product:
+ tmp_product.seek(0, 0)
+ tmp_product.write(contents_str)
+ tmp_product.close()
+ cmd = "createrepo -g {0} {1}".format(ICONFIG.product_xml, ICONFIG.temp_path_new_image)
+ ret = ICONFIG.run_cmd(cmd)
+ if ret[0] != 0:
+ print("createrepo_with_product_xml failed!!")
+ print(ret[1])
+ return 6
return 0
# 检查裁剪的ISO所需的rpm包的依赖关系
@@ -626,14 +657,14 @@ def replace_kickstart_file():
return 13
if os.uname()[-1].strip() == 'x86_64':
- sed_cmd = r"sed -i '/append/ s/$/ inst.ks=cdrom:\/dev\/cdrom:\/" + KS_NAME + \
+ sed_cmd = r"sed -i '/append/ s/$/ inst.ks=hd:LABEL=" + ICONFIG.new_iso_name + ":\/" + KS_NAME + \
" inst.multilib/g' " + ICONFIG.temp_path_new_image + "/" + ISOLINUX_CFG
ret = ICONFIG.run_cmd(sed_cmd)
if ret[0] != 0:
print("Set kickstart file failed!!")
return 13
- sed_cmd = r"sed -i '/inst.stage2/ s/$/ inst.ks=cdrom:\/dev\/cdrom:\/" + KS_NAME + \
+ sed_cmd = r"sed -i '/inst.stage2/ s/$/ inst.ks=hd:LABEL=" + ICONFIG.new_iso_name + ":\/" + KS_NAME + \
" inst.multilib/g' " + ICONFIG.temp_path_new_image + "/" + EFILINUX_CFG
ret = ICONFIG.run_cmd(sed_cmd)
if ret[0] != 0:
@@ -682,6 +713,8 @@ def add_checksum():
return 0
def add_sha256sum():
+ cmd = "chmod 666 {0}".format(ICONFIG.dest_iso)
+ ret = ICONFIG.run_cmd(cmd)
cmd = "sha256sum {0}".format(ICONFIG.dest_iso)
ret = ICONFIG.run_cmd(cmd)
if ret[0] != 0:
@@ -693,6 +726,7 @@ def add_sha256sum():
return 0
def do_clean():
+ print('Clean intermediate file...')
cmd = "umount {old}".format(old=ICONFIG.temp_path_old_image)
ret = ICONFIG.run_cmd(cmd)
if ret[0] != 0:
diff --git a/isocut/product.xml.example b/isocut/product.xml.example
new file mode 100644
index 0000000000000000000000000000000000000000..2ab9e22e6d62c8dcb901125438e9eee9dcc59832
--- /dev/null
+++ b/isocut/product.xml.example
@@ -0,0 +1,234 @@
+
+
+
+
+ core
+ Core
+ 核心
+ Smallest possible installation
+ 最小安装
+ true
+ false
+
+ audit
+ kernel
+ basesystem
+ bash
+ coreutils
+ cronie
+ curl
+ dnf
+ e2fsprogs
+ filesystem
+ firewalld
+ glibc
+ grubby
+ hostname
+ initscripts
+ iproute
+ iprutils
+ iputils
+ irqbalance
+ kbd
+ kexec-tools
+ less
+ man-db
+ ncurses
+ openssh
+ openssh-server
+ openssh-clients
+ openEuler-release
+ openEuler-latest-release
+ parted
+ passwd
+ policycoreutils
+ procps-ng
+ rng-tools
+ rootfiles
+ rpm
+ selinux-policy-targeted
+ setup
+ shadow
+ sssd
+ sudo
+ systemd
+ tuned
+ util-linux
+ vim-minimal
+ xfsprogs
+ yum
+ wget
+ NetworkManager
+ NetworkManager-config-server
+ authselect
+ dnf-plugins-core
+ dracut-config-rescue
+ kernel-tools
+ sysfsutils
+ linux-firmware
+ lshw
+ lsscsi
+ rsyslog
+ security-tool
+ sg3_utils
+ dracut-config-generic
+ dracut-network
+ rdma-core
+ selinux-policy-mls
+
+
+
+ base
+ Base
+ 基本
+ The standard installation.
+ true
+ false
+
+ acl
+ at
+ attr
+ bc
+ cpio
+ crontabs
+ cyrus-sasl
+ dbus
+ ed
+ file
+ iptstate
+ irqbalance
+ kpatch
+ logrotate
+ lsof
+ net-tools
+ pciutils
+ psacct
+ quota
+ openEuler-release
+ openEuler-latest-release
+ sudo
+ symlinks
+ systemd-udev
+ tar
+ tree
+ util-linux-user
+ bash-completion
+ bpftool
+ bzip2
+ chrony
+ cockpit
+ cryptsetup
+ dos2unix
+ dosfstools
+ ethtool
+ gnupg2
+ libstoragemgmt
+ lvm2
+ mailcap
+ man-pages
+ mdadm
+ mlocate
+ mtr
+ nano
+ realmd
+ rng-tools
+ rsync
+ smartmontools
+ sssd
+ strace
+ libteam
+ time
+ unzip
+ usbutils
+ virt-what
+ which
+ words
+ xfsdump
+ zip
+ cifs-utils
+ cockpit-doc
+ ima-evm-utils
+ nfs-utils
+ traceroute
+ zsh
+
+
+
+ ukui
+ UKUI
+ UKUI桌面环境
+ UKUI desktop environment
+ UKUI桌面环境
+ false
+ false
+
+ ukui
+ nodejs-packaging
+
+
+
+ anaconda-tools
+ Anaconda tools
+ Anaconda 工具
+
+ false
+ false
+
+ lorax
+ chrony
+ cryptsetup
+ device-mapper-multipath
+ dosfstools
+ dracut-network
+ e2fsprogs
+ efibootmgr
+ fcoe-utils
+ firewalld
+ gfs2-utils
+ glibc-all-langpacks
+ grub2-efi-x64
+ grub2-efi-x64-cdboot
+ grub2-tools
+ grub2-tools-extra
+ iscsi-initiator-utils
+ lvm2
+ mdadm
+ realmd
+ shim
+ libteam
+ tmux
+ xfsprogs
+ authselect-compat
+ kdump-anaconda-addon
+
+
+
+ product
+ Product
+ 产品基础包
+ Product base.
+ 产品基础包。
+ 5
+
+ base
+ core
+
+
+ ukui
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+