toolkit/iso/py/util/iso_utils.py

318 lines
10 KiB
Python
Raw Normal View History

"""
Builds ISO's for Rocky Linux.
Louis Abel <label AT rockylinux.org>
"""
import logging
import sys
import os
import os.path
import subprocess
import shlex
import time
import re
2022-06-13 14:37:50 +00:00
from productmd.common import SortedConfigParser
from common import Color
2022-06-15 20:53:12 +00:00
from jinja2 import Environment, FileSystemLoader
class IsoBuild:
"""
This helps us build the generic ISO's for a Rocky Linux release. In
2022-06-15 20:53:12 +00:00
particular, this is for the boot images.
2022-06-15 20:53:12 +00:00
While there is a function for building the DVD and live images, this not
the main design of this class. The other functions can be called on their
own to facilitate those particular builds.
"""
def __init__(
self,
rlvars,
config,
major,
2022-06-16 19:24:19 +00:00
rc: bool = False,
2022-06-15 20:53:12 +00:00
isolation: str = 'auto',
compose_dir_is_here: bool = False,
image=None,
logger=None
):
self.image = image
2022-06-13 14:37:50 +00:00
self.fullname = rlvars['fullname']
2022-06-15 20:53:12 +00:00
self.distname = config['distname']
self.shortname = config['shortname']
# Relevant config items
self.major_version = major
2022-06-15 20:53:12 +00:00
self.compose_dir_is_here = compose_dir_is_here
2022-06-13 14:37:50 +00:00
self.disttag = config['dist']
self.date_stamp = config['date_stamp']
2022-06-13 14:37:50 +00:00
self.timestamp = time.time()
self.compose_root = config['compose_root']
self.compose_base = config['compose_root'] + "/" + major
2022-06-13 14:37:50 +00:00
self.iso_drop = config['compose_root'] + "/" + major + "/isos"
self.current_arch = config['arch']
2022-06-15 20:53:12 +00:00
self.required_pkgs = rlvars['iso_map']['required_pkgs']
self.mock_work_root = config['mock_work_root']
self.lorax_result_root = config['mock_work_root'] + "/" + "lorax"
self.mock_isolation = isolation
self.iso_map = rlvars['iso_map']
2022-06-16 19:24:19 +00:00
self.release_candidate = rc
# Relevant major version items
2022-06-15 20:53:12 +00:00
self.release = rlvars['revision']
self.minor_version = rlvars['revision'].split('.')[1]
self.revision = rlvars['revision'] + "-" + rlvars['rclvl']
2022-06-16 19:24:19 +00:00
self.rclvl = rlvars['rclvl']
2022-06-15 20:53:12 +00:00
self.repos = rlvars['iso_map']['repos']
self.repo_base_url = config['repo_base_url']
self.project_id = rlvars['project_id']
self.extra_files = rlvars['extra_files']
self.staging_dir = os.path.join(
config['staging_root'],
config['category_stub'],
self.revision
)
2022-06-15 20:53:12 +00:00
# Templates
file_loader = FileSystemLoader('templates')
self.tmplenv = Environment(loader=file_loader)
self.compose_latest_dir = os.path.join(
config['compose_root'],
major,
"latest-Rocky-{}".format(major)
)
self.compose_latest_sync = os.path.join(
self.compose_latest_dir,
"compose"
)
self.compose_log_dir = os.path.join(
self.compose_latest_dir,
"work/logs"
)
2022-06-15 20:53:12 +00:00
self.iso_work_dir = os.path.join(
self.compose_latest_dir,
"work/iso",
config['arch']
)
# This is temporary for now.
if logger is None:
self.log = logging.getLogger("iso")
self.log.setLevel(logging.INFO)
handler = logging.StreamHandler(sys.stdout)
handler.setLevel(logging.INFO)
formatter = logging.Formatter(
'%(asctime)s :: %(name)s :: %(message)s',
'%Y-%m-%d %H:%M:%S'
)
handler.setFormatter(formatter)
self.log.addHandler(handler)
self.log.info('iso build init')
2022-06-15 20:53:12 +00:00
self.repolist = self.build_repo_list()
self.log.info(self.revision)
def run(self):
work_root = os.path.join(
self.compose_latest_dir,
'work'
)
sync_root = self.compose_latest_sync
log_root = os.path.join(
work_root,
"logs"
)
2022-06-15 20:53:12 +00:00
self.iso_build()
self.log.info('Compose repo directory: %s' % sync_root)
self.log.info('ISO Build Logs: %s' % log_root)
self.log.info('ISO Build completed.')
2022-06-15 20:53:12 +00:00
def build_repo_list(self):
"""
2022-06-15 20:53:12 +00:00
Builds the repo dictionary
"""
2022-06-15 20:53:12 +00:00
repolist = []
for name in self.repos:
if not self.compose_dir_is_here:
constructed_url = '{}/{}/repo/hashed-{}/{}'.format(
self.repo_base_url,
self.project_id,
name,
self.current_arch
)
else:
constructed_url = 'file://{}/{}/{}/os'.format(
self.compose_latest_sync,
name,
self.current_arch
)
2022-06-15 20:53:12 +00:00
repodata = {
'name': name,
'url': constructed_url
}
repolist.append(repodata)
return repolist
2022-06-15 20:53:12 +00:00
def iso_build(self):
"""
2022-06-15 20:53:12 +00:00
This does the general ISO building for the current running
architecture. This generates the mock config and the general script
needed to get this part running.
"""
2022-06-15 20:53:12 +00:00
# Check for local build, build accordingly
# Check for arch specific build, build accordingly
# local AND arch cannot be used together, local supersedes. print
# warning.
self.generate_iso_scripts()
2022-06-17 05:55:07 +00:00
self.run_lorax()
2022-06-13 14:37:50 +00:00
def generate_iso_scripts(self):
"""
2022-06-17 05:55:07 +00:00
Generates the scripts needed to be ran to run lorax in mock as well as
package up the results.
2022-06-13 14:37:50 +00:00
"""
2022-06-16 19:24:19 +00:00
self.log.info('Generating ISO configuration and scripts')
2022-06-15 20:53:12 +00:00
mock_iso_template = self.tmplenv.get_template('isomock.tmpl.cfg')
mock_sh_template = self.tmplenv.get_template('isobuild.tmpl.sh')
iso_template = self.tmplenv.get_template('buildImage.tmpl.sh')
mock_iso_path = '/var/tmp/lorax-' + self.major_version + '.cfg'
mock_sh_path = '/var/tmp/isobuild.sh'
iso_template_path = '/var/tmp/buildImage.sh'
2022-06-16 19:24:19 +00:00
rclevel = ''
if self.release_candidate:
rclevel = '-' + self.rclvl
2022-06-15 20:53:12 +00:00
mock_iso_template_output = mock_iso_template.render(
arch=self.current_arch,
major=self.major_version,
fullname=self.fullname,
2022-06-17 05:55:07 +00:00
shortname=self.shortname,
2022-06-15 20:53:12 +00:00
required_pkgs=self.required_pkgs,
dist=self.disttag,
repos=self.repolist,
user_agent='{{ user_agent }}',
)
mock_sh_template_output = mock_sh_template.render(
arch=self.current_arch,
major=self.major_version,
isolation=self.mock_isolation,
builddir=self.mock_work_root,
shortname=self.shortname,
)
iso_template_output = iso_template.render(
arch=self.current_arch,
major=self.major_version,
minor=self.minor_version,
shortname=self.shortname,
repos=self.repolist,
variant=self.iso_map['variant'],
lorax=self.iso_map['lorax_removes'],
distname=self.distname,
revision=self.release,
2022-06-16 19:24:19 +00:00
rc=rclevel,
2022-06-17 05:55:07 +00:00
builddir=self.mock_work_root,
lorax_work_root=self.lorax_result_root,
2022-06-15 20:53:12 +00:00
)
mock_iso_entry = open(mock_iso_path, "w+")
mock_iso_entry.write(mock_iso_template_output)
mock_iso_entry.close()
mock_sh_entry = open(mock_sh_path, "w+")
mock_sh_entry.write(mock_sh_template_output)
mock_sh_entry.close()
iso_template_entry = open(iso_template_path, "w+")
iso_template_entry.write(iso_template_output)
iso_template_entry.close()
2022-06-13 14:37:50 +00:00
2022-06-17 05:55:07 +00:00
os.chmod(mock_sh_path, 0o755)
os.chmod(iso_template_path, 0o755)
def run_lorax(self):
"""
This actually runs lorax on this system. It will call the right scripts
to do so.
"""
lorax_cmd = '/bin/bash /var/tmp/isobuild.sh'
self.log.info('Starting lorax...')
try:
subprocess.call(shlex.split(lorax_cmd))
except:
self.log.error('An error occured during execution.')
self.log.error('See the logs for more information.')
raise SystemExit()
2022-06-15 20:53:12 +00:00
# !!! Send help, we would prefer to do this using the productmd python
# !!! library. If you are reading this and you can help us, please do so!
2022-06-13 14:37:50 +00:00
def treeinfo_write(self):
"""
Ensure treeinfo is written correctly
"""
print()
2022-06-15 20:53:12 +00:00
# !!! Send help, we would prefer to do this using the productmd python
# !!! library. If you are reading this and you can help us, please do so!
2022-06-13 14:37:50 +00:00
def discinfo_write(self):
"""
Ensure discinfo is written correctly
"""
#with open(file_path, "w") as f:
# f.write("%s\n" % self.timestamp)
# f.write("%s\n" % self.fullname)
# f.write("%s\n" % self.arch)
# if disc_numbers:
# f.write("%s\n" % ",".join([str(i) for i in disc_numbers]))
print()
def write_media_repo(self):
"""
Ensure media.repo exists
"""
data = [
"[InstallMedia]",
"name=%s" % self.fullname,
"mediaid=%s" % self.timestamp,
"metadata_expire=-1",
"gpgcheck=0",
"cost=500",
"",
]
2022-06-15 20:53:12 +00:00
def build_extra_iso(self):
"""
Builds DVD images based on the data created from the initial lorax on
each arch. This should NOT be called during the usual run() section.
"""
print()
2022-06-13 14:37:50 +00:00
def generate_graft_points(self):
"""
2022-06-15 20:53:12 +00:00
Get a list of packages for an extras ISO. This should NOT be called
during the usual run() section.
2022-06-13 14:37:50 +00:00
"""
print()
class LiveBuild:
"""
This helps us build the live images for Rocky Linux.
"""