From e98736668fe92f74b1737f057aab8958150367a3 Mon Sep 17 00:00:00 2001 From: mgb01105731 Date: Mon, 6 Dec 2021 10:12:35 +0800 Subject: [PATCH] Add migration to Anolis 7.7 ; modify README.md --- README.md | 11 +- centos2anolis.py | 1115 ++++++++++++++++++++++++---------------------- 2 files changed, 594 insertions(+), 532 deletions(-) diff --git a/README.md b/README.md index dbb2fde..500118d 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This script is designed to automatically convert a CentOS instance to Anolis in- ## Supported versions -This script only supports switching CentOS Linux 8. It does not support CentOS Stream. +This script supports switching CentOS Linux 7 & 8. It does not support CentOS Stream. ## Before you switch @@ -20,6 +20,7 @@ Please ensure you have a **complete backup** of the system before you execute th ## Usage 1. Make sure you can run this script as root. +1. Make sure you have python3. 1. Either clone this repository or download [`centos2anolis.py`][2]. 1. Run `python3 centos2anolis.py -v * ` to start converting.`(* is the version of the anolis which you want)` @@ -44,11 +45,13 @@ Please ensure you have a **complete backup** of the system before you execute th The tool downloads packages from mirrors.openanolis.org by default, which could take a long time. This option intends to use mirrors.aliyun.com to speed up the process. -* `-v` The version of anolis8 +* `-v` The version of Anolis - The version of anolis8,like `8.2` or `8.4`.If you do not specify this parameter, the system prompts you to select. + The version of anolis , like `7.7` or `8.2` or `8.4`.If you do not specify this parameter, the system prompts you to select. - `Note that centos8.3/8.4 only supports migration to anolis8.4`. + * `Note that centos7.x only supports migration to anolis7.7`. + * `Note that centos8.0-8.2 supports migration to anolis8.2 or anolis8.4`. + * `Note that centos8.3/8.4 only supports migration to anolis8.4`. ## Support Open an issue on [bugs.openanolis.cn][1] for any bugs, questions and requirements. diff --git a/centos2anolis.py b/centos2anolis.py index bc7608f..ccb20da 100644 --- a/centos2anolis.py +++ b/centos2anolis.py @@ -1,528 +1,587 @@ -#!/usr/bin/env python3 -# Copyright (c) 2021 OpenAnolis Community. -# Licensed under the MIT license. -# -# Script to switch CentOS to the OpenAnolis yum repository. -# - -import os -import subprocess -import re -import dnf -import socket -import sys -import shutil -import argparse -import platform - -yum_url="https://mirrors.openanolis.org/anolis/" -github_url="http://codeup.openanolis.cn/codeup/migration/centos2anolis" -repostr_an8 = '''[an8_baseos] -name=AnolisOS-8 - BaseOS -baseurl=http://mirrors.openanolis.org/anolis/8/BaseOS/$basearch/os -gpgcheck=0 -enabled=1 - -[an8_appstream] -name=AnolisOS-8 - AppStream -baseurl=http://mirrors.openanolis.org/anolis/8/AppStream/$basearch/os -gpgcheck=0 -enabled=1 -''' - -old_packages = 'centos-backgrounds centos-logos centos-release centos-release-cr desktop-backgrounds-basic \ -centos-release-advanced-virtualization centos-release-ansible26 centos-release-ansible-27 \ -centos-release-ansible-28 centos-release-ansible-29 centos-release-azure \ -centos-release-ceph-jewel centos-release-ceph-luminous centos-release-ceph-nautilus \ -centos-release-ceph-octopus centos-release-configmanagement centos-release-dotnet centos-release-fdio \ -centos-release-gluster40 centos-release-gluster41 centos-release-gluster5 \ -centos-release-gluster6 centos-release-gluster7 centos-release-gluster8 \ -centos-release-gluster-legacy centos-release-messaging centos-release-nfs-ganesha28 \ -centos-release-nfs-ganesha30 centos-release-nfv-common \ -centos-release-nfv-openvswitch centos-release-openshift-origin centos-release-openstack-queens \ -centos-release-openstack-rocky centos-release-openstack-stein centos-release-openstack-train \ -centos-release-openstack-ussuri centos-release-opstools centos-release-ovirt42 centos-release-ovirt43 \ -centos-release-ovirt44 centos-release-paas-common centos-release-qemu-ev centos-release-qpid-proton \ -centos-release-rabbitmq-38 centos-release-samba411 centos-release-samba412 \ -centos-release-scl centos-release-scl-rh centos-release-storage-common \ -centos-release-virt-common centos-release-xen centos-release-xen-410 \ -centos-release-xen-412 centos-release-xen-46 centos-release-xen-48 centos-release-xen-common \ -libreport-centos libreport-plugin-mantisbt libreport-plugin-rhtsupport python3-syspurpose \ -python-oauth sl-logos yum-rhn-plugin centos-indexhtml' - -reposdir ='' -anolislist = ['8.2','8.4'] - - -def check_pkg(pkg): - if pkg.split('/')[0] == '': - if os.path.exists(pkg): - return True - else: - return False - - paths = os.environ['PATH'].split(':') - for path in paths: - if not os.path.isdir(path): - continue - for f in os.listdir(path): - if os.path.isfile(os.path.join(path, f)): - if f == pkg: - return True - return False - -def clean_and_exit(): - global reposdir - global repostr_an8 - repostr_an8 = re.sub(r"/(8.4)/", "/8/", repostr_an8) - - repo_path = os.path.join(reposdir, 'switch-to-anolis.repo') - if os.path.exists(repo_path): - os.remove(repo_path) - sys.exit(1) - -def get_disk_info(string): - dev_name = "" - part_name = "" - length = len(string) - for c in range(length-1, -1, -1): - if not string[c].isdigit(): - if string.find('nvme') != -1: - dev_name = string[0:c] - part_num = string[c+1:length] - else: - dev_name = string[0:c+1] - part_num = string[c+1:length] - break - return dev_name,part_num - -def add_boot_option(): - print("Current system is uefi, add boot option to boot manager.") - subprocess.run('which efibootmgr > /dev/null 2>&1 || dnf install -y efibootmgr', shell=True) - disk_name = subprocess.check_output('mount | grep /boot/efi | awk \'{print $1}\'', shell=True) - disk_name = str(disk_name, 'utf-8') - disk_name = disk_name.split('\n')[0] - dev_name,part_num = get_disk_info(disk_name) - if dev_name == "" or part_num == "": - print("Parse /boot/efi disk info failed, update boot loader failed.") - return - - cmd="" - arch = platform.machine() - if arch == "x86_64": - cmd = 'efibootmgr -c -d ' + dev_name + ' -p ' + part_num + ' -l "/EFI/anolis/shimx64.efi" -L "Anolis OS"' - elif arch == "aarch64": - cmd = 'efibootmgr -c -d ' + dev_name + ' -p ' + part_num + ' -l "/EFI/anolis/shimaa64.efi" -L "Anolis OS"' - try: - subprocess.check_call(cmd, shell=True) - except: - print("Use efibootmgr update boot loader failed, please update boot loader manually.") - -def change_repo_mirror(reposdir, prefix): - mirror_openanolis1 = "mirrors.openanolis.org" - mirror_openanolis2 = "mirrors.openanolis.cn" - mirror_aliyun="mirrors.aliyun.com" - - print("Accelerating downloads...") - anolis_repos = [] - files = os.listdir(reposdir) - for f in files: - repo_path=os.path.join(reposdir, f) - if os.path.isfile(repo_path): - if re.match(prefix, f): - #replace - with open(repo_path, 'r') as fr: - content = fr.read() - content = content.replace(mirror_openanolis1, mirror_aliyun).replace(mirror_openanolis2, mirror_aliyun) - with open(repo_path, 'w') as fw: - fw.writelines(content) - -def backup_repofiles(old_version): - global yum_url - - repos = [] - if re.match('centos-release-8\.*|centos-linux-release-8\.*', old_version): - old_version_r = subprocess.check_output('rpm -qa centos*repos', shell=True) - old_version_r = str(old_version_r, 'utf-8')[:-1] - old_version = old_version +" "+old_version_r - if len(old_version_r) != 0: - repos = subprocess.check_output("rpm -ql " + old_version_r + " | grep '\.repo$'", shell=True) - repos = str(repos, 'utf-8').split('\n')[:-1] - else: - repos = subprocess.check_output("rpm -ql centos-release | grep '\.repo$'", shell=True) - repos = str(repos, 'utf-8').split('\n')[:-1] - - num_centos_repos = subprocess.check_output('rpm -qa "centos-release-*" | wc -l', shell=True) - if int(str(num_centos_repos,'utf-8')[0]) > 0: - addtional_repos = subprocess.check_output('rpm -qla "centos-release-*"', shell=True) - addtional_repos = str(addtional_repos, 'utf-8') - if addtional_repos != '': - addtional_repos = addtional_repos.split('\n') - for r in addtional_repos: - if re.match('.*\.repo$', r): - repos.append(r) - - backup_comment = '# This is a yum repository file that was disabled by\n' \ - + '# ' + __file__+ ', a script to convert CentOS to Anolis.\n' \ - + '# Please see '+yum_url+' for more information.\n\n' - - for repo in repos: - if not os.path.isfile(repo): - continue - with open(repo, 'r') as fsrc: - content = fsrc.read() - with open(repo+'.disabled','w') as fdst: - fdst.write(repo+'\n'+backup_comment+content) - os.remove(repo) - return old_version - - -def check_version(version): - global repostr_an8 - - try: - centosv = str(subprocess.check_output("cat /etc/centos-release | awk '{print $4}'",shell=True),'utf-8')[:3] - print("centos version is " +centosv) - float(centosv) - except: - print("centos version not found or centos version is wrong type") - print("please check the file of centos-release") - sys.exit(1) - - if not version: - print("You have to set the version of anolis8") - print("The following version are enabled") - if float(centosv)>8.2: - print(' '.join(anolislist[1:])) - else: - print(' '.join(anolislist)) - version = str(input("Selected the version is : ")).strip() - if float(centosv) <=8.2 and version == "8.2" or version == "8": - print("You selected anolis8.2") - elif version == "8.4": - print("You selected anolis8.4") - repostr_an8 = re.sub(r"/(8)/","/8.4/",repostr_an8) - else: - print("version "+ version +" not found") - sys.exit(1) - elif version == "8.4": - print("You selected anolis8.4") - repostr_an8 = re.sub(r"/(8)/", "/8.4/", repostr_an8) - elif float(centosv) <=8.2 and version == "8.2" or version == "8": - print("You selected anolis8.2") - else: - print("version " + version + " not found") - print("The following version are enabled") - if float(centosv)>8.2: - print(' '.join(anolislist[1:])) - else: - print(' '.join(anolislist)) - sys.exit(1) - -def process_special_pkgs(): - print("swap centos-logos related packages with Anolis packages") - subprocess.run('rpm -q centos-logos-ipa && dnf swap -y centos-logos-ipa anolis-logos-ipa', shell=True) - subprocess.run('rpm -q centos-logos-httpd && dnf swap -y centos-logos-httpd anolis-logos-httpd', shell=True) - - print("redhat-lsb is replaced by system-lsb on Anolis") - subprocess.run('rpm -q redhat-lsb-core && dnf swap -y redhat-lsb-core system-lsb-core', shell=True) - subprocess.run('rpm -q redhat-lsb-submod-security && dnf swap -y redhat-lsb-submod-security system-lsb-submod-security',shell=True) - - print("rhn related packages is not provided by Anolis") - subprocess.run('rpm -q rhn-client-tools && dnf -y remove rhn-client-tools python3-rhn-client-tools python3-rhnlib', shell=True) - - print("subscription-manager related packages is not provided by Anolis") - subprocess.run('rpm -q subscription-manager && dnf -y remove subscription-manager', shell=True) - - print("python3-syspurpose is not provided by Anolis") - subprocess.run('rpm -q python3-syspurpose && dnf -y remove python3-syspurpose', shell=True) - - print("remove centos gpg-pubkey") - subprocess.run('rpm -e $(rpm -q gpg-pubkey --qf "%{NAME}-%{VERSION}-%{RELEASE} %{PACKAGER}\\n" | grep CentOS | awk \'{print $1}\')', shell=True) - - -def main(reinstall_all_rpms=False, verify_all_rpms=False, accelerate=False, version=False): - global reposdir - - print("Checking if the tool is executed by root user") - # check if the script is executed by root user - if os.geteuid() != 0: - print("Please run the tool as root user.") - sys.exit(1) - - print("Checking the version of anolis") - check_version(version) - - # check required packages - print('Checking required packages') - for pkg in ['rpm','yum','curl']: - if not check_pkg(pkg): - print("Could not found "+pkg) - sys.exit(1) - - # display rpms info before conversion - if verify_all_rpms: - print("Creating a list of RPMs installed before the switch") - print("Verifying RPMs installed before the switch against RPM database") - out1 = subprocess.check_output('rpm -qa --qf \ - "%{NAME}|%{VERSION}|%{RELEASE}|%{INSTALLTIME}|%{VENDOR}|%{BUILDTIME}|%{BUILDHOST}|%{SOURCERPM}|%{LICENSE}|%{PACKAGER}\\n" \ - | sort > "/var/tmp/$(hostname)-rpms-list-before.log"', shell=True) - out2 = subprocess.check_output('rpm -Va | sort -k3 > "/var/tmp/$(hostname)-rpms-verified-before.log"',shell=True) - files = os.listdir('/var/tmp/') - hostname = socket.gethostname() - print("Review the output of following files:") - for f in files: - if re.match(hostname+'-rpms-(.*)\.log', f): - print(f) - - # check if the os old_version is supported - print("========= Checking: distribution =========") - old_version = subprocess.check_output("rpm -q --whatprovides /etc/redhat-release", shell=True) - old_version = str(old_version, 'utf-8') - old_version = old_version.split('\n')[:-1] - if len(old_version) == 0: - print("You appear to be running an unsupported distribution.") - sys.exit(1) - if len(old_version) > 1: - print("Could not determine your distribution because multiple packages are providing redhat-release:") - print('\n'.join(old_version)) - sys.exit(1) - - old_version = old_version[0] - print(old_version) - if re.match('anolis-release', old_version): - print("You are already using Anolis.") - sys.exit(1) - - elif re.match('centos-linux-release', old_version): - subver = old_version.split('-')[3] - - elif re.match('redhat-release|centos-release|sl-release', old_version): - subver = old_version.split('-')[2] - - else: - print("Your are using an unsupported distribution.") - sys.exit(1) - - if not re.match('8',subver): - print("You appear to be running an unsupported distribution.") - sys.exit(1) - - print("========= Checking: required python packages =========") - if not check_pkg('/usr/libexec/platform-python'): - print('/usr/libexec/platform-python not found.') - sys.exit(1) - base_packages=['basesystem','initscripts','anolis-logos','plymouth','grub2','grubby'] - - print("========= Checking: yum lock ===========") - if os.path.exists('/var/run/yum.pid'): - with open('/var/run/yum.pid', 'r') as f: - pid = f.read() - with open('/proc/'+pid+'/comm', 'r') as ff: - comm = ff.read() - print('Another app is currently holding the yum lock: '+comm) - print('Running as pid: '+pid) - print('Please kill it and run the tool again.') - sys.exit(1) - - # check dnf - print("========= Checking: dnf =========") - print("Identifying dnf modules that are enabled...") - enabled_modules = str( - subprocess.check_output("dnf module list --enabled | grep rhel | awk '{print $1}'", shell=True), - 'utf-8') - enabled_modules = enabled_modules.split('\n')[:-1] - unknown_mods=[] - if len(enabled_modules) > 0: - for mod in enabled_modules: - if re.fullmatch('container-tools|llvm-toolset', mod): - subprocess.run('dnf module reset -y '+mod, shell=True) - if not re.fullmatch('container-tools|go-toolset|jmc|llvm-toolset|rust-toolset|virt', mod): - unknown_mods.append(mod) - if len(unknown_mods) > 0: - print('This tool is unable to automatically switch module(s) ' \ - + ','.join(unknown_mods) \ - + ' from a CentOS \'rhel\' stream to an Anolis equivalent.'\ - ) - opt = input('Do you want to continue and resolve it manually? (Yes or No)\n' + \ - 'You may want select No to stop and raise an issue on ' \ - + github_url \ - + ' for advice. '\ - ) - if opt != 'Yes': - sys.exit(1) - - print("========= Finding your repository directory =========") - dir = dnf.Base().conf.get_reposdir - if os.path.isdir(dir): - reposdir = dir - else: - print("repository directory not found") - sys.exit(1) - - if len(reposdir) == 0: - print("Could not locate your repository directory.") - sys.exit(1) - - repofile = os.path.join(reposdir, 'switch-to-anolis.repo') - with open(repofile, 'w') as f: - f.write(repostr_an8) - if accelerate: - change_repo_mirror(reposdir, 'switch-to-anolis.repo') - - print("========= Looking for yumdownloader ==========") - if not check_pkg('yumdownloader'): - subprocess.run("yum -y install yum-utils --disablerepo an* || true", shell=True) - if not check_pkg('yumdownloader'): - clean_and_exit() - - print("========= Start converting =========") - - print("Backing up and removing old repository files...") - old_version = backup_repofiles(old_version) - - print("Removing CentOS-specific yum configuration from /etc/yum.conf ...") - with open('/etc/yum.conf', 'r') as f: - content = f.read() - if re.search(r'^distroverpkg=', content, re.MULTILINE): - content = re.sub(r"\n(distroverpkg=)", r"\n#\1", content) - if re.search(r'bugtracker_url=', content, re.MULTILINE): - content = re.sub(r"\n(bugtracker_url=)", r"\n#\1", content) - with open('/etc/yum.conf', 'w') as f: - f.write(content) - - print("Downloading anolis release package...") - dst_release = ['anolis-release', 'anolis-repos', 'anolis-gpg-keys'] - try: - stat = subprocess.check_output("yumdownloader "+' '.join(dst_release), shell=True) - except Exception: - print("Could not download the following packages from " + yum_url) - print('\n'.join(dst_release)) - print() - print("Are you behind a proxy? If so, make sure the 'http_proxy' environmen") - print("variable is set with your proxy address.") - print("An error occurred while attempting to switch this system to Anolis" + \ - "and it may be in an unstable/unbootable state. To avoid further issues, " +\ - "the script has terminated.") - clean_and_exit() - - print("Switching old release package with Anolis...") - dst_rpms = [s+'*.rpm' for s in dst_release] - subprocess.run('rpm -i --force ' + ' '.join(dst_rpms) + ' --nodeps', shell=True) - subprocess.run('rpm -e --nodeps ' + old_version + ' centos-gpg-keys', shell=True) - os.remove(repofile) - # switch completed - - if accelerate: - change_repo_mirror(reposdir, 'AnolisOS-') - - print("Installing base packages for Anolis...") - cmd='yum shell -y < 0: - for mod in enabled_modules: - subprocess.run('dnf module reset -y '+mod, shell=True) - if re.fullmatch('container-tools|go-toolset|jmc|llvm-toolset|rust-toolset', mod): - subprocess.run('dnf module enable -y '+mod+':an8', shell=True) - elif mod =='virt': - subprocess.run('dnf module enable -y '+mod+':an', shell=True) - else: - print("Unsure how to transform module"+mod) - subprocess.run('dnf -y distro-sync', shell=True) - - try: - subprocess.check_call('dnf module list --enabled | grep satellite-5-client', shell=True) - print("Anolis does not provide satellite-5-client module, disable it.") - subprocess.run('dnf module disable -y satellite-5-client', shell=True) - except: - pass - - process_special_pkgs() - - if reinstall_all_rpms: - print("Testing for remaining CentOS RPMs") - centos_rpms = subprocess.check_output('rpm -qa --qf "%{NAME}-%{VERSION}-%{RELEASE} %{VENDOR}\n" \ - | grep CentOS | grep -v kernel | awk \'{print $1}\'', \ - shell=True) - centos_rpms = str(centos_rpms,'utf-8') - centos_rpms = centos_rpms.split('\n')[:-1] - if len(centos_rpms) > 0: - print("Reinstalling RPMs:") - print(' '.join(centos_rpms)) - subprocess.run('yum --assumeyes reinstall '+ ' '.join(centos_rpms), shell=True) - - non_anolis_rpms = subprocess.check_output('rpm -qa --qf "%{NAME}-%{VERSION}-%{RELEASE}|%{VENDOR}|%{PACKAGER}\\n" \ - |grep -v Anolis', shell=True) - non_anolis_rpms = str(non_anolis_rpms, 'utf-8') - non_anolis_rpms = non_anolis_rpms.split('\n')[:-1] - if len(non_anolis_rpms) > 0: - print("The following non-Anolis RPMs are installed on the system:") - print(' '.join(non_anolis_rpms)) - print("This may be expected of your environment and does not necessarily indicate a problem.") - print("If a large number of CentOS RPMs are included and you're unsure why please open an issue on " + github_url) - - print("Removing yum cache") - if os.path.isfile('/var/cache/yum'): - os.remove('/var/cache/yum') - elif os.path.isdir('/var/cache/yum'): - shutil.rmtree('/var/cache/yum') - if os.path.isfile('/var/cache/dnf'): - os.remove('/var/cache/dnf') - elif os.path.isdir('/var/cache/dnf'): - shutil.rmtree('/var/cache/dnf') - - if verify_all_rpms: - print("Creating a list of RPMs installed after the switch") - print("Verifying RPMs installed after the switch against RPM database") - out1 = subprocess.check_output('rpm -qa --qf \ - "%{NAME}|%{VERSION}|%{RELEASE}|%{INSTALLTIME}|%{VENDOR}|%{BUILDTIME}|%{BUILDHOST}|%{SOURCERPM}|%{LICENSE}|%{PACKAGER}\\n" \ - | sort > "/var/tmp/$(hostname)-rpms-list-after.log"', shell=True) - out2 = subprocess.check_output('rpm -Va | sort -k3 > "/var/tmp/$(hostname)-rpms-verified-after.log"',shell=True) - files = os.listdir('/var/tmp/') - hostname = socket.gethostname() - print("Review the output of following files:") - for f in files: - if re.match(hostname+'-rpms-(.*)\.log', f): - print(f) - - print("Sync successfully, update grub.cfg.") - if os.path.isdir('/sys/firmware/efi'): - subprocess.run('grub2-mkconfig -o /boot/efi/EFI/anolis/grub.cfg', shell=True) - add_boot_option() - else: - subprocess.run('grub2-mkconfig -o /boot/grub2/grub.cfg', shell=True) - - print("Switch complete. Anolis recommends rebooting this system.") - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument('-r', action='store_true', help='Reinstall all CentOS RPMs with Anolis RPMs (Note: This is not necessary for support)') - parser.add_argument('-V', action='store_true', help='Verify RPM information before and after the switch') - parser.add_argument('-s', action='store_true', help='Accelerate download') - parser.add_argument('-v', help='Choose the version of anolis8') - args = parser.parse_args() - sys.exit(main(args.r, args.V, args.s, args.v)) +#!/usr/bin/env python3 +# Copyright (c) 2021 OpenAnolis Community. +# Licensed under the MIT license. +# +# Script to switch CentOS to the OpenAnolis yum repository. +# + +import os +import subprocess +import re +import socket +import sys +import shutil +import argparse +import platform + +yum_url="https://mirrors.openanolis.org/anolis/" +github_url="http://codeup.openanolis.cn/codeup/migration/centos2anolis" +repostr_an7 = '''[an7_os] +name=AnolisOS-7 - OS +baseurl=http://mirrors.openanolis.org/anolis/7/os/$basearch/os +gpgcheck=0 +enabled=1 + +[an7_updates] +name=AnolisOS-7 - updates +baseurl=http://mirrors.openanolis.org/anolis/7/updates/$basearch/os +gpgcheck=0 +enabled=1 +''' +repostr_an8 = '''[an8_baseos] +name=AnolisOS-8 - BaseOS +baseurl=http://mirrors.openanolis.org/anolis/8/BaseOS/$basearch/os +gpgcheck=0 +enabled=1 + +[an8_appstream] +name=AnolisOS-8 - AppStream +baseurl=http://mirrors.openanolis.org/anolis/8/AppStream/$basearch/os +gpgcheck=0 +enabled=1 +''' + +old_packages = 'centos-backgrounds centos-logos centos-release centos-release-cr desktop-backgrounds-basic \ +centos-release-advanced-virtualization centos-release-ansible26 centos-release-ansible-27 \ +centos-release-ansible-28 centos-release-ansible-29 centos-release-azure \ +centos-release-ceph-jewel centos-release-ceph-luminous centos-release-ceph-nautilus \ +centos-release-ceph-octopus centos-release-configmanagement centos-release-dotnet centos-release-fdio \ +centos-release-gluster40 centos-release-gluster41 centos-release-gluster5 \ +centos-release-gluster6 centos-release-gluster7 centos-release-gluster8 \ +centos-release-gluster-legacy centos-release-messaging centos-release-nfs-ganesha28 \ +centos-release-nfs-ganesha30 centos-release-nfv-common \ +centos-release-nfv-openvswitch centos-release-openshift-origin centos-release-openstack-queens \ +centos-release-openstack-rocky centos-release-openstack-stein centos-release-openstack-train \ +centos-release-openstack-ussuri centos-release-opstools centos-release-ovirt42 centos-release-ovirt43 \ +centos-release-ovirt44 centos-release-paas-common centos-release-qemu-ev centos-release-qpid-proton \ +centos-release-rabbitmq-38 centos-release-samba411 centos-release-samba412 \ +centos-release-scl centos-release-scl-rh centos-release-storage-common \ +centos-release-virt-common centos-release-xen centos-release-xen-410 \ +centos-release-xen-412 centos-release-xen-46 centos-release-xen-48 centos-release-xen-common \ +libreport-centos libreport-plugin-mantisbt libreport-plugin-rhtsupport python3-syspurpose \ +python-oauth sl-logos yum-rhn-plugin centos-indexhtml' + +reposdir ='' +anolislist7 = ['7.7'] +anolislist8 = ['8.2','8.4'] +try: + centosv = str(subprocess.check_output("cat /etc/centos-release | awk '{print $4}'", shell=True), 'utf-8')[:3] + print("centos version is " + centosv) + float(centosv) +except: + print("centos version not found or centos version is wrong type") + print("please check the file of centos-release") + sys.exit(1) +centosversion=int(float(centosv)) + +def check_pkg(pkg): + if pkg.split('/')[0] == '': + if os.path.exists(pkg): + return True + else: + return False + + paths = os.environ['PATH'].split(':') + for path in paths: + if not os.path.isdir(path): + continue + for f in os.listdir(path): + if os.path.isfile(os.path.join(path, f)): + if f == pkg: + return True + return False + +def clean_and_exit(): + global reposdir + global repostr_an7 + global repostr_an8 + + if centosversion == 7: + repostr_an7 = re.sub(r"anolis/(.*)/", "anolis/7/", repostr_an7) + if centosversion == 8: + repostr_an8 = re.sub(r"anolis/(.*)/", "anolis/8/", repostr_an8) + + repo_path = os.path.join(reposdir, 'switch-to-anolis.repo') + if os.path.exists(repo_path): + os.remove(repo_path) + sys.exit(1) + +def get_disk_info(string): + dev_name = "" + part_name = "" + length = len(string) + for c in range(length-1, -1, -1): + if not string[c].isdigit(): + if string.find('nvme') != -1: + dev_name = string[0:c] + part_num = string[c+1:length] + else: + dev_name = string[0:c+1] + part_num = string[c+1:length] + break + return dev_name,part_num + +def add_boot_option(): + print("Current system is uefi, add boot option to boot manager.") + subprocess.run('which efibootmgr > /dev/null 2>&1 || yum install -y efibootmgr', shell=True) + disk_name = subprocess.check_output('mount | grep /boot/efi | awk \'{print $1}\'', shell=True) + disk_name = str(disk_name, 'utf-8') + disk_name = disk_name.split('\n')[0] + dev_name,part_num = get_disk_info(disk_name) + if dev_name == "" or part_num == "": + print("Parse /boot/efi disk info failed, update boot loader failed.") + return + + cmd="" + arch = platform.machine() + if arch == "x86_64": + cmd = 'efibootmgr -c -d ' + dev_name + ' -p ' + part_num + ' -l "/EFI/anolis/shimx64.efi" -L "Anolis OS"' + elif arch == "aarch64": + cmd = 'efibootmgr -c -d ' + dev_name + ' -p ' + part_num + ' -l "/EFI/anolis/shimaa64.efi" -L "Anolis OS"' + try: + subprocess.check_call(cmd, shell=True) + except: + print("Use efibootmgr update boot loader failed, please update boot loader manually.") + +def change_repo_mirror(reposdir, prefix): + mirror_openanolis1 = "mirrors.openanolis.org" + mirror_openanolis2 = "mirrors.openanolis.cn" + mirror_aliyun="mirrors.aliyun.com" + + print("Accelerating downloads...") + anolis_repos = [] + files = os.listdir(reposdir) + for f in files: + repo_path=os.path.join(reposdir, f) + if os.path.isfile(repo_path): + if re.match(prefix, f): + #replace + with open(repo_path, 'r') as fr: + content = fr.read() + content = content.replace(mirror_openanolis1, mirror_aliyun).replace(mirror_openanolis2, mirror_aliyun) + with open(repo_path, 'w') as fw: + fw.writelines(content) + +def backup_repofiles(old_version): + global yum_url + global centosversion + + repos = [] + if re.match('centos-release-'+str(centosversion)+'\.*|centos-linux-release-'+str(centosversion)+'\.*', old_version): + old_version_r = subprocess.check_output('rpm -qa centos*repos', shell=True) + old_version_r = str(old_version_r, 'utf-8')[:-1] + old_version = old_version +" "+old_version_r + if len(old_version_r) != 0: + repos = subprocess.check_output("rpm -ql " + old_version_r + " | grep '\.repo$'", shell=True) + repos = str(repos, 'utf-8').split('\n')[:-1] + else: + repos = subprocess.check_output("rpm -ql centos-release | grep '\.repo$'", shell=True) + repos = str(repos, 'utf-8').split('\n')[:-1] + + num_centos_repos = subprocess.check_output('rpm -qa "centos-release-*" | wc -l', shell=True) + if int(str(num_centos_repos,'utf-8')[0]) > 0: + addtional_repos = subprocess.check_output('rpm -qla "centos-release-*"', shell=True) + addtional_repos = str(addtional_repos, 'utf-8') + if addtional_repos != '': + addtional_repos = addtional_repos.split('\n') + for r in addtional_repos: + if re.match('.*\.repo$', r): + repos.append(r) + + backup_comment = '# This is a yum repository file that was disabled by\n' \ + + '# ' + __file__+ ', a script to convert CentOS to Anolis.\n' \ + + '# Please see '+yum_url+' for more information.\n\n' + + for repo in repos: + if not os.path.isfile(repo): + continue + with open(repo, 'r') as fsrc: + content = fsrc.read() + with open(repo+'.disabled','w') as fdst: + fdst.write(repo+'\n'+backup_comment+content) + os.remove(repo) + return old_version + +def check_version(version): + global repostr_an7 + global repostr_an8 + global centosv + + if float(centosv) == 7.0: + print("set 'setenforce 0' in centos 7.0") + subprocess.run('setenforce 0', shell=True) + + if not version: + print("You have to set the version of Anolis") + print("The following version are enabled") + if float(centosv)>8.2: + print(' '.join(anolislist8[1:])) + elif float(centosv)<8: + print(' '.join(anolislist7)) + else: + print(' '.join(anolislist8)) + version = str(input("Selected the version is : ")).strip() + if centosversion < 8 and version == "7.7": + print("You selected anolis7.7") + repostr_an7 = re.sub(r"/(7)/", "/7.7/", repostr_an7) + elif 8 <= float(centosv) <= 8.2 and version == "8.2": + print("You selected anolis8.2") + repostr_an8 = re.sub(r"/(8)/", "/8.2/", repostr_an8) + elif centosversion >= 8 and version == "8.4": + print("You selected anolis8.4") + repostr_an8 = re.sub(r"/(8)/", "/8.4/", repostr_an8) + else: + print("version " + version + " not found, Please Check!") + sys.exit(1) + elif centosversion < 8 and version == "7.7": + print("You selected anolis7.7") + repostr_an7 = re.sub(r"/(7)/", "/7.7/", repostr_an7) + elif 8 <= float(centosv) <= 8.2 and version == "8.2": + print("You selected anolis8.2") + repostr_an8 = re.sub(r"/(8)/", "/8.2/", repostr_an8) + elif centosversion >= 8 and version == "8.4": + print("You selected anolis8.4") + repostr_an8 = re.sub(r"/(8)/", "/8.4/", repostr_an8) + else: + print("version " + version + " not found,Please Check!") + print("The following version are enabled") + if float(centosv)>8.2: + print(' '.join(anolislist8[1:])) + elif float(centosv)<8: + print(' '.join(anolislist7)) + else: + print(' '.join(anolislist8)) + sys.exit(1) + +def process_special_pkgs(): + print("swap centos-logos related packages with Anolis packages") + subprocess.run('rpm -q centos-logos-ipa && yum swap -y centos-logos-ipa anolis-logos-ipa', shell=True) + subprocess.run('rpm -q centos-logos-httpd && yum swap -y centos-logos-httpd anolis-logos-httpd', shell=True) + + print("redhat-lsb is replaced by system-lsb on Anolis") + subprocess.run('rpm -q redhat-lsb-core && yum swap -y redhat-lsb-core system-lsb-core', shell=True) + subprocess.run('rpm -q redhat-lsb-submod-security && yum swap -y redhat-lsb-submod-security system-lsb-submod-security',shell=True) + + print("rhn related packages is not provided by Anolis") + subprocess.run('rpm -q rhn-client-tools && yum -y remove rhn-client-tools python3-rhn-client-tools python3-rhnlib', shell=True) + + print("subscription-manager related packages is not provided by Anolis") + subprocess.run('rpm -q subscription-manager && yum -y remove subscription-manager', shell=True) + + print("python3-syspurpose is not provided by Anolis") + subprocess.run('rpm -q python3-syspurpose && yum -y remove python3-syspurpose', shell=True) + + print("remove centos gpg-pubkey") + subprocess.run('rpm -e $(rpm -q gpg-pubkey --qf "%{NAME}-%{VERSION}-%{RELEASE} %{PACKAGER}\\n" | grep CentOS | awk \'{print $1}\')', shell=True) + +def yum_remove_pkg(): + # 7.0-7.1 + subprocess.run('rpm -q gnome-documents && yum -y remove gnome-documents', shell=True) + # 7.0-7.3 + # downgrade mythes-en & hyphen-en + subprocess.run("rpm -q mythes-en hyphen-en && yum -y downgrade mythes-en hyphen-en", shell=True) + subprocess.run("rpm -q cdparanoia-libs && yum -y downgrade cdparanoia-libs", shell=True) + subprocess.run("rpm -q libvirt-client && yum -y upgrade libvirt-client", shell=True) + subprocess.run("rpm -q gnome-packagekit* && yum -y upgrade gnome-packagekit*", shell=True) + subprocess.run("rpm -q libreoffice-langpack-en && yum -y upgrade libreoffice-langpack-en", shell=True) + subprocess.run("rpm -q unoconv && yum -y update unoconv", shell=True) + #7.0-7.1 remove centos-bookmarks + subprocess.run("rpm -q centos-bookmarks && yum -y remove centos-bookmarks", shell=True) + # remove kmod-kvdo + subprocess.run('rpm -q kmod-kvdo && yum -y remove kmod-kvdo', shell=True) + +def main(reinstall_all_rpms=False, verify_all_rpms=False, accelerate=False, version=False): + global reposdir + + print("Checking if the tool is executed by root user") + # check if the script is executed by root user + if os.geteuid() != 0: + print("Please run the tool as root user.") + sys.exit(1) + + print("Checking the version of anolis") + check_version(version) + + # check required packages + print('Checking required packages') + for pkg in ['rpm', 'yum', 'curl']: + if not check_pkg(pkg): + print("Could not found " + pkg) + sys.exit(1) + + if verify_all_rpms: + print("Creating a list of RPMs installed before the switch") + print("Verifying RPMs installed before the switch against RPM database") + out1 = subprocess.check_output('rpm -qa --qf \ + "%{NAME}|%{VERSION}|%{RELEASE}|%{INSTALLTIME}|%{VENDOR}|%{BUILDTIME}|%{BUILDHOST}|%{SOURCERPM}|%{LICENSE}|%{PACKAGER}\\n" \ + | sort > "/var/tmp/$(hostname)-rpms-list-before.log"', shell=True) + out2 = subprocess.check_output('rpm -Va | sort -k3 > "/var/tmp/$(hostname)-rpms-verified-before.log"',shell=True) + files = os.listdir('/var/tmp/') + hostname = socket.gethostname() + print("Review the output of following files:") + for f in files: + if re.match(hostname+'-rpms-(.*)\.log', f): + print(f) + + # check if the os old_version is supported + print("========= Checking: distribution =========") + old_version = subprocess.check_output("rpm -q --whatprovides /etc/redhat-release", shell=True) + old_version = str(old_version, 'utf-8') + old_version = old_version.split('\n')[:-1] + if len(old_version) == 0: + print("You appear to be running an unsupported distribution.") + sys.exit(1) + if len(old_version) > 1: + print("Could not determine your distribution because multiple packages are providing redhat-release:") + print('\n'.join(old_version)) + sys.exit(1) + + old_version = old_version[0] + print(old_version) + if re.match('anolis-release', old_version): + print("You are already using Anolis.") + sys.exit(1) + + elif re.match('centos-linux-release', old_version): + subver = old_version.split('-')[3] + + elif re.match('redhat-release|centos-release|sl-release', old_version): + subver = old_version.split('-')[2] + + else: + print("Your are using an unsupported distribution.") + sys.exit(1) + + if not re.match(str(centosversion),subver): + print("You appear to be running an unsupported distribution.") + sys.exit(1) + + base_packages=['basesystem','initscripts','anolis-logos','plymouth','grub2','grubby'] + + print("========= Checking: yum lock ===========") + if os.path.exists('/var/run/yum.pid'): + with open('/var/run/yum.pid', 'r') as f: + pid = f.read() + with open('/proc/' + pid + '/comm', 'r') as ff: + comm = ff.read() + print('Another app is currently holding the yum lock: ' + comm) + print('Running as pid: ' + pid) + print('Please kill it and run the tool again.') + sys.exit(1) + + if centosversion == 8: + # check dnf + print("========= Checking: dnf =========") + print("Identifying dnf modules that are enabled...") + enabled_modules = str( + subprocess.check_output("dnf module list --enabled | grep rhel | awk '{print $1}'", shell=True), + 'utf-8') + enabled_modules = enabled_modules.split('\n')[:-1] + unknown_mods = [] + if len(enabled_modules) > 0: + for mod in enabled_modules: + if re.fullmatch('container-tools|llvm-toolset', mod): + subprocess.run('dnf module reset -y ' + mod, shell=True) + if not re.fullmatch('container-tools|go-toolset|jmc|llvm-toolset|rust-toolset|virt', mod): + unknown_mods.append(mod) + if len(unknown_mods) > 0: + print('This tool is unable to automatically switch module(s) ' \ + + ','.join(unknown_mods) \ + + ' from a CentOS \'rhel\' stream to an Anolis equivalent.' \ + ) + opt = input('Do you want to continue and resolve it manually? (Yes or No)\n' + \ + 'You may want select No to stop and raise an issue on ' \ + + github_url \ + + ' for advice. ' \ + ) + if opt != 'Yes': + sys.exit(1) + + print("========= Finding your repository directory =========") + dir = '/etc/yum.repos.d/' + if os.path.isdir(dir): + reposdir = dir + else: + print("repository directory not found") + sys.exit(1) + + if len(reposdir) == 0: + print("Could not locate your repository directory.") + sys.exit(1) + + repofile = os.path.join(reposdir, 'switch-to-anolis.repo') + with open(repofile, 'w') as f: + if centosversion == 7: + repostr_an=repostr_an7 + else: + repostr_an=repostr_an8 + f.write(repostr_an) + if accelerate: + change_repo_mirror(reposdir, 'switch-to-anolis.repo') + + print("========= Looking for yumdownloader ==========") + if not check_pkg('yumdownloader'): + subprocess.run("yum -y install yum-utils --disablerepo an* || true", shell=True) + if not check_pkg('yumdownloader'): + clean_and_exit() + + print("========= Start converting =========") + + print("Backing up and removing old repository files...") + old_version = backup_repofiles(old_version) + + print("Removing CentOS-specific yum configuration from /etc/yum.conf ...") + with open('/etc/yum.conf', 'r') as f: + content = f.read() + if re.search(r'^distroverpkg=', content, re.MULTILINE): + content = re.sub(r"\n(distroverpkg=)", r"\n#\1", content) + if re.search(r'bugtracker_url=', content, re.MULTILINE): + content = re.sub(r"\n(bugtracker_url=)", r"\n#\1", content) + with open('/etc/yum.conf', 'w') as f: + f.write(content) + + print("Downloading anolis release package...") + dst_release = ['anolis-release', 'anolis-repos', 'anolis-gpg-keys'] + try: + stat = subprocess.check_output("yumdownloader "+' '.join(dst_release), shell=True) + except Exception: + print("Could not download the following packages from " + yum_url) + print('\n'.join(dst_release)) + print() + print("Are you behind a proxy? If so, make sure the 'http_proxy' environmen") + print("variable is set with your proxy address.") + print("An error occurred while attempting to switch this system to Anolis" + \ + "and it may be in an unstable/unbootable state. To avoid further issues, " +\ + "the script has terminated.") + clean_and_exit() + + print("Switching old release package with Anolis...") + dst_rpms = [s + '*.rpm' for s in dst_release] + subprocess.run('rpm -i --force ' + ' '.join(dst_rpms) + ' --nodeps', shell=True) + if centosversion ==7: + subprocess.run('rpm -e --nodeps ' + old_version, shell=True) + else: + subprocess.run('rpm -e --nodeps ' + old_version + ' centos-gpg-keys', shell=True) + os.remove(repofile) + # switch completed + + if accelerate: + change_repo_mirror(reposdir, 'AnolisOS-') + + print("Installing base packages for Anolis...") + subprocess.run('yum clean all', shell=True) + cmd = 'yum shell -y < 0: + for mod in enabled_modules: + subprocess.run('dnf module reset -y '+mod, shell=True) + if re.fullmatch('container-tools|go-toolset|jmc|llvm-toolset|rust-toolset', mod): + subprocess.run('dnf module enable -y '+mod+':an8', shell=True) + elif mod =='virt': + subprocess.run('dnf module enable -y '+mod+':an', shell=True) + else: + print("Unsure how to transform module"+mod) + subprocess.run('dnf -y distro-sync', shell=True) + + try: + subprocess.check_call('dnf module list --enabled | grep satellite-5-client', shell=True) + print("Anolis does not provide satellite-5-client module, disable it.") + subprocess.run('dnf module disable -y satellite-5-client', shell=True) + except: + pass + + process_special_pkgs() + + if reinstall_all_rpms: + print("Testing for remaining CentOS RPMs") + centos_rpms = subprocess.check_output('rpm -qa --qf "%{NAME}-%{VERSION}-%{RELEASE} %{VENDOR}\n" \ + | grep CentOS | grep -v kernel | awk \'{print $1}\'', \ + shell=True) + centos_rpms = str(centos_rpms,'utf-8') + centos_rpms = centos_rpms.split('\n')[:-1] + if len(centos_rpms) > 0: + print("Reinstalling RPMs:") + print(' '.join(centos_rpms)) + subprocess.run('yum --assumeyes reinstall '+ ' '.join(centos_rpms), shell=True) + + non_anolis_rpms = subprocess.check_output('rpm -qa --qf "%{NAME}-%{VERSION}-%{RELEASE}|%{VENDOR}|%{PACKAGER}\\n" \ + |grep -v Anolis', shell=True) + non_anolis_rpms = str(non_anolis_rpms, 'utf-8') + non_anolis_rpms = non_anolis_rpms.split('\n')[:-1] + if len(non_anolis_rpms) > 0: + print("The following non-Anolis RPMs are installed on the system:") + print(' '.join(non_anolis_rpms)) + print("This may be expected of your environment and does not necessarily indicate a problem.") + print("If a large number of CentOS RPMs are included and you're unsure why please open an issue on " + github_url) + + print("Removing yum cache") + if os.path.isfile('/var/cache/yum'): + os.remove('/var/cache/yum') + elif os.path.isdir('/var/cache/yum'): + shutil.rmtree('/var/cache/yum') + if centosversion ==8: + if os.path.isfile('/var/cache/dnf'): + os.remove('/var/cache/dnf') + elif os.path.isdir('/var/cache/dnf'): + shutil.rmtree('/var/cache/dnf') + + if verify_all_rpms: + print("Creating a list of RPMs installed after the switch") + print("Verifying RPMs installed after the switch against RPM database") + out1 = subprocess.check_output('rpm -qa --qf \ + "%{NAME}|%{VERSION}|%{RELEASE}|%{INSTALLTIME}|%{VENDOR}|%{BUILDTIME}|%{BUILDHOST}|%{SOURCERPM}|%{LICENSE}|%{PACKAGER}\\n" \ + | sort > "/var/tmp/$(hostname)-rpms-list-after.log"', shell=True) + out2 = subprocess.check_output('rpm -Va | sort -k3 > "/var/tmp/$(hostname)-rpms-verified-after.log"',shell=True) + files = os.listdir('/var/tmp/') + hostname = socket.gethostname() + print("Review the output of following files:") + for f in files: + if re.match(hostname+'-rpms-(.*)\.log', f): + print(f) + + print("Sync successfully, update grub.cfg.") + if os.path.isdir('/sys/firmware/efi'): + subprocess.run('grub2-mkconfig -o /boot/efi/EFI/anolis/grub.cfg', shell=True) + add_boot_option() + else: + subprocess.run('grub2-mkconfig -o /boot/grub2/grub.cfg', shell=True) + + print("Switch complete. Anolis recommends rebooting this system.") + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument('-r', action='store_true', help='Reinstall all CentOS RPMs with Anolis RPMs (Note: This is not necessary for support)') + parser.add_argument('-V', action='store_true', help='Verify RPM information before and after the switch') + parser.add_argument('-s', action='store_true', help='Accelerate download') + parser.add_argument('-v', help='Choose the version of Anolis') + args = parser.parse_args() + sys.exit(main(args.r, args.V, args.s, args.v)) + -- Gitee