Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/photon-os-installer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
run: |
POI_IMAGE_NAME=photon/installer:${{ github.sha }}
cd docker
docker build -t $POI_IMAGE_NAME --build-arg DOCKER_PROXY=dockerhub.artifactory.eng.vmware.com/ --build-context poi-helper=$(realpath $(pwd)/..) .
docker build -t $POI_IMAGE_NAME --build-context poi-helper=$(realpath $(pwd)/..) .
docker system prune -f

test:
Expand All @@ -37,6 +37,9 @@ jobs:
python -m pip install --upgrade pip
pip install -r requirements.txt # Ensure this file lists the necessary dependencies

- name: install pytest
run: pip install pytest

- name: Run Pytest
run: |
pytest -x tests/poi-container-test.py
Expand Down
51 changes: 45 additions & 6 deletions photon_installer/installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ class PartitionType(Enum):
BIOS = 5


RHEL_LIKES=["fedora", "rocky", "rhel", "centos"]


class Installer(object):
"""
Photon installer
Expand All @@ -66,6 +69,7 @@ class Installer(object):
'bootmode',
'disk',
'disks',
'dist',
'docker',
'dps',
'eject_cdrom',
Expand Down Expand Up @@ -93,6 +97,7 @@ class Installer(object):
'prepkgsinstallscripts',
'public_key',
'photon_docker_image',
'release_package',
'repos',
'search_path',
'setup_grub_script',
Expand Down Expand Up @@ -327,6 +332,10 @@ def _add_defaults(self, install_config):
else:
arch = install_config['arch']

if 'dist' not in install_config:
install_config['dist'] = "photon"
dist = install_config['dist']

# 'bootmode' mode
if 'bootmode' not in install_config:
if "x86_64" in arch:
Expand Down Expand Up @@ -371,7 +380,9 @@ def _add_defaults(self, install_config):

# add bootloader packages after bootmode set
if install_config['bootmode'] in ['dualboot', 'efi']:
packages.append('grub2-efi-image')
dist = install_config.get('dist', "photon")
if dist == "photon":
packages.append("grub2-efi-image")

# ansible needs python3 in the target
if 'ansible' in install_config:
Expand Down Expand Up @@ -450,7 +461,7 @@ def _add_defaults(self, install_config):

# define 'hostname' as 'photon-<RANDOM STRING>'
if "hostname" not in install_config or install_config['hostname'] == "":
install_config['hostname'] = f'photon-{secrets.randbelow(16 ** 12):12x}'
install_config['hostname'] = f"{dist}-{secrets.randbelow(16 ** 12):12x}"

# Set password if needed.
# Installer uses 'shadow_password' and optionally 'password'/'age'
Expand Down Expand Up @@ -1225,8 +1236,15 @@ def _initialize_system(self):
self.logger.error("Failed to initialize rpm DB")
self.exit_gracefully()

retval = self.tdnf.run(['install', 'filesystem'],
packages = ["filesystem"]
# in RHEL like OSes, "filesystem" will pull in a release package, like "fedora-release-basic".
# This can later conflict with any other release package if installed later
if 'release_package' in self.install_config:
packages.append(self.install_config['release_package'])

retval = self.tdnf.run(["install"] + packages,
repos=self.install_config['repos'], do_json=False)

if retval != 0:
self.logger.error("Failed to install filesystem rpm")
self.exit_gracefully()
Expand Down Expand Up @@ -1503,13 +1521,26 @@ def _install_packages(self):
"""
Install packages using tdnf command
"""
self._adjust_packages_based_on_selected_flavor()

if self.install_config['dist'] == "photon":
self._adjust_packages_based_on_selected_flavor()

selected_packages = self.install_config['packages']
state = 0
packages_to_install = {}
total_size = 0
stderr = None

dracut_conffile = None
if self.install_config['dist'] in RHEL_LIKES:
# make sure to build initramfs with hostonly="no" for a generic kernel
dracut_confdir = os.path.join(self.photon_root, "etc", "dracut.conf.d")
os.makedirs(dracut_confdir)
# Fedora sets hostonly="yes" in 01-dist.conf, override it
dracut_conffile = os.path.join(dracut_confdir, "01-dist-poi.conf")
with open(dracut_conffile, "wt") as f:
f.write(f'hostonly="no"\n')

if self.install_config['ui']:
tdnf_cmd = ("tdnf install -y --releasever {0} --installroot {1} "
"-c {2} --setopt=reposdir={3} "
Expand Down Expand Up @@ -1569,6 +1600,11 @@ def _install_packages(self):
self.logger.error(stderr.decode())
self.exit_gracefully()

# remove again, assuming kernel upgrades will be done in a real host using hostonly="yes"
if dracut_conffile is not None:
os.remove(dracut_conffile)


def _eject_cdrom(self):
"""
Eject the cdrom on request
Expand All @@ -1580,8 +1616,11 @@ def _enable_network_in_chroot(self):
"""
Enable network in chroot
"""
if os.path.exists("/etc/resolv.conf"):
shutil.copy("/etc/resolv.conf", self.photon_root + '/etc/.')
try:
if os.path.exists("/etc/resolv.conf"):
shutil.copy("/etc/resolv.conf", self.photon_root + '/etc/.')
except FileNotFoundError:
pass

def _deactivate_network_in_chroot(self):
"""
Expand Down
9 changes: 4 additions & 5 deletions photon_installer/modules/m_updatehostname.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ def execute(installer):
hostname_file = os.path.join(installer.photon_root, "etc/hostname")
hosts_file = os.path.join(installer.photon_root, "etc/hosts")

with open(hostname_file, "wb") as outfile:
outfile.write(hostname.encode())
with open(hostname_file, "wt") as fout:
fout.write(hostname)

pattern = r'(127\.0\.0\.1)(\s+)(localhost)\s*\Z'
replace = r'\1\2\3\n\1\2' + hostname
commons.replace_string_in_file(hosts_file, pattern, replace)
with open(hosts_file, "at") as fout:
fout.write(f"127.0.1.1 {hostname}\n")
30 changes: 20 additions & 10 deletions photon_installer/modules/m_updaterootpassword.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,29 @@
# * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-only
# */

import os
import commons
import os
import shutil


install_phase = commons.POST_INSTALL
enabled = True


def replace_passwd(filepath, passwd, user="root"):

filepath_tmp = f"{filepath}.tmp"
with open(filepath, "rt") as fin:
with open(filepath_tmp, "wt") as fout:
for line in fin:
l = line.split(":")
if l[0] == user:
l[1] = passwd
fout.write(":".join(l))
shutil.copystat(filepath, filepath_tmp)
os.rename(filepath_tmp, filepath)


def execute(installer):
shadow_password = installer.install_config['shadow_password']
installer.logger.info("Set root password")
Expand All @@ -18,19 +34,13 @@ def execute(installer):
shadow_filename = os.path.join(installer.photon_root, 'etc/shadow')

# replace root blank password in passwd file to point to shadow file
commons.replace_string_in_file(passwd_filename, "root::", "root:x:")
replace_passwd(passwd_filename, "x")

if not os.path.isfile(shadow_filename):
with open(shadow_filename, "w") as destination:
destination.write("root:" + shadow_password + ":")
destination.write(f"root:{shadow_password}:")
else:
# add password hash in shadow file
commons.replace_string_in_file(
shadow_filename, "root::", f"root:{shadow_password}:"
)
commons.replace_string_in_file(
shadow_filename, "root:x:", f"root:{shadow_password}:"
)
replace_passwd(shadow_filename, shadow_password)

installer.cmd.run_in_chroot(installer.photon_root, "/usr/sbin/pwconv")
installer.cmd.run_in_chroot(installer.photon_root, "/usr/sbin/grpconv")
Expand Down
Loading