701ced5ddb
Apply diff anaconda-21.48.21-1..anaconda-22.20.13-1
558 lines
20 KiB
Python
Executable File
558 lines
20 KiB
Python
Executable File
#!/usr/bin/python2
|
|
#vim: set fileencoding=utf8
|
|
# parse-kickstart - read a kickstart file and emit equivalent dracut boot args
|
|
#
|
|
# Designed to run inside the dracut initramfs environment.
|
|
# Requires python 2.7 or later.
|
|
#
|
|
#
|
|
# Copyright © 2012-2014 Red Hat, Inc.
|
|
#
|
|
# This copyrighted material is made available to anyone wishing to use,
|
|
# modify, copy, or redistribute it subject to the terms and conditions of
|
|
# the GNU General Public License v.2, or (at your option) any later version.
|
|
# This program is distributed in the hope that it will be useful, but WITHOUT
|
|
# ANY WARRANTY expressed or implied, including the implied warranties 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, write to the
|
|
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
|
|
# source code or documentation are not subject to the GNU General Public
|
|
# License and may only be used or replicated with the express permission of
|
|
# Red Hat, Inc.
|
|
#
|
|
# Authors:
|
|
# Will Woods <wwoods@redhat.com>
|
|
|
|
import sys, os
|
|
import logging
|
|
import shutil
|
|
import uuid
|
|
import glob
|
|
from pykickstart.parser import KickstartParser, preprocessKickstart
|
|
from pykickstart.sections import NullSection
|
|
from pykickstart.version import returnClassForVersion
|
|
from pykickstart.errors import KickstartError
|
|
# pylint: disable=wildcard-import
|
|
from pykickstart.constants import *
|
|
from pykickstart import commands
|
|
from collections import OrderedDict
|
|
|
|
# Default logging: none
|
|
log = logging.getLogger('parse-kickstart').addHandler(logging.NullHandler())
|
|
|
|
# Helper function for reading simple files in /sys
|
|
def readsysfile(f):
|
|
'''Return the contents of f, or "" if missing.'''
|
|
try:
|
|
val = open(f).readline().strip()
|
|
except IOError:
|
|
val = ""
|
|
return val
|
|
|
|
def read_cmdline(f):
|
|
'''Returns an OrderedDict containing key-value pairs from a file with
|
|
boot arguments (e.g. /proc/cmdline).'''
|
|
args = OrderedDict()
|
|
try:
|
|
lines = open(f).readlines()
|
|
except IOError:
|
|
lines = []
|
|
# pylint: disable=redefined-outer-name
|
|
for line in lines:
|
|
for arg in line.split():
|
|
k,_e,v = arg.partition("=")
|
|
args[k] = v
|
|
return args
|
|
|
|
proc_cmdline = read_cmdline("/proc/cmdline")
|
|
|
|
# Here are the kickstart commands we care about:
|
|
|
|
class Cdrom(commands.cdrom.FC3_Cdrom):
|
|
def dracut_args(self, args, lineno, obj):
|
|
return "inst.repo=cdrom"
|
|
|
|
class HardDrive(commands.harddrive.FC3_HardDrive):
|
|
def dracut_args(self, args, lineno, obj):
|
|
if self.biospart:
|
|
return "inst.repo=bd:%s:%s" % (self.partition, self.dir)
|
|
else:
|
|
return "inst.repo=hd:%s:%s" % (self.partition, self.dir)
|
|
|
|
class NFS(commands.nfs.FC6_NFS):
|
|
def dracut_args(self, args, lineno, obj):
|
|
if self.opts:
|
|
method = "nfs:%s:%s:%s" % (self.opts, self.server, self.dir)
|
|
else:
|
|
method="nfs:%s:%s" % (self.server, self.dir)
|
|
|
|
# Spaces on the cmdline need to be '\ '
|
|
method = method.replace(" ", "\\ ")
|
|
return "inst.repo=%s" % method
|
|
|
|
class URL(commands.url.F18_Url):
|
|
def dracut_args(self, args, lineno, obj):
|
|
# Spaces in the url need to be %20
|
|
if self.url:
|
|
method = self.url.replace(" ", "%20")
|
|
else:
|
|
method = None
|
|
|
|
args = ["inst.repo=%s" % method]
|
|
|
|
if self.noverifyssl:
|
|
args.append("rd.noverifyssl")
|
|
if self.proxy:
|
|
args.append("proxy=%s" % self.proxy)
|
|
|
|
return "\n".join(args)
|
|
|
|
class Updates(commands.updates.F7_Updates):
|
|
def dracut_args(self, args, lineno, obj):
|
|
if self.url == "floppy":
|
|
return "live.updates=/dev/fd0"
|
|
elif self.url:
|
|
return "live.updates=%s" % self.url
|
|
|
|
class MediaCheck(commands.mediacheck.FC4_MediaCheck):
|
|
def dracut_args(self, args, lineno, obj):
|
|
if self.mediacheck:
|
|
return "rd.live.check"
|
|
|
|
class DriverDisk(commands.driverdisk.F14_DriverDisk):
|
|
def dracut_args(self, args, lineno, obj):
|
|
dd_net = []
|
|
dd_disk = []
|
|
for dd in self.driverdiskList:
|
|
if dd.partition:
|
|
dd_disk.append(dd.partition)
|
|
elif dd.source:
|
|
dd_net.append("inst.dd=%s" % dd.source)
|
|
|
|
# disk sources cannot be added to cmdline because the initial
|
|
# driver-update run has already finished.
|
|
if dd_disk:
|
|
with open("/tmp/dd_args_ks", "w") as f:
|
|
f.write(" ".join(dd_disk))
|
|
|
|
# network sources can be added to the existing cmdline, they
|
|
# are processed later.
|
|
return "\n".join(dd_net)
|
|
|
|
class Network(commands.network.F22_Network):
|
|
def dracut_args(self, args, lineno, net):
|
|
'''
|
|
NOTE: The first 'network' line get special treatment:
|
|
* '--activate' is always enabled
|
|
* '--device' is optional (defaults to the 'ksdevice=' boot arg)
|
|
* the device gets brought online in initramfs
|
|
'''
|
|
netline = None
|
|
|
|
# first 'network' line
|
|
if len(self.network) == 1:
|
|
# Setting only hostname in kickstart
|
|
if not net.device and net.hostname and not self.handler.ksdevice:
|
|
return None
|
|
net.activate = True
|
|
if net.device == "link" or not net.device:
|
|
# NOTE: this might still be empty (e.g. 'ks=file:...')
|
|
# XXX FIXME: handle "link" properly?
|
|
log.debug("Using ksdevice %s for missing --device in first kickstart network command", self.handler.ksdevice)
|
|
net.device = self.handler.ksdevice
|
|
# tell dracut to bring this device up
|
|
netline = ksnet_to_dracut(args, lineno, net, bootdev=True)
|
|
else:
|
|
# all subsequent 'network' lines require '--device'
|
|
if not net.device or net.device == "link":
|
|
log.error("'%s': missing --device", " ".join(args))
|
|
return
|
|
|
|
# write ifcfg so NM will set up the device correctly later
|
|
ksnet_to_ifcfg(net)
|
|
|
|
return netline
|
|
|
|
class DisplayMode(commands.displaymode.FC3_DisplayMode):
|
|
def dracut_args(self, args, lineno, obj):
|
|
if self.displayMode == DISPLAY_MODE_CMDLINE:
|
|
return "inst.cmdline"
|
|
elif self.displayMode == DISPLAY_MODE_TEXT:
|
|
return "inst.text"
|
|
elif self.displayMode == DISPLAY_MODE_GRAPHICAL:
|
|
return "inst.graphical"
|
|
|
|
class Bootloader(commands.bootloader.F21_Bootloader):
|
|
def dracut_args(self, args, lineno, obj):
|
|
if self.extlinux:
|
|
return "extlinux"
|
|
|
|
# TODO: keymap, lang... device? selinux?
|
|
|
|
dracutCmds = {
|
|
'cdrom': Cdrom,
|
|
'harddrive': HardDrive,
|
|
'nfs': NFS,
|
|
'url': URL,
|
|
'updates': Updates,
|
|
'mediacheck': MediaCheck,
|
|
'driverdisk': DriverDisk,
|
|
'network': Network,
|
|
'cmdline': DisplayMode,
|
|
'graphical': DisplayMode,
|
|
'text': DisplayMode,
|
|
'bootloader': Bootloader,
|
|
}
|
|
handlerclass = returnClassForVersion()
|
|
class DracutHandler(handlerclass):
|
|
def __init__(self):
|
|
handlerclass.__init__(self, commandUpdates=dracutCmds)
|
|
self.output = []
|
|
self.ksdevice = None
|
|
def dispatcher(self, args, lineno):
|
|
obj = handlerclass.dispatcher(self, args, lineno)
|
|
# and execute any specified dracut_args
|
|
cmd = args[0]
|
|
# the commands member is implemented by the class returned
|
|
# by returnClassForVersion
|
|
# pylint: disable=no-member
|
|
command = self.commands[cmd]
|
|
if hasattr(command, "dracut_args"):
|
|
log.debug("kickstart line %u: handling %s", lineno, cmd)
|
|
self.output.append(command.dracut_args(args, lineno, obj))
|
|
return obj
|
|
|
|
def init_logger(level=None):
|
|
if level is None and 'rd.debug' in proc_cmdline:
|
|
level = logging.DEBUG
|
|
logfmt = "%(name)s %(levelname)s: %(message)s"
|
|
logging.basicConfig(format=logfmt, level=level)
|
|
logger = logging.getLogger('parse-kickstart')
|
|
return logger
|
|
|
|
def is_mac(addr):
|
|
return addr and len(addr) == 17 and addr.count(":") == 5 # good enough
|
|
|
|
def find_devname(mac):
|
|
for netif in os.listdir("/sys/class/net"):
|
|
thismac = readsysfile("/sys/class/net/%s/address" % netif)
|
|
if thismac.lower() == mac.lower():
|
|
return netif
|
|
|
|
def s390_settings(device):
|
|
cfg = {
|
|
'SUBCHANNELS': '',
|
|
'NETTYPE': '',
|
|
'OPTIONS': ''
|
|
}
|
|
|
|
subchannels = []
|
|
for symlink in sorted(glob.glob("/sys/class/net/%s/device/cdev[0-9]*" % device)):
|
|
subchannels.append(os.path.basename(os.readlink(symlink)))
|
|
if not subchannels:
|
|
return cfg
|
|
cfg['SUBCHANNELS'] = ','.join(subchannels)
|
|
|
|
## cat /etc/ccw.conf
|
|
#qeth,0.0.0900,0.0.0901,0.0.0902,layer2=0,portname=FOOBAR,portno=0
|
|
#
|
|
#SUBCHANNELS="0.0.0900,0.0.0901,0.0.0902"
|
|
#NETTYPE="qeth"
|
|
#OPTIONS="layer2=1 portname=FOOBAR portno=0"
|
|
with open('/etc/ccw.conf') as f:
|
|
# pylint: disable=redefined-outer-name
|
|
for line in f:
|
|
if cfg['SUBCHANNELS'] in line:
|
|
items = line.strip().split(',')
|
|
cfg['NETTYPE'] = items[0]
|
|
cfg['OPTIONS'] = " ".join(i for i in items[1:] if '=' in i)
|
|
break
|
|
|
|
return cfg
|
|
|
|
def ksnet_to_dracut(args, lineno, net, bootdev=False):
|
|
'''Translate the kickstart network data into dracut network data.'''
|
|
# pylint: disable=redefined-outer-name
|
|
line = []
|
|
ip=""
|
|
autoconf=""
|
|
|
|
if is_mac(net.device): # this is a MAC - find the interface name
|
|
mac = net.device
|
|
net.device = find_devname(mac)
|
|
if net.device is None: # iface not active - pick a name for it
|
|
net.device = "ksdev0" # we only get called once, so this is OK
|
|
line.append("ifname=%s:%s" % (net.device, mac.lower()))
|
|
|
|
# NOTE: dracut currently only does ipv4 *or* ipv6, so only one ip=arg..
|
|
if net.bootProto in (BOOTPROTO_DHCP, BOOTPROTO_BOOTP):
|
|
autoconf="dhcp"
|
|
elif net.bootProto == BOOTPROTO_IBFT:
|
|
autoconf="ibft"
|
|
elif net.bootProto == BOOTPROTO_QUERY:
|
|
log.error("'%s': --bootproto=query is deprecated", " ".join(args))
|
|
elif net.bootProto == BOOTPROTO_STATIC:
|
|
req = ("gateway", "netmask", "nameserver", "ip")
|
|
missing = ", ".join("--%s" % i for i in req if not hasattr(net, i))
|
|
if missing:
|
|
log.warn("line %u: network missing %s", lineno, missing)
|
|
else:
|
|
ip="{0.ip}::{0.gateway}:{0.netmask}:" \
|
|
"{0.hostname}:{0.device}:none:{0.mtu}".format(net)
|
|
elif net.ipv6 == "auto":
|
|
autoconf="auto6"
|
|
elif net.ipv6 == "dhcp":
|
|
autoconf="dhcp6"
|
|
elif net.ipv6:
|
|
ip="[{0.ipv6}]::{0.ipv6gateway}:{0.netmask}:" \
|
|
"{0.hostname}:{0.device}:none:{0.mtu}".format(net)
|
|
|
|
if autoconf:
|
|
if net.device or net.mtu:
|
|
ip="%s:%s:%s" % (net.device, autoconf, net.mtu)
|
|
else:
|
|
ip=autoconf
|
|
|
|
if ip:
|
|
line.append("ip=%s" % ip)
|
|
|
|
for ns in net.nameserver.split(","):
|
|
if ns:
|
|
line.append("nameserver=%s" % ns)
|
|
|
|
if bootdev:
|
|
if net.device:
|
|
line.append("bootdev=%s" % net.device)
|
|
# touch /tmp/net.ifaces to make sure dracut brings up network
|
|
open("/tmp/net.ifaces", "a")
|
|
|
|
if net.essid or net.wepkey or net.wpakey:
|
|
# TODO: make dracut support wireless? (do we care?)
|
|
log.error("'%s': dracut doesn't support wireless networks",
|
|
" ".join(args))
|
|
|
|
return " ".join(line)
|
|
|
|
def add_s390_settings(dev, ifcfg):
|
|
s390cfg = s390_settings(dev)
|
|
if s390cfg['SUBCHANNELS']:
|
|
ifcfg.pop('HWADDR', None)
|
|
ifcfg['SUBCHANNELS'] = s390cfg['SUBCHANNELS']
|
|
if s390cfg['NETTYPE']:
|
|
ifcfg['NETTYPE'] = s390cfg['NETTYPE']
|
|
if s390cfg['OPTIONS']:
|
|
ifcfg['OPTIONS'] = s390cfg['OPTIONS']
|
|
|
|
def ksnet_to_ifcfg(net, filename=None):
|
|
'''Write an ifcfg file for the given kickstart network config'''
|
|
dev = net.device
|
|
if is_mac(dev):
|
|
dev = find_devname(dev)
|
|
if not dev:
|
|
return
|
|
if (not os.path.isdir("/sys/class/net/%s" % dev)
|
|
and not net.bondslaves and not net.teamslaves and not net.bridgeslaves):
|
|
log.info("can't find device %s", dev)
|
|
return
|
|
ifcfg = dict()
|
|
if filename is None:
|
|
filename = "/tmp/ifcfg/ifcfg-%s" % dev
|
|
if not os.path.isdir("/tmp/ifcfg"):
|
|
os.makedirs("/tmp/ifcfg")
|
|
ifcfg['DEVICE'] = dev
|
|
hwaddr = readsysfile("/sys/class/net/%s/address" % dev)
|
|
if "ifname={0}:{1}".format(dev, hwaddr).upper() in open("/proc/cmdline").read().upper():
|
|
# rename by initscript's 60-net-rules on target system after switchroot
|
|
ifcfg['HWADDR'] = hwaddr
|
|
ifcfg['UUID'] = str(uuid.uuid4())
|
|
# we set real ONBOOT value in anaconda, here
|
|
# we use it to activate devcies by NM on start
|
|
ifcfg['ONBOOT'] = "yes" if net.activate else "no"
|
|
|
|
add_s390_settings(dev, ifcfg)
|
|
|
|
# dhcp etc.
|
|
ifcfg['BOOTPROTO'] = net.bootProto
|
|
if net.bootProto == 'static':
|
|
ifcfg['IPADDR'] = net.ip
|
|
ifcfg['NETMASK'] = net.netmask
|
|
ifcfg['GATEWAY'] = net.gateway
|
|
if net.bootProto == 'dhcp':
|
|
if net.hostname:
|
|
ifcfg['DHCP_HOSTNAME'] = net.hostname
|
|
|
|
# ipv6 settings
|
|
if net.noipv6:
|
|
ifcfg['IPV6INIT'] = "no"
|
|
else:
|
|
ifcfg['IPV6INIT'] = "yes"
|
|
|
|
if net.ipv6 == 'dhcp':
|
|
ifcfg['DHCPV6C'] = "yes"
|
|
ifcfg['IPV6_AUTOCONF'] = "no"
|
|
if net.ipv6gateway:
|
|
ifcfg['IPV6_DEFAULTGW'] = net.ipv6gateway
|
|
elif net.ipv6 == 'auto':
|
|
ifcfg['IPV6_AUTOCONF'] = "yes" # NOTE: redundant (this is the default)
|
|
elif ':' in net.ipv6:
|
|
ifcfg['IPV6ADDR'] = net.ipv6
|
|
ifcfg['IPV6_AUTOCONF'] = "no"
|
|
|
|
# misc stuff
|
|
if net.mtu:
|
|
ifcfg['MTU'] = net.mtu
|
|
if net.nameserver:
|
|
for i, ip in enumerate(net.nameserver.split(",")):
|
|
ifcfg["DNS%d" % (i+1)] = ip
|
|
if net.nodefroute:
|
|
ifcfg['DEFROUTE'] = "no"
|
|
|
|
# TODO: dhcpclass, ethtool, essid/wepkey/wpakay, etc.
|
|
|
|
if net.bootProto == 'dhcp':
|
|
srcpath = "/tmp/dhclient.%s.lease" % dev
|
|
dstdir = "/tmp/ifcfg-leases"
|
|
dstpath = "%s/dhclient-%s-%s.lease" % (dstdir, ifcfg['UUID'], dev)
|
|
if os.path.exists(srcpath):
|
|
if not os.path.isdir(dstdir):
|
|
os.makedirs(dstdir)
|
|
shutil.copyfile(srcpath, dstpath)
|
|
|
|
if net.bondslaves:
|
|
ifcfg.pop('HWADDR', None)
|
|
ifcfg['TYPE'] = "Bond"
|
|
ifcfg['BONDING_MASTER'] = "yes"
|
|
ifcfg['NAME'] = "Bond connection %s" % dev
|
|
if ';' in net.bondopts:
|
|
sep = ";"
|
|
else:
|
|
sep = ","
|
|
ifcfg['BONDING_OPTS'] = '"' + " ".join(net.bondopts.split(sep)) + '"'
|
|
|
|
for i, slave in enumerate(net.bondslaves.split(","), 1):
|
|
slave_ifcfg = {
|
|
'TYPE' : "Ethernet",
|
|
'NAME' : "%s slave %s" % (dev, i),
|
|
'UUID' : str(uuid.uuid4()),
|
|
'ONBOOT' : "yes",
|
|
'MASTER' : ifcfg['UUID'],
|
|
'HWADDR' : readsysfile("/sys/class/net/%s/address" % slave),
|
|
}
|
|
add_s390_settings(slave, slave_ifcfg)
|
|
slave_filename = "/tmp/ifcfg/ifcfg-%s" % "_".join(slave_ifcfg['NAME'].split(" "))
|
|
log.info("writing ifcfg %s for slave %s of bond %s", slave_filename, slave, dev)
|
|
write_ifcfg(slave_filename, slave_ifcfg)
|
|
|
|
if net.teamslaves:
|
|
|
|
ifcfg.pop('HWADDR', None)
|
|
ifcfg['TYPE'] = "Team"
|
|
ifcfg['NAME'] = "Team connection %s" % dev
|
|
ifcfg['TEAM_CONFIG'] = "'" + net.teamconfig + "'"
|
|
|
|
for i, (slave, cfg) in enumerate(net.teamslaves):
|
|
slave_ifcfg = {
|
|
'DEVICE': slave,
|
|
'DEVICETYPE' : "TeamPort",
|
|
'NAME' : "%s slave %s" % (dev, i),
|
|
'UUID' : str(uuid.uuid4()),
|
|
'ONBOOT' : "yes",
|
|
'TEAM_MASTER' : dev,
|
|
# 'HWADDR' : readsysfile("/sys/class/net/%s/address" % slave),
|
|
}
|
|
if cfg:
|
|
slave_ifcfg['TEAM_PORT_CONFIG'] = "'" + cfg + "'"
|
|
|
|
slave_filename = "/tmp/ifcfg/ifcfg-%s" % "_".join(slave_ifcfg['NAME'].split(" "))
|
|
log.info("writing ifcfg %s for slave %s of team %s", slave_filename, slave, dev)
|
|
write_ifcfg(slave_filename, slave_ifcfg)
|
|
|
|
if net.bridgeslaves:
|
|
|
|
ifcfg.pop('HWADDR', None)
|
|
ifcfg['TYPE'] = "Bridge"
|
|
ifcfg['NAME'] = "Bridge connection %s" % dev
|
|
|
|
options = {}
|
|
for opt in net.bridgeopts.split(","):
|
|
key, _sep, value = opt.partition("=")
|
|
if not value:
|
|
log.error("Invalid bridge option %s", opt)
|
|
continue
|
|
key = key.replace('-', '_')
|
|
options[key] = value
|
|
stp = options.pop("stp", None)
|
|
if stp:
|
|
ifcfg['STP'] = stp
|
|
delay = options.pop("forward_delay", None)
|
|
if delay:
|
|
ifcfg['DELAY'] = delay
|
|
if options:
|
|
keyvalues = ["%s=%s" % (key, options[key]) for key in options]
|
|
ifcfg['BRIDGING_OPTS'] = '"' + " ".join(keyvalues) + '"'
|
|
|
|
for i, slave in enumerate(net.bridgeslaves.split(","), 1):
|
|
slave_ifcfg = {
|
|
'TYPE' : "Ethernet",
|
|
'NAME' : "%s slave %s" % (dev, i),
|
|
'UUID' : str(uuid.uuid4()),
|
|
'ONBOOT' : "yes",
|
|
'BRIDGE' : dev,
|
|
'HWADDR' : readsysfile("/sys/class/net/%s/address" % slave),
|
|
}
|
|
slave_filename = "/tmp/ifcfg/ifcfg-%s" % "_".join(slave_ifcfg['NAME'].split(" "))
|
|
log.info("writing ifcfg %s for slave %s of bridge %s", slave_filename, slave, dev)
|
|
write_ifcfg(slave_filename, slave_ifcfg)
|
|
|
|
if net.vlanid:
|
|
interface_name = net.interfacename or "%s.%s" % (dev, net.vlanid)
|
|
ifcfg.pop('HWADDR', None)
|
|
ifcfg['TYPE'] = "Vlan"
|
|
ifcfg['VLAN'] = "yes"
|
|
ifcfg['VLAN_ID'] = net.vlanid
|
|
ifcfg['NAME'] = "VLAN connection %s" % interface_name
|
|
ifcfg['DEVICE'] = interface_name
|
|
ifcfg['PHYSDEV'] = dev
|
|
filename = "/tmp/ifcfg/ifcfg-%s" % interface_name
|
|
|
|
log.info("writing ifcfg %s for %s", filename, dev)
|
|
if write_ifcfg(filename, ifcfg):
|
|
return filename
|
|
|
|
def write_ifcfg(filename, ifcfg):
|
|
try:
|
|
with open(filename, "w") as f:
|
|
f.write('# Generated by parse-kickstart\n')
|
|
for k,v in ifcfg.items():
|
|
f.write("%s=%s\n" % (k,v))
|
|
except IOError as e:
|
|
log.error("can't write %s: %s", filename, e)
|
|
return False
|
|
return True
|
|
|
|
def process_kickstart(ksfile):
|
|
handler = DracutHandler()
|
|
handler.ksdevice = os.environ.get('ksdevice')
|
|
parser = KickstartParser(handler, missingIncludeIsFatal=False, errorsAreFatal=False)
|
|
parser.registerSection(NullSection(handler, sectionOpen="%addon"))
|
|
parser.registerSection(NullSection(handler, sectionOpen="%anaconda"))
|
|
log.info("processing kickstart file %s", ksfile)
|
|
processed_file = preprocessKickstart(ksfile)
|
|
try:
|
|
parser.readKickstart(processed_file)
|
|
except KickstartError as e:
|
|
log.error(str(e))
|
|
with open("/tmp/ks.info", "a") as f:
|
|
f.write('parsed_kickstart="%s"\n' % processed_file)
|
|
log.info("finished parsing kickstart")
|
|
return processed_file, handler.output
|
|
|
|
if __name__ == '__main__':
|
|
log = init_logger()
|
|
for path in sys.argv[1:]:
|
|
outfile, output = process_kickstart(path)
|
|
for line in filter(None, output):
|
|
print(line)
|