Add lorax-composer and the composer kickstart templates

This commit is contained in:
Brian C. Lane 2018-05-03 09:14:11 -07:00
parent 9085840401
commit cb0158ca22
6 changed files with 833 additions and 0 deletions

View File

@ -0,0 +1,46 @@
# Lorax Composer filesystem output kickstart template
#
sshpw --username=root --plaintext randOmStrinGhERE
# Firewall configuration
firewall --enabled
# Root password
rootpw --plaintext removethispw
# Network information
network --bootproto=dhcp --onboot=on --activate
# System authorization information
auth --useshadow --enablemd5
# System keyboard
keyboard --xlayouts=us --vckeymap=us
# System language
lang en_US.UTF-8
# SELinux configuration
selinux --enforcing
# Installation logging level
logging --level=info
# Shutdown after installation
shutdown
# System timezone
timezone US/Eastern
# System bootloader configuration
bootloader --location=none
# Clear the Master Boot Record
zerombr
# Partition clearing information
clearpart --all
# Disk partitioning information
part / --fstype="ext4" --size=4000
part swap --size=1000
%post
# Remove root password
passwd -d root > /dev/null
# Remove random-seed
rm /var/lib/systemd/random-seed
%end
%packages --nobase
# NOTE lorax-composer will add the recipe packages below here, including the final %end

368
share/composer/live-iso.ks Normal file
View File

@ -0,0 +1,368 @@
# Lorax Composer Live ISO output kickstart template
#
sshpw --username=root --plaintext randOmStrinGhERE
# Firewall configuration
firewall --enabled --service=mdns
# X Window System configuration information
xconfig --startxonboot
# Root password
rootpw --plaintext removethispw
# Network information
network --bootproto=dhcp --onboot=on --activate
# System authorization information
auth --useshadow --enablemd5
# System keyboard
keyboard --xlayouts=us --vckeymap=us
# System language
lang en_US.UTF-8
# SELinux configuration
selinux --enforcing
# Installation logging level
logging --level=info
# Shutdown after installation
shutdown
# System services
services --disabled="network,sshd" --enabled="NetworkManager"
# System timezone
timezone US/Eastern
# System bootloader configuration
bootloader --location=mbr
# Clear the Master Boot Record
zerombr
# Partition clearing information
clearpart --all
# Disk partitioning information
%post
# FIXME: it'd be better to get this installed from a package
cat > /etc/rc.d/init.d/livesys << EOF
#!/bin/bash
#
# live: Init script for live image
#
# chkconfig: 345 00 99
# description: Init script for live image.
. /etc/init.d/functions
if ! strstr "\`cat /proc/cmdline\`" rd.live.image || [ "\$1" != "start" ]; then
exit 0
fi
if [ -e /.liveimg-configured ] ; then
configdone=1
fi
exists() {
which \$1 >/dev/null 2>&1 || return
\$*
}
touch /.liveimg-configured
# mount live image
if [ -b \`readlink -f /dev/live\` ]; then
mkdir -p /mnt/live
mount -o ro /dev/live /mnt/live 2>/dev/null || mount /dev/live /mnt/live
fi
livedir="LiveOS"
for arg in \`cat /proc/cmdline\` ; do
if [ "\${arg##live_dir=}" != "\${arg}" ]; then
livedir=\${arg##live_dir=}
return
fi
done
# enable swaps unless requested otherwise
swaps=\`blkid -t TYPE=swap -o device\`
if ! strstr "\`cat /proc/cmdline\`" noswap && [ -n "\$swaps" ] ; then
for s in \$swaps ; do
action "Enabling swap partition \$s" swapon \$s
done
fi
if ! strstr "\`cat /proc/cmdline\`" noswap && [ -f /mnt/live/\${livedir}/swap.img ] ; then
action "Enabling swap file" swapon /mnt/live/\${livedir}/swap.img
fi
mountPersistentHome() {
# support label/uuid
if [ "\${homedev##LABEL=}" != "\${homedev}" -o "\${homedev##UUID=}" != "\${homedev}" ]; then
homedev=\`/sbin/blkid -o device -t "\$homedev"\`
fi
# if we're given a file rather than a blockdev, loopback it
if [ "\${homedev##mtd}" != "\${homedev}" ]; then
# mtd devs don't have a block device but get magic-mounted with -t jffs2
mountopts="-t jffs2"
elif [ ! -b "\$homedev" ]; then
loopdev=\`losetup -f\`
if [ "\${homedev##/mnt/live}" != "\${homedev}" ]; then
action "Remounting live store r/w" mount -o remount,rw /mnt/live
fi
losetup \$loopdev \$homedev
homedev=\$loopdev
fi
# if it's encrypted, we need to unlock it
if [ "\$(/sbin/blkid -s TYPE -o value \$homedev 2>/dev/null)" = "crypto_LUKS" ]; then
echo
echo "Setting up encrypted /home device"
plymouth ask-for-password --command="cryptsetup luksOpen \$homedev EncHome"
homedev=/dev/mapper/EncHome
fi
# and finally do the mount
mount \$mountopts \$homedev /home
# if we have /home under what's passed for persistent home, then
# we should make that the real /home. useful for mtd device on olpc
if [ -d /home/home ]; then mount --bind /home/home /home ; fi
[ -x /sbin/restorecon ] && /sbin/restorecon /home
if [ -d /home/liveuser ]; then USERADDARGS="-M" ; fi
}
findPersistentHome() {
for arg in \`cat /proc/cmdline\` ; do
if [ "\${arg##persistenthome=}" != "\${arg}" ]; then
homedev=\${arg##persistenthome=}
return
fi
done
}
if strstr "\`cat /proc/cmdline\`" persistenthome= ; then
findPersistentHome
elif [ -e /mnt/live/\${livedir}/home.img ]; then
homedev=/mnt/live/\${livedir}/home.img
fi
# if we have a persistent /home, then we want to go ahead and mount it
if ! strstr "\`cat /proc/cmdline\`" nopersistenthome && [ -n "\$homedev" ] ; then
action "Mounting persistent /home" mountPersistentHome
fi
# make it so that we don't do writing to the overlay for things which
# are just tmpdirs/caches
mount -t tmpfs -o mode=0755 varcacheyum /var/cache/yum
mount -t tmpfs tmp /tmp
mount -t tmpfs vartmp /var/tmp
[ -x /sbin/restorecon ] && /sbin/restorecon /var/cache/yum /tmp /var/tmp >/dev/null 2>&1
if [ -n "\$configdone" ]; then
exit 0
fi
# add fedora user with no passwd
action "Adding live user" useradd \$USERADDARGS -c "Live System User" liveuser
passwd -d liveuser > /dev/null
# turn off firstboot for livecd boots
chkconfig --level 345 firstboot off 2>/dev/null
# We made firstboot a native systemd service, so it can no longer be turned
# off with chkconfig. It should be possible to turn it off with systemctl, but
# that doesn't work right either. For now, this is good enough: the firstboot
# service will start up, but this tells it not to run firstboot. I suspect the
# other services 'disabled' below are not actually getting disabled properly,
# with systemd, but we can look into that later. - AdamW 2010/08 F14Alpha
echo "RUN_FIRSTBOOT=NO" > /etc/sysconfig/firstboot
# don't start yum-updatesd for livecd boots
chkconfig --level 345 yum-updatesd off 2>/dev/null
# turn off mdmonitor by default
chkconfig --level 345 mdmonitor off 2>/dev/null
# turn off setroubleshoot on the live image to preserve resources
chkconfig --level 345 setroubleshoot off 2>/dev/null
# don't do packagekit checking by default
gconftool-2 --direct --config-source=xml:readwrite:/etc/gconf/gconf.xml.defaults -s -t string /apps/gnome-packagekit/update-icon/frequency_get_updates never >/dev/null
gconftool-2 --direct --config-source=xml:readwrite:/etc/gconf/gconf.xml.defaults -s -t string /apps/gnome-packagekit/update-icon/frequency_get_upgrades never >/dev/null
gconftool-2 --direct --config-source=xml:readwrite:/etc/gconf/gconf.xml.defaults -s -t string /apps/gnome-packagekit/update-icon/frequency_refresh_cache never >/dev/null
gconftool-2 --direct --config-source=xml:readwrite:/etc/gconf/gconf.xml.defaults -s -t bool /apps/gnome-packagekit/update-icon/notify_available false >/dev/null
gconftool-2 --direct --config-source=xml:readwrite:/etc/gconf/gconf.xml.defaults -s -t bool /apps/gnome-packagekit/update-icon/notify_distro_upgrades false >/dev/null
gconftool-2 --direct --config-source=xml:readwrite:/etc/gconf/gconf.xml.defaults -s -t bool /apps/gnome-packagekit/enable_check_firmware false >/dev/null
gconftool-2 --direct --config-source=xml:readwrite:/etc/gconf/gconf.xml.defaults -s -t bool /apps/gnome-packagekit/enable_check_hardware false >/dev/null
gconftool-2 --direct --config-source=xml:readwrite:/etc/gconf/gconf.xml.defaults -s -t bool /apps/gnome-packagekit/enable_codec_helper false >/dev/null
gconftool-2 --direct --config-source=xml:readwrite:/etc/gconf/gconf.xml.defaults -s -t bool /apps/gnome-packagekit/enable_font_helper false >/dev/null
gconftool-2 --direct --config-source=xml:readwrite:/etc/gconf/gconf.xml.defaults -s -t bool /apps/gnome-packagekit/enable_mime_type_helper false >/dev/null
# don't start cron/at as they tend to spawn things which are
# disk intensive that are painful on a live image
chkconfig --level 345 crond off 2>/dev/null
chkconfig --level 345 atd off 2>/dev/null
chkconfig --level 345 anacron off 2>/dev/null
chkconfig --level 345 readahead_early off 2>/dev/null
chkconfig --level 345 readahead_later off 2>/dev/null
# Stopgap fix for RH #217966; should be fixed in HAL instead
touch /media/.hal-mtab
# workaround clock syncing on shutdown that we don't want (#297421)
sed -i -e 's/hwclock/no-such-hwclock/g' /etc/rc.d/init.d/halt
# and hack so that we eject the cd on shutdown if we're using a CD...
if strstr "\`cat /proc/cmdline\`" CDLABEL= ; then
cat >> /sbin/halt.local << FOE
#!/bin/bash
# XXX: This often gets stuck during shutdown because /etc/init.d/halt
# (or something else still running) wants to read files from the block\
# device that was ejected. Disable for now. Bug #531924
# we want to eject the cd on halt, but let's also try to avoid
# io errors due to not being able to get files...
#cat /sbin/halt > /dev/null
#cat /sbin/reboot > /dev/null
#/usr/sbin/eject -p -m \$(readlink -f /dev/live) >/dev/null 2>&1
#echo "Please remove the CD from your drive and press Enter to finish restarting"
#read -t 30 < /dev/console
FOE
chmod +x /sbin/halt.local
fi
EOF
# bah, hal starts way too late
cat > /etc/rc.d/init.d/livesys-late << EOF
#!/bin/bash
#
# live: Late init script for live image
#
# chkconfig: 345 99 01
# description: Late init script for live image.
. /etc/init.d/functions
if ! strstr "\`cat /proc/cmdline\`" rd.live.image || [ "\$1" != "start" ] || [ -e /.liveimg-late-configured ] ; then
exit 0
fi
exists() {
which \$1 >/dev/null 2>&1 || return
\$*
}
touch /.liveimg-late-configured
# read some variables out of /proc/cmdline
for o in \`cat /proc/cmdline\` ; do
case \$o in
ks=*)
ks="--kickstart=\${o#ks=}"
;;
xdriver=*)
xdriver="\${o#xdriver=}"
;;
esac
done
# if liveinst or textinst is given, start anaconda
if strstr "\`cat /proc/cmdline\`" liveinst ; then
plymouth --quit
/usr/sbin/liveinst \$ks
fi
if strstr "\`cat /proc/cmdline\`" textinst ; then
plymouth --quit
/usr/sbin/liveinst --text \$ks
fi
# configure X, allowing user to override xdriver
if [ -n "\$xdriver" ]; then
cat > /etc/X11/xorg.conf.d/00-xdriver.conf <<FOE
Section "Device"
Identifier "Videocard0"
Driver "\$xdriver"
EndSection
FOE
fi
EOF
chmod 755 /etc/rc.d/init.d/livesys
/sbin/restorecon /etc/rc.d/init.d/livesys
/sbin/chkconfig --add livesys
chmod 755 /etc/rc.d/init.d/livesys-late
/sbin/restorecon /etc/rc.d/init.d/livesys-late
/sbin/chkconfig --add livesys-late
# work around for poor key import UI in PackageKit
rm -f /var/lib/rpm/__db*
rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-fedora
echo "Packages within this LiveCD"
rpm -qa
# go ahead and pre-make the man -k cache (#455968)
/usr/bin/mandb
# make sure there aren't core files lying around
rm -f /core*
# convince readahead not to collect
rm -f /.readahead_collect
touch /var/lib/readahead/early.sorted
# Remove random-seed
rm /var/lib/systemd/random-seed
%end
%post
cat >> /etc/rc.d/init.d/livesys << EOF
# disable screensaver locking
gconftool-2 --direct --config-source=xml:readwrite:/etc/gconf/gconf.xml.defaults -s -t bool /apps/gnome-screensaver/lock_enabled false >/dev/null
gconftool-2 --direct --config-source=xml:readwrite:/etc/gconf/gconf.xml.defaults -s -t bool /desktop/gnome/lockdown/disable_lock_screen true >/dev/null
# set up timed auto-login for after 60 seconds
cat >> /etc/gdm/custom.conf << FOE
[daemon]
AutomaticLoginEnable=True
AutomaticLogin=liveuser
FOE
# Show harddisk install on the desktop
sed -i -e 's/NoDisplay=true/NoDisplay=false/' /usr/share/applications/liveinst.desktop
mkdir /home/liveuser/Desktop
cp /usr/share/applications/liveinst.desktop /home/liveuser/Desktop
chown -R liveuser.liveuser /home/liveuser/Desktop
chmod a+x /home/liveuser/Desktop/liveinst.desktop
# But not trash and home
gconftool-2 --direct --config-source=xml:readwrite:/etc/gconf/gconf.xml.defaults -s -t bool /apps/nautilus/desktop/trash_icon_visible false >/dev/null
gconftool-2 --direct --config-source=xml:readwrite:/etc/gconf/gconf.xml.defaults -s -t bool /apps/nautilus/desktop/home_icon_visible false >/dev/null
# Turn off PackageKit-command-not-found while uninstalled
sed -i -e 's/^SoftwareSourceSearch=true/SoftwareSourceSearch=false/' /etc/PackageKit/CommandNotFound.conf
EOF
# Remove root password
passwd -d root > /dev/null
# fstab from the install won't match anything. remove it and let dracut
# handle mounting.
cat /dev/null > /etc/fstab
%end
# NOTE Do NOT add any other sections after %packages
%packages
# Packages requires to support this output format go here
isomd5sum
kernel
memtest86+
syslinux
-dracut-config-rescue
# This package is needed to boot the iso on UEFI
shim
shim-ia32
grub2
grub2-efi
grub2-efi-*-cdboot
grub2-efi-ia32
efibootmgr
# NOTE lorax-composer will add the recipe packages below here, including the final %end%packages

View File

@ -0,0 +1,53 @@
# Lorax Composer partitioned disk output kickstart template
#
sshpw --username=root --plaintext randOmStrinGhERE
# Firewall configuration
firewall --enabled
# Root password
rootpw --plaintext removethispw
# Network information
network --bootproto=dhcp --onboot=on --activate
# System authorization information
auth --useshadow --enablemd5
# System keyboard
keyboard --xlayouts=us --vckeymap=us
# System language
lang en_US.UTF-8
# SELinux configuration
selinux --enforcing
# Installation logging level
logging --level=info
# Shutdown after installation
shutdown
# System timezone
timezone US/Eastern
# System bootloader configuration
bootloader --location=mbr
# Clear the Master Boot Record
zerombr
# Partition clearing information
clearpart --all
%post
# Remove root password
passwd -d root > /dev/null
# Remove random-seed
rm /var/lib/systemd/random-seed
%end
%packages
kernel
-dracut-config-rescue
shim
shim-ia32
grub2
grub2-efi
grub2-efi-*-cdboot
grub2-efi-ia32
efibootmgr
# NOTE lorax-composer will add the recipe packages below here, including the final %end

53
share/composer/qcow2.ks Normal file
View File

@ -0,0 +1,53 @@
# Lorax Composer qcow2 output kickstart template
#
sshpw --username=root --plaintext randOmStrinGhERE
# Firewall configuration
firewall --enabled
# Root password
rootpw --plaintext removethispw
# Network information
network --bootproto=dhcp --onboot=on --activate
# System authorization information
auth --useshadow --enablemd5
# System keyboard
keyboard --xlayouts=us --vckeymap=us
# System language
lang en_US.UTF-8
# SELinux configuration
selinux --enforcing
# Installation logging level
logging --level=info
# Shutdown after installation
shutdown
# System timezone
timezone US/Eastern
# System bootloader configuration
bootloader --location=mbr
# Clear the Master Boot Record
zerombr
# Partition clearing information
clearpart --all
%post
# Remove root password
passwd -d root > /dev/null
# Remove random-seed
rm /var/lib/systemd/random-seed
%end
%packages
kernel
-dracut-config-rescue
shim
shim-ia32
grub2
grub2-efi
grub2-efi-*-cdboot
grub2-efi-ia32
efibootmgr
# NOTE lorax-composer will add the recipe packages below here, including the final %end

46
share/composer/tar.ks Normal file
View File

@ -0,0 +1,46 @@
# Lorax Composer tar output kickstart template
#
sshpw --username=root --plaintext randOmStrinGhERE
# Firewall configuration
firewall --enabled
# Root password
rootpw --plaintext removethispw
# Network information
network --bootproto=dhcp --onboot=on --activate
# System authorization information
auth --useshadow --enablemd5
# System keyboard
keyboard --xlayouts=us --vckeymap=us
# System language
lang en_US.UTF-8
# SELinux configuration
selinux --enforcing
# Installation logging level
logging --level=info
# Shutdown after installation
shutdown
# System timezone
timezone US/Eastern
# System bootloader configuration
bootloader --location=mbr
# Clear the Master Boot Record
zerombr
# Partition clearing information
clearpart --all
%post
# Remove root password
passwd -d root > /dev/null
# Remove random-seed
rm /var/lib/systemd/random-seed
%end
# NOTE Do NOT add any other sections after %packages
%packages
# Packages requires to support this output format go here
# NOTE lorax-composer will add the recipe packages below here, including the final %end

267
src/sbin/lorax-composer Executable file
View File

@ -0,0 +1,267 @@
#!/usr/bin/python3
#
# lorax-composer
#
# Copyright (C) 2017-2018 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import logging
log = logging.getLogger("lorax-composer")
program_log = logging.getLogger("program")
pylorax_log = logging.getLogger("pylorax")
server_log = logging.getLogger("server")
dnf_log = logging.getLogger("dnf")
import argparse
import grp
import os
import pwd
import sys
import subprocess
from threading import Lock
from gevent import socket
from gevent.wsgi import WSGIServer
from pylorax import vernum
from pylorax.api.config import configure, make_dnf_dirs, make_queue_dirs
from pylorax.api.queue import start_queue_monitor
from pylorax.api.recipes import open_or_create_repo, commit_recipe_directory
from pylorax.api.server import server, GitLock, DNFLock
from pylorax.api.dnfbase import get_base_object
VERSION = "{0}-{1}".format(os.path.basename(sys.argv[0]), vernum)
def get_parser():
""" Return the ArgumentParser for lorax-composer"""
parser = argparse.ArgumentParser(description="Lorax Composer API Server",
fromfile_prefix_chars="@")
parser.add_argument("--socket", default="/run/weldr/api.socket", metavar="SOCKET",
help="Path to the socket file to listen on")
parser.add_argument("--user", default="weldr", metavar="USER",
help="User to use for reduced permissions")
parser.add_argument("--group", default="weldr", metavar="GROUP",
help="Group to set ownership of the socket to")
parser.add_argument("--log", dest="logfile", default="/var/log/lorax-composer/composer.log", metavar="LOG",
help="Path to logfile (/var/log/lorax-composer/composer.log)")
parser.add_argument("--mockfiles", default="/var/tmp/bdcs-mockfiles/", metavar="MOCKFILES",
help="Path to JSON files used for /api/mock/ paths (/var/tmp/bdcs-mockfiles/)")
parser.add_argument("--sharedir", type=os.path.abspath, metavar="SHAREDIR",
help="Directory containing all the templates. Overrides config file sharedir")
parser.add_argument("-V", action="store_true", dest="showver",
help="show program's version number and exit")
parser.add_argument("-c", "--config", default="/etc/lorax/composer.conf", metavar="CONFIG",
help="Path to lorax-composer configuration file.")
parser.add_argument( "--releasever", default=None, metavar="STRING",
help="Release version to use for $releasever in dnf repository urls" )
parser.add_argument("BLUEPRINTS", metavar="BLUEPRINTS",
help="Path to the blueprints")
return parser
def setup_logging(logfile):
# Setup logging to console and to logfile
log.setLevel(logging.DEBUG)
pylorax_log.setLevel(logging.DEBUG)
sh = logging.StreamHandler()
sh.setLevel(logging.INFO)
fmt = logging.Formatter("%(asctime)s: %(message)s")
sh.setFormatter(fmt)
log.addHandler(sh)
pylorax_log.addHandler(sh)
fh = logging.FileHandler(filename=logfile)
fh.setLevel(logging.DEBUG)
fmt = logging.Formatter("%(asctime)s %(levelname)s %(name)s: %(message)s")
fh.setFormatter(fmt)
log.addHandler(fh)
pylorax_log.addHandler(fh)
# External program output log
program_log.setLevel(logging.DEBUG)
logfile = os.path.abspath(os.path.dirname(logfile))+"/program.log"
fh = logging.FileHandler(filename=logfile)
fh.setLevel(logging.DEBUG)
program_log.addHandler(fh)
# Server request logging
server_log.setLevel(logging.DEBUG)
logfile = os.path.abspath(os.path.dirname(logfile))+"/server.log"
fh = logging.FileHandler(filename=logfile)
fh.setLevel(logging.DEBUG)
server_log.addHandler(fh)
# DNF logging
dnf_log.setLevel(logging.DEBUG)
logfile = os.path.abspath(os.path.dirname(logfile))+"/dnf.log"
fh = logging.FileHandler(filename=logfile)
fh.setLevel(logging.DEBUG)
dnf_log.addHandler(fh)
class LogWrapper(object):
"""Wrapper for the WSGIServer which only calls write()"""
def __init__(self, log_obj):
self.log = log_obj
def write(self, msg):
"""Log everything as INFO"""
self.log.info(msg.strip())
def make_pidfile(pid_path="/run/lorax-composer.pid"):
"""Check for a running instance of lorax-composer
:param pid_path: Path to the pid file
:type pid_path: str
:returns: False if there is already a running lorax-composer, True otherwise
:rtype: bool
This will look for an existing pid file, and if found read the PID and check to
see if it is really lorax-composer running, or if it is a stale pid.
It will create a new pid file if there isn't already one, or if the PID is stale.
"""
if os.path.exists(pid_path):
try:
pid = int(open(pid_path, "r").read())
cmdline = open("/proc/%s/cmdline" % pid, "r").read()
if "lorax-composer" in cmdline:
return False
except (IOError, ValueError):
pass
open(pid_path, "w").write(str(os.getpid()))
return True
if __name__ == '__main__':
# parse the arguments
opts = get_parser().parse_args()
if opts.showver:
print(VERSION)
sys.exit(0)
logpath = os.path.abspath(os.path.dirname(opts.logfile))
if not os.path.isdir(logpath):
os.makedirs(logpath)
setup_logging(opts.logfile)
log.debug("opts=%s", opts)
if not make_pidfile():
log.error("PID file exists, lorax-composer already running. Quitting.")
sys.exit(1)
errors = []
# Check to make sure the user exists and get its uid
try:
uid = pwd.getpwnam(opts.user).pw_uid
except KeyError:
errors.append("Missing user '%s'" % opts.user)
# Check to make sure the group exists and get its gid
try:
gid = grp.getgrnam(opts.group).gr_gid
except KeyError:
errors.append("Missing group '%s'" % opts.group)
# No point in continuing if there are uid or gid errors
if errors:
for e in errors:
log.error(e)
sys.exit(1)
errors = []
# Check the socket path to make sure it exists, and that ownership and permissions are correct.
socket_dir = os.path.dirname(opts.socket)
if not os.path.exists(socket_dir):
# Create the directory and set permissions and ownership
os.makedirs(socket_dir, 0o750)
os.chown(socket_dir, 0, gid)
sockdir_stat = os.stat(socket_dir)
if sockdir_stat.st_mode & 0o007 != 0:
errors.append("Incorrect permissions on %s, no 'other' permissions are allowed." % socket_dir)
if sockdir_stat.st_gid != gid or sockdir_stat.st_uid != 0:
errors.append("%s should be owned by root:%s" % (socket_dir, opts.group))
# No point in continuing if there are ownership or permission errors
if errors:
for e in errors:
log.error(e)
sys.exit(1)
server.config["COMPOSER_CFG"] = configure(conf_file=opts.config)
# Make sure the git repo can be accessed by the API uid/gid
if os.path.exists(opts.BLUEPRINTS):
repodir_stat = os.stat(opts.BLUEPRINTS)
if repodir_stat.st_gid != gid or repodir_stat.st_uid != uid:
subprocess.call(["chown", "-R", "%s:%s" % (opts.user, opts.group), opts.BLUEPRINTS])
# If the user passed in a releasever set it in the configuration
if opts.releasever:
server.config["COMPOSER_CFG"].set("composer", "releasever", opts.releasever)
# Override the default sharedir
if opts.sharedir:
server.config["COMPOSER_CFG"].set("composer", "share_dir", opts.sharedir)
# Make sure the queue paths are setup correctly, exit on errors
errors = make_queue_dirs(server.config["COMPOSER_CFG"], gid)
if errors:
for e in errors:
log.error(e)
sys.exit(1)
# Setup the Unix Domain Socket, remove old one, set ownership and permissions
if os.path.exists(opts.socket):
os.unlink(opts.socket)
listener = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
listener.bind(opts.socket)
os.chmod(opts.socket, 0o660)
os.chown(opts.socket, 0, gid)
listener.listen(1)
start_queue_monitor(server.config["COMPOSER_CFG"], uid, gid)
# Drop root privileges on the main process
os.setgid(gid)
os.setuid(uid)
log.debug("user is now %s:%s", os.getresuid(), os.getresgid())
# Switch to a home directory we can access (libgit2 uses this to look for .gitconfig)
os.environ["HOME"] = server.config["COMPOSER_CFG"].get("composer", "lib_dir")
# Make sure dnf directories are created
make_dnf_dirs(server.config["COMPOSER_CFG"])
# Get a dnf.Base to share with the requests
dbo = get_base_object(server.config["COMPOSER_CFG"])
server.config["DNFLOCK"] = DNFLock(dbo=dbo, lock=Lock())
# Setup access to the git repo
server.config["REPO_DIR"] = opts.BLUEPRINTS
repo = open_or_create_repo(server.config["REPO_DIR"])
server.config["GITLOCK"] = GitLock(repo=repo, lock=Lock(), dir=opts.BLUEPRINTS)
# Import example blueprints
commit_recipe_directory(server.config["GITLOCK"].repo, "master", opts.BLUEPRINTS)
log.info("Starting %s on %s with blueprints from %s", VERSION, opts.socket, opts.BLUEPRINTS)
http_server = WSGIServer(listener, server, log=LogWrapper(server_log))
# The server writes directly to a file object, so point to our log directory
http_server.serve_forever()