2011-01-18 09:24:57 +00:00
#
# kickstart.py: kickstart install support
#
# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
# Red Hat, Inc. All rights reserved.
#
# 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/>.
#
2013-01-23 17:28:19 +00:00
from pyanaconda . errors import ScriptError , errorHandler
2014-04-07 12:38:09 +00:00
from blivet . deviceaction import ActionCreateFormat , ActionDestroyFormat , ActionResizeDevice , ActionResizeFormat
from blivet . devices import LUKSDevice
from blivet . devicelibs . lvm import getPossiblePhysicalExtents
from blivet . devicelibs import swap
from blivet . formats import getFormat
from blivet . partitioning import doPartitioning
from blivet . partitioning import growLVM
from blivet import udev
import blivet . iscsi
import blivet . fcoe
import blivet . zfcp
import blivet . arch
2011-01-18 09:24:57 +00:00
2013-01-23 17:28:19 +00:00
import glob
2014-04-07 12:38:09 +00:00
from pyanaconda import iutil
2011-01-18 09:24:57 +00:00
import os
import os . path
import tempfile
2014-04-07 12:38:09 +00:00
import subprocess
from pyanaconda . flags import flags , can_touch_runtime_system
from pyanaconda . constants import ADDON_PATHS , ROOT_PATH
2013-01-23 17:28:19 +00:00
import shlex
2011-01-18 09:24:57 +00:00
import sys
import urlgrabber
import pykickstart . commands as commands
2013-01-23 17:28:19 +00:00
from pyanaconda import keyboard
from pyanaconda import ntp
from pyanaconda import timezone
2014-04-07 12:38:09 +00:00
from pyanaconda . timezone import NTP_PACKAGE , NTP_SERVICE
2013-01-23 17:28:19 +00:00
from pyanaconda import localization
from pyanaconda import network
2014-04-07 12:38:09 +00:00
from pyanaconda import nm
2013-01-23 17:28:19 +00:00
from pyanaconda . simpleconfig import SimpleConfigFile
from pyanaconda . users import getPassAlgo
from pyanaconda . desktop import Desktop
2014-04-07 12:38:09 +00:00
from pyanaconda . i18n import _
from pyanaconda . ui . common import collect
from pyanaconda . addons import AddonSection , AddonData , AddonRegistry , collect_addon_paths
2013-01-23 17:28:19 +00:00
2014-04-07 12:38:09 +00:00
from pykickstart . constants import CLEARPART_TYPE_NONE , FIRSTBOOT_SKIP , FIRSTBOOT_RECONFIG , KS_SCRIPT_POST , KS_SCRIPT_PRE , \
KS_SCRIPT_TRACEBACK , SELINUX_DISABLED , SELINUX_ENFORCING , SELINUX_PERMISSIVE
2013-01-23 17:28:19 +00:00
from pykickstart . errors import formatErrorMsg , KickstartError , KickstartValueError
from pykickstart . parser import KickstartParser
from pykickstart . parser import Script as KSScript
2014-04-07 12:38:09 +00:00
from pykickstart . sections import NullSection , PackageSection , PostScriptSection , PreScriptSection , TracebackScriptSection
2013-01-23 17:28:19 +00:00
from pykickstart . version import returnClassForVersion
2011-01-18 09:24:57 +00:00
import logging
log = logging . getLogger ( " anaconda " )
stderrLog = logging . getLogger ( " anaconda.stderr " )
2014-04-07 12:38:09 +00:00
storage_log = logging . getLogger ( " blivet " )
2013-01-23 17:28:19 +00:00
stdoutLog = logging . getLogger ( " anaconda.stdout " )
2014-04-07 12:38:09 +00:00
from pyanaconda . anaconda_log import logger , logLevelMap , setHandlersLevel , \
2011-01-18 09:24:57 +00:00
DEFAULT_TTY_LEVEL
2013-01-23 17:28:19 +00:00
class AnacondaKSScript ( KSScript ) :
2014-04-07 12:38:09 +00:00
""" Execute a kickstart script
This will write the script to a file named / tmp / ks - script - before
execution .
Output is logged by the program logger , the path specified by - - log
or to / tmp / ks - script - * . log
"""
2013-01-23 17:28:19 +00:00
def run ( self , chroot ) :
2014-04-07 12:38:09 +00:00
""" Run the kickstart script
@param chroot directory path to chroot into before execution
"""
2011-01-18 09:24:57 +00:00
if self . inChroot :
scriptRoot = chroot
else :
scriptRoot = " / "
( fd , path ) = tempfile . mkstemp ( " " , " ks-script- " , scriptRoot + " /tmp " )
os . write ( fd , self . script )
os . close ( fd )
os . chmod ( path , 0700 )
2014-04-07 12:38:09 +00:00
# Always log stdout/stderr from scripts. Using --log just lets you
2011-01-18 09:24:57 +00:00
# pick where it goes. The script will also be logged to program.log
2014-04-07 12:38:09 +00:00
# because of execWithRedirect.
2011-01-18 09:24:57 +00:00
if self . logfile :
if self . inChroot :
messages = " %s / %s " % ( scriptRoot , self . logfile )
else :
messages = self . logfile
2013-01-23 17:28:19 +00:00
d = os . path . dirname ( messages )
2011-01-18 09:24:57 +00:00
if not os . path . exists ( d ) :
os . makedirs ( d )
else :
2013-01-23 17:28:19 +00:00
# Always log outside the chroot, we copy those logs into the
# chroot later.
messages = " /tmp/ %s .log " % os . path . basename ( path )
2011-01-18 09:24:57 +00:00
2014-04-07 12:38:09 +00:00
with open ( messages , " w " ) as fp :
rc = iutil . execWithRedirect ( self . interp , [ " /tmp/ %s " % os . path . basename ( path ) ] ,
stdout = fp ,
root = scriptRoot )
2011-01-18 09:24:57 +00:00
if rc != 0 :
2014-04-07 12:38:09 +00:00
log . error ( " Error code %s running the kickstart script at line %s " , rc , self . lineno )
2011-01-18 09:24:57 +00:00
if self . errorOnFail :
2014-04-07 12:38:09 +00:00
err = " "
with open ( messages , " r " ) as fp :
err = " " . join ( fp . readlines ( ) )
2013-01-23 17:28:19 +00:00
errorHandler . cb ( ScriptError ( ) , self . lineno , err )
2011-01-18 09:24:57 +00:00
sys . exit ( 0 )
2013-01-23 17:28:19 +00:00
class AnacondaInternalScript ( AnacondaKSScript ) :
def __init__ ( self , * args , * * kwargs ) :
AnacondaKSScript . __init__ ( self , * args , * * kwargs )
self . _hidden = True
2011-01-18 09:24:57 +00:00
2013-01-23 17:28:19 +00:00
def __str__ ( self ) :
# Scripts that implement portions of anaconda (copying screenshots and
# log files, setfilecons, etc.) should not be written to the output
# kickstart file.
return " "
2011-01-18 09:24:57 +00:00
2013-01-23 17:28:19 +00:00
def getEscrowCertificate ( escrowCerts , url ) :
2011-01-18 09:24:57 +00:00
if not url :
return None
2013-01-23 17:28:19 +00:00
if url in escrowCerts :
return escrowCerts [ url ]
2011-01-18 09:24:57 +00:00
needs_net = not url . startswith ( " / " ) and not url . startswith ( " file: " )
2014-04-07 12:38:09 +00:00
if needs_net and not nm . nm_is_connected ( ) :
2013-01-23 17:28:19 +00:00
msg = _ ( " Escrow certificate %s requires the network. " ) % url
raise KickstartError ( msg )
2011-01-18 09:24:57 +00:00
2014-04-07 12:38:09 +00:00
log . info ( " escrow: downloading %s " , url )
2013-01-23 17:28:19 +00:00
try :
f = urlgrabber . urlopen ( url )
except urlgrabber . grabber . URLGrabError as e :
msg = _ ( " The following error was encountered while downloading the escrow certificate: \n \n %s " % e )
raise KickstartError ( msg )
2011-01-18 09:24:57 +00:00
try :
2013-01-23 17:28:19 +00:00
escrowCerts [ url ] = f . read ( )
2011-01-18 09:24:57 +00:00
finally :
f . close ( )
2013-01-23 17:28:19 +00:00
return escrowCerts [ url ]
def deviceMatches ( spec ) :
full_spec = spec
if not full_spec . startswith ( " /dev/ " ) :
full_spec = os . path . normpath ( " /dev/ " + full_spec )
2011-01-18 09:24:57 +00:00
2013-01-23 17:28:19 +00:00
# the regular case
2014-04-07 12:38:09 +00:00
matches = udev . udev_resolve_glob ( full_spec )
dev = udev . udev_resolve_devspec ( full_spec )
2011-01-18 09:24:57 +00:00
# udev_resolve_devspec returns None if there's no match, but we don't
# want that ending up in the list.
if dev and dev not in matches :
matches . append ( dev )
return matches
2013-01-23 17:28:19 +00:00
def lookupAlias ( devicetree , alias ) :
for dev in devicetree . devices :
if getattr ( dev , " req_name " , None ) == alias :
return dev
return None
2011-01-18 09:24:57 +00:00
# Remove any existing formatting on a device, but do not remove the partition
# itself. This sets up an existing device to be used in a --onpart option.
def removeExistingFormat ( device , storage ) :
deps = storage . deviceDeps ( device )
while deps :
leaves = [ d for d in deps if d . isleaf ]
for leaf in leaves :
storage . destroyDevice ( leaf )
deps . remove ( leaf )
storage . devicetree . registerAction ( ActionDestroyFormat ( device ) )
2014-04-07 12:38:09 +00:00
def getAvailableDiskSpace ( storage ) :
"""
Get overall disk space available on disks we may use ( not free space on the
disks , but overall space on the disks ) .
: param storage : blivet . Blivet instance
: return : overall disk space available in MB
: rtype : int
"""
disk_space = 0
for disk in storage . disks :
if not storage . config . clearPartDisks or \
disk . name in storage . config . clearPartDisks :
disk_space + = disk . size
return disk_space
2011-01-18 09:24:57 +00:00
###
### SUBCLASSES OF PYKICKSTART COMMAND HANDLERS
###
class Authconfig ( commands . authconfig . FC3_Authconfig ) :
2013-01-23 17:28:19 +00:00
def execute ( self , * args ) :
args = [ " --update " , " --nostart " ] + shlex . split ( self . authconfig )
if not flags . automatedInstall and \
( os . path . exists ( ROOT_PATH + " /lib64/security/pam_fprintd.so " ) or \
os . path . exists ( ROOT_PATH + " /lib/security/pam_fprintd.so " ) ) :
args + = [ " --enablefingerprint " ]
try :
2014-04-07 12:38:09 +00:00
iutil . execWithRedirect ( " /usr/sbin/authconfig " , args , root = ROOT_PATH )
2013-01-23 17:28:19 +00:00
except RuntimeError as msg :
log . error ( " Error running /usr/sbin/authconfig %s : %s " , args , msg )
2014-04-07 12:38:09 +00:00
class AutoPart ( commands . autopart . F20_AutoPart ) :
2013-01-26 21:29:36 +00:00
def __init__ ( self , writePriority = 100 , * args , * * kwargs ) :
if ' encrypted ' not in kwargs :
kwargs [ ' encrypted ' ] = True
2013-02-12 01:30:05 +00:00
super ( AutoPart , self ) . __init__ ( writePriority = writePriority , * args , * * kwargs )
2013-01-26 21:29:36 +00:00
2013-01-23 17:28:19 +00:00
def execute ( self , storage , ksdata , instClass ) :
2014-04-07 12:38:09 +00:00
from blivet . partitioning import doAutoPartition
2013-01-23 17:28:19 +00:00
if not self . autopart :
return
2011-01-18 09:24:57 +00:00
# sets up default autopartitioning. use clearpart separately
# if you want it
2013-01-23 17:28:19 +00:00
instClass . setDefaultPartitioning ( storage )
storage . doAutoPart = True
2011-01-18 09:24:57 +00:00
if self . encrypted :
2013-01-23 17:28:19 +00:00
storage . encryptedAutoPart = True
storage . encryptionPassphrase = self . passphrase
storage . encryptionCipher = self . cipher
storage . autoPartEscrowCert = getEscrowCertificate ( storage . escrowCertificates , self . escrowcert )
storage . autoPartAddBackupPassphrase = self . backuppassphrase
if self . type is not None :
storage . autoPartType = self . type
doAutoPartition ( storage , ksdata )
2014-04-07 12:38:09 +00:00
class Bootloader ( commands . bootloader . F19_Bootloader ) :
def __init__ ( self , * args , * * kwargs ) :
commands . bootloader . F19_Bootloader . __init__ ( self , * args , * * kwargs )
self . location = " mbr "
2013-01-23 17:28:19 +00:00
def execute ( self , storage , ksdata , instClass ) :
2011-01-18 09:24:57 +00:00
if self . location == " none " :
location = None
elif self . location == " partition " :
location = " boot "
else :
location = self . location
2013-01-23 17:28:19 +00:00
if not location :
storage . bootloader . skip_bootloader = True
return
if self . appendLine :
args = self . appendLine . split ( )
storage . bootloader . boot_args . update ( args )
if self . password :
if self . isCrypted :
storage . bootloader . encrypted_password = self . password
else :
storage . bootloader . password = self . password
if location :
storage . bootloader . set_preferred_stage1_type ( location )
if self . timeout is not None :
storage . bootloader . timeout = self . timeout
# Throw out drives specified that don't exist.
disk_names = [ d . name for d in storage . disks
if not d . format . hidden and not d . protected ]
for drive in self . driveorder [ : ] :
if drive not in disk_names :
2014-04-07 12:38:09 +00:00
log . warning ( " requested drive %s in boot drive order doesn ' t exist " , drive )
2013-01-23 17:28:19 +00:00
self . driveorder . remove ( drive )
storage . bootloader . disk_order = self . driveorder
if self . bootDrive :
if not self . bootDrive in disk_names :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno ,
msg = " Requested boot drive %s doesn ' t exist " % self . bootDrive ) )
2011-01-18 09:24:57 +00:00
else :
2013-01-23 17:28:19 +00:00
self . bootDrive = disk_names [ 0 ]
2011-01-18 09:24:57 +00:00
2014-04-07 12:38:09 +00:00
spec = udev . udev_resolve_devspec ( self . bootDrive )
2013-01-23 17:28:19 +00:00
drive = storage . devicetree . getDeviceByName ( spec )
storage . bootloader . stage1_disk = drive
2011-01-18 09:24:57 +00:00
2013-01-23 17:28:19 +00:00
if self . leavebootorder :
flags . leavebootorder = True
2011-01-18 09:24:57 +00:00
2013-01-23 17:28:19 +00:00
class BTRFS ( commands . btrfs . F17_BTRFS ) :
def execute ( self , storage , ksdata , instClass ) :
for b in self . btrfsList :
b . execute ( storage , ksdata , instClass )
2011-01-18 09:24:57 +00:00
2013-01-23 17:28:19 +00:00
class BTRFSData ( commands . btrfs . F17_BTRFSData ) :
def execute ( self , storage , ksdata , instClass ) :
devicetree = storage . devicetree
storage . doAutoPart = False
members = [ ]
# Get a list of all the devices that make up this volume.
for member in self . devices :
2014-04-07 12:38:09 +00:00
dev = devicetree . resolveDevice ( member )
2013-01-23 17:28:19 +00:00
if not dev :
2014-04-07 12:38:09 +00:00
# if using --onpart, use original device
member_name = ksdata . onPart . get ( member , member )
dev = devicetree . resolveDevice ( member_name ) or lookupAlias ( devicetree , member )
2013-01-23 17:28:19 +00:00
if dev and dev . format . type == " luks " :
try :
dev = devicetree . getChildren ( dev ) [ 0 ]
except IndexError :
dev = None
2014-04-07 12:38:09 +00:00
if dev and dev . format . type != " btrfs " :
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " BTRFS partition %s has incorrect format ( %s ) " % ( member , dev . format . type ) ) )
2013-01-23 17:28:19 +00:00
if not dev :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " Tried to use undefined partition %s in BTRFS volume specification " % member ) )
2013-01-23 17:28:19 +00:00
members . append ( dev )
if self . subvol :
name = self . name
elif self . label :
name = self . label
else :
name = None
if len ( members ) == 0 and not self . preexist :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " BTRFS volume defined without any member devices. Either specify member devices or use --useexisting. " ) )
2013-01-23 17:28:19 +00:00
# allow creating btrfs vols/subvols without specifying mountpoint
if self . mountpoint in ( " none " , " None " ) :
self . mountpoint = " "
# Sanity check mountpoint
if self . mountpoint != " " and self . mountpoint [ 0 ] != ' / ' :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " The mount point \" %s \" is not valid. " % ( self . mountpoint , ) ) )
# If a previous device has claimed this mount point, delete the
# old one.
try :
if self . mountpoint :
device = storage . mountpoints [ self . mountpoint ]
storage . destroyDevice ( device )
except KeyError :
pass
2013-01-23 17:28:19 +00:00
if self . preexist :
device = devicetree . getDeviceByName ( self . name )
if not device :
2014-04-07 12:38:09 +00:00
device = udev . udev_resolve_devspec ( self . name )
2013-01-23 17:28:19 +00:00
if not device :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " Specified nonexistent BTRFS volume %s in btrfs command " % self . name ) )
2013-01-23 17:28:19 +00:00
2014-04-07 12:38:09 +00:00
device . format . mountpoint = self . mountpoint
else :
2013-01-23 17:28:19 +00:00
request = storage . newBTRFS ( name = name ,
subvol = self . subvol ,
mountpoint = self . mountpoint ,
metaDataLevel = self . metaDataLevel ,
dataLevel = self . dataLevel ,
parents = members )
storage . createDevice ( request )
2014-04-07 12:38:09 +00:00
class Realm ( commands . realm . F19_Realm ) :
def __init__ ( self , * args ) :
commands . realm . F19_Realm . __init__ ( self , * args )
self . packages = [ ]
self . discovered = " "
def setup ( self ) :
if not self . join_realm :
return
try :
argv = [ " realm " , " discover " , " --verbose " ] + \
self . discover_options + [ self . join_realm ]
proc = subprocess . Popen ( argv , stdout = subprocess . PIPE , stderr = subprocess . PIPE )
output , stderr = proc . communicate ( )
# might contain useful information for users who use
# use the realm kickstart command
log . info ( " Realm discover stderr: \n %s " , stderr )
except OSError as msg :
# TODO: A lousy way of propagating what will usually be
# 'no such realm'
log . error ( " Error running realm %s : %s " , argv , msg )
return
# Now parse the output for the required software. First line is the
# realm name, and following lines are information as "name: value"
self . packages = [ " realmd " ]
self . discovered = " "
lines = output . split ( " \n " )
if not lines :
return
self . discovered = lines . pop ( 0 ) . strip ( )
log . info ( " Realm discovered: %s " , self . discovered )
for line in lines :
parts = line . split ( " : " , 1 )
if len ( parts ) == 2 and parts [ 0 ] . strip ( ) == " required-package " :
self . packages . append ( parts [ 1 ] . strip ( ) )
log . info ( " Realm %s needs packages %s " ,
self . discovered , " , " . join ( self . packages ) )
def execute ( self , * args ) :
if not self . discovered :
return
for arg in self . join_args :
if arg . startswith ( " --no-password " ) or arg . startswith ( " --one-time-password " ) :
pw_args = [ ]
break
else :
# no explicit password arg using implicit --no-password
pw_args = [ " --no-password " ]
argv = [ " realm " , " join " , " --install " , ROOT_PATH , " --verbose " ] + \
pw_args + self . join_args
rc = - 1
try :
proc = subprocess . Popen ( argv , stdout = subprocess . PIPE ,
stderr = subprocess . PIPE )
stderr = proc . communicate ( ) [ 1 ]
# might contain useful information for users who use
# use the realm kickstart command
log . info ( " Realm join stderr: \n %s " , stderr )
rc = proc . returncode
except OSError as msg :
log . error ( " Error running %s : %s " , argv , msg )
if rc != 0 :
log . error ( " Command failure: %s : %d " , argv , rc )
return
log . info ( " Joined realm %s " , self . join_realm )
2013-01-23 17:28:19 +00:00
class ClearPart ( commands . clearpart . F17_ClearPart ) :
2011-01-18 09:24:57 +00:00
def parse ( self , args ) :
2013-01-23 17:28:19 +00:00
retval = commands . clearpart . F17_ClearPart . parse ( self , args )
2011-01-18 09:24:57 +00:00
if self . type is None :
self . type = CLEARPART_TYPE_NONE
# Do any glob expansion now, since we need to have the real list of
# disks available before the execute methods run.
drives = [ ]
for spec in self . drives :
matched = deviceMatches ( spec )
if matched :
drives . extend ( matched )
else :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " Specified nonexistent disk %s in clearpart command " % spec ) )
2011-01-18 09:24:57 +00:00
self . drives = drives
2013-01-23 17:28:19 +00:00
# Do any glob expansion now, since we need to have the real list of
# devices available before the execute methods run.
devices = [ ]
for spec in self . devices :
matched = deviceMatches ( spec )
if matched :
devices . extend ( matched )
else :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " Specified nonexistent device %s in clearpart device list " % spec ) )
2013-01-23 17:28:19 +00:00
self . devices = devices
2011-01-18 09:24:57 +00:00
return retval
2013-01-23 17:28:19 +00:00
def execute ( self , storage , ksdata , instClass ) :
storage . config . clearPartType = self . type
storage . config . clearPartDisks = self . drives
storage . config . clearPartDevices = self . devices
2011-01-18 09:24:57 +00:00
if self . initAll :
2013-01-23 17:28:19 +00:00
storage . config . initializeDisks = self . initAll
2011-01-18 09:24:57 +00:00
2013-01-23 17:28:19 +00:00
storage . clearPartitions ( )
2011-01-18 09:24:57 +00:00
class Fcoe ( commands . fcoe . F13_Fcoe ) :
def parse ( self , args ) :
fc = commands . fcoe . F13_Fcoe . parse ( self , args )
2014-04-07 12:38:09 +00:00
if fc . nic not in nm . nm_devices ( ) :
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " Specified nonexistent nic %s in fcoe command " % fc . nic ) )
2011-01-18 09:24:57 +00:00
2014-04-07 12:38:09 +00:00
blivet . fcoe . fcoe ( ) . addSan ( nic = fc . nic , dcb = fc . dcb , auto_vlan = True )
2011-01-18 09:24:57 +00:00
return fc
2014-04-07 12:38:09 +00:00
class Firewall ( commands . firewall . F20_Firewall ) :
2013-01-23 17:28:19 +00:00
def execute ( self , storage , ksdata , instClass ) :
args = [ ]
# enabled is None if neither --enable or --disable is passed
# default to enabled if nothing has been set.
if self . enabled == False :
args + = [ " --disabled " ]
else :
args + = [ " --enabled " ]
2014-04-07 12:38:09 +00:00
if " ssh " not in self . services and " ssh " not in self . remove_services \
and " 22:tcp " not in self . ports :
2013-01-23 17:28:19 +00:00
args + = [ " --service=ssh " ]
for dev in self . trusts :
args + = [ " --trust= %s " % ( dev , ) ]
2011-01-18 09:24:57 +00:00
for port in self . ports :
2013-01-23 17:28:19 +00:00
args + = [ " --port= %s " % ( port , ) ]
2014-04-07 12:38:09 +00:00
for remove_service in self . remove_services :
args + = [ " --remove-service= %s " % ( remove_service , ) ]
2013-01-23 17:28:19 +00:00
for service in self . services :
args + = [ " --service= %s " % ( service , ) ]
2011-01-18 09:24:57 +00:00
2013-01-23 17:28:19 +00:00
cmd = " /usr/bin/firewall-offline-cmd "
if not os . path . exists ( ROOT_PATH + cmd ) :
2014-04-07 12:38:09 +00:00
if self . enabled :
msg = _ ( " %s is missing. Cannot setup firewall. " ) % ( cmd , )
raise KickstartError ( msg )
2013-01-23 17:28:19 +00:00
else :
2014-04-07 12:38:09 +00:00
iutil . execWithRedirect ( cmd , args , root = ROOT_PATH )
2011-01-18 09:24:57 +00:00
2013-01-23 17:28:19 +00:00
class Firstboot ( commands . firstboot . FC3_Firstboot ) :
2014-04-07 12:38:09 +00:00
def setup ( self , * args ) :
# firstboot should be disabled by default after kickstart installations
if flags . automatedInstall and not self . seen :
self . firstboot = FIRSTBOOT_SKIP
2013-01-23 17:28:19 +00:00
2014-04-07 12:38:09 +00:00
def execute ( self , * args ) :
2013-01-23 17:28:19 +00:00
action = " enable "
if self . firstboot == FIRSTBOOT_SKIP :
action = " disable "
elif self . firstboot == FIRSTBOOT_RECONFIG :
f = open ( ROOT_PATH + " /etc/reconfigSys " , " w+ " )
f . close ( )
2014-04-07 12:38:09 +00:00
iutil . execWithRedirect ( " systemctl " , [ action , " firstboot-graphical.service " ,
" initial-setup-graphical.service " ,
" initial-setup-text.service " ] ,
2013-01-23 17:28:19 +00:00
root = ROOT_PATH )
class Group ( commands . group . F12_Group ) :
def execute ( self , storage , ksdata , instClass , users ) :
for grp in self . groupList :
kwargs = grp . __dict__
kwargs . update ( { " root " : ROOT_PATH } )
2014-04-07 12:38:09 +00:00
users . createGroup ( grp . name , * * kwargs )
2013-01-23 17:28:19 +00:00
class IgnoreDisk ( commands . ignoredisk . RHEL6_IgnoreDisk ) :
2011-01-18 09:24:57 +00:00
def parse ( self , args ) :
2013-01-23 17:28:19 +00:00
retval = commands . ignoredisk . RHEL6_IgnoreDisk . parse ( self , args )
2011-01-18 09:24:57 +00:00
# See comment in ClearPart.parse
drives = [ ]
for spec in self . ignoredisk :
matched = deviceMatches ( spec )
if matched :
drives . extend ( matched )
else :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " Specified nonexistent disk %s in ignoredisk command " % spec ) )
2011-01-18 09:24:57 +00:00
self . ignoredisk = drives
drives = [ ]
for spec in self . onlyuse :
matched = deviceMatches ( spec )
if matched :
drives . extend ( matched )
else :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " Specified nonexistent disk %s in ignoredisk command " % spec ) )
2011-01-18 09:24:57 +00:00
self . onlyuse = drives
return retval
2013-01-23 17:28:19 +00:00
class Iscsi ( commands . iscsi . F17_Iscsi ) :
2011-01-18 09:24:57 +00:00
def parse ( self , args ) :
2013-01-23 17:28:19 +00:00
tg = commands . iscsi . F17_Iscsi . parse ( self , args )
if tg . iface :
2014-04-07 12:38:09 +00:00
if not network . wait_for_network_devices ( [ tg . iface ] ) :
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " network interface %s required by iscsi %s target is not up " % ( tg . iface , tg . target ) ) )
2013-01-23 17:28:19 +00:00
2014-04-07 12:38:09 +00:00
mode = blivet . iscsi . iscsi ( ) . mode
2013-01-23 17:28:19 +00:00
if mode == " none " :
if tg . iface :
2014-04-07 12:38:09 +00:00
blivet . iscsi . iscsi ( ) . create_interfaces ( nm . nm_activated_devices ( ) )
2013-01-23 17:28:19 +00:00
elif ( ( mode == " bind " and not tg . iface )
or ( mode == " default " and tg . iface ) ) :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " iscsi --iface must be specified (binding used) either for all targets or for none " ) )
2011-01-18 09:24:57 +00:00
try :
2014-04-07 12:38:09 +00:00
blivet . iscsi . iscsi ( ) . addTarget ( tg . ipaddr , tg . port , tg . user ,
2013-01-23 17:28:19 +00:00
tg . password , tg . user_in ,
tg . password_in ,
target = tg . target ,
iface = tg . iface )
2014-04-07 12:38:09 +00:00
log . info ( " added iscsi target %s at %s via %s " , tg . target ,
tg . ipaddr ,
tg . iface )
2013-01-23 17:28:19 +00:00
except ( IOError , ValueError ) as e :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = str ( e ) ) )
2013-01-23 17:28:19 +00:00
2011-01-18 09:24:57 +00:00
return tg
class IscsiName ( commands . iscsiname . FC6_IscsiName ) :
def parse ( self , args ) :
retval = commands . iscsiname . FC6_IscsiName . parse ( self , args )
2014-04-07 12:38:09 +00:00
blivet . iscsi . iscsi ( ) . initiator = self . iscsiname
2011-01-18 09:24:57 +00:00
return retval
2014-04-07 12:38:09 +00:00
class Lang ( commands . lang . F19_Lang ) :
2013-01-23 17:28:19 +00:00
def execute ( self , * args , * * kwargs ) :
localization . write_language_configuration ( self , ROOT_PATH )
2014-04-07 12:38:09 +00:00
# no overrides needed here
Eula = commands . eula . F20_Eula
class LogVol ( commands . logvol . F20_LogVol ) :
2013-01-23 17:28:19 +00:00
def execute ( self , storage , ksdata , instClass ) :
for l in self . lvList :
l . execute ( storage , ksdata , instClass )
if self . lvList :
growLVM ( storage )
2014-04-07 12:38:09 +00:00
class LogVolData ( commands . logvol . F20_LogVolData ) :
2013-01-23 17:28:19 +00:00
def execute ( self , storage , ksdata , instClass ) :
2011-01-18 09:24:57 +00:00
devicetree = storage . devicetree
storage . doAutoPart = False
2014-04-07 12:38:09 +00:00
# we might have truncated or otherwise changed the specified vg name
vgname = ksdata . onPart . get ( self . vgname , self . vgname )
2011-01-18 09:24:57 +00:00
if self . mountpoint == " swap " :
2014-04-07 12:38:09 +00:00
ty = " swap "
2011-01-18 09:24:57 +00:00
self . mountpoint = " "
2013-01-23 17:28:19 +00:00
if self . recommended or self . hibernation :
2014-04-07 12:38:09 +00:00
disk_space = getAvailableDiskSpace ( storage )
self . size = swap . swapSuggestion ( hibernation = self . hibernation , disk_space = disk_space )
2013-01-23 17:28:19 +00:00
self . grow = False
2011-01-18 09:24:57 +00:00
else :
if self . fstype != " " :
2014-04-07 12:38:09 +00:00
ty = self . fstype
2011-01-18 09:24:57 +00:00
else :
2014-04-07 12:38:09 +00:00
ty = storage . defaultFSType
if self . thin_pool :
self . mountpoint = " "
ty = None
2011-01-18 09:24:57 +00:00
# Sanity check mountpoint
if self . mountpoint != " " and self . mountpoint [ 0 ] != ' / ' :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " The mount point \" %s \" is not valid. " % ( self . mountpoint , ) ) )
2011-01-18 09:24:57 +00:00
# Check that the VG this LV is a member of has already been specified.
2014-04-07 12:38:09 +00:00
vg = devicetree . getDeviceByName ( vgname )
2011-01-18 09:24:57 +00:00
if not vg :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " No volume group exists with the name \" %s \" . Specify volume groups before logical volumes. " % self . vgname ) )
pool = None
if self . thin_volume :
pool = devicetree . getDeviceByName ( " %s - %s " % ( vg . name , self . pool_name ) )
if not pool :
err = formatErrorMsg ( self . lineno ,
msg = " No thin pool exists with the name "
" \" %s \" . Specify thin pools before "
" thin volumes. " % self . pool_name )
raise KickstartValueError ( err )
2011-01-18 09:24:57 +00:00
# If this specifies an existing request that we should not format,
# quit here after setting up enough information to mount it later.
if not self . format :
if not self . name :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " --noformat used without --name " ) )
2011-01-18 09:24:57 +00:00
dev = devicetree . getDeviceByName ( " %s - %s " % ( vg . name , self . name ) )
if not dev :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " No preexisting logical volume with the name \" %s \" was found. " % self . name ) )
2011-01-18 09:24:57 +00:00
2013-01-23 17:28:19 +00:00
if self . resize :
if self . size < dev . currentSize :
# shrink
try :
devicetree . registerAction ( ActionResizeFormat ( dev , self . size ) )
devicetree . registerAction ( ActionResizeDevice ( dev , self . size ) )
except ValueError :
raise KickstartValueError ( formatErrorMsg ( self . lineno ,
msg = " Invalid target size ( %d ) for device %s " % ( self . size , dev . name ) ) )
else :
# grow
try :
devicetree . registerAction ( ActionResizeDevice ( dev , self . size ) )
devicetree . registerAction ( ActionResizeFormat ( dev , self . size ) )
except ValueError :
raise KickstartValueError ( formatErrorMsg ( self . lineno ,
msg = " Invalid target size ( %d ) for device %s " % ( self . size , dev . name ) ) )
2011-01-18 09:24:57 +00:00
dev . format . mountpoint = self . mountpoint
dev . format . mountopts = self . fsopts
2014-04-07 12:38:09 +00:00
if ty == " swap " :
storage . addFstabSwap ( dev )
2011-01-18 09:24:57 +00:00
return
# Make sure this LV name is not already used in the requested VG.
if not self . preexist :
tmp = devicetree . getDeviceByName ( " %s - %s " % ( vg . name , self . name ) )
if tmp :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " Logical volume name already used in volume group %s " % vg . name ) )
2011-01-18 09:24:57 +00:00
# Size specification checks
if not self . percent :
if not self . size :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " Size required " ) )
2011-01-18 09:24:57 +00:00
elif not self . grow and self . size * 1024 < vg . peSize :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " Logical volume size must be larger than the volume group physical extent size. " ) )
2011-01-18 09:24:57 +00:00
elif self . percent < = 0 or self . percent > 100 :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " Percentage must be between 0 and 100 " ) )
2011-01-18 09:24:57 +00:00
# Now get a format to hold a lot of these extra values.
2014-04-07 12:38:09 +00:00
fmt = getFormat ( ty ,
mountpoint = self . mountpoint ,
label = self . label ,
fsprofile = self . fsprofile ,
mountopts = self . fsopts )
if not fmt . type and not self . thin_pool :
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " The \" %s \" filesystem type is not supported. " % ty ) )
2011-01-18 09:24:57 +00:00
# If we were given a pre-existing LV to create a filesystem on, we need
# to verify it and its VG exists and then schedule a new format action
# to take place there. Also, we only support a subset of all the
# options on pre-existing LVs.
if self . preexist :
device = devicetree . getDeviceByName ( " %s - %s " % ( vg . name , self . name ) )
if not device :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " Specified nonexistent LV %s in logvol command " % self . name ) )
2011-01-18 09:24:57 +00:00
removeExistingFormat ( device , storage )
2013-01-23 17:28:19 +00:00
if self . resize :
try :
devicetree . registerAction ( ActionResizeDevice ( device , self . size ) )
except ValueError :
raise KickstartValueError ( formatErrorMsg ( self . lineno ,
msg = " Invalid target size ( %d ) for device %s " % ( self . size , device . name ) ) )
2014-04-07 12:38:09 +00:00
devicetree . registerAction ( ActionCreateFormat ( device , fmt ) )
if ty == " swap " :
storage . addFstabSwap ( device )
2011-01-18 09:24:57 +00:00
else :
# If a previous device has claimed this mount point, delete the
# old one.
try :
if self . mountpoint :
device = storage . mountpoints [ self . mountpoint ]
storage . destroyDevice ( device )
except KeyError :
pass
2014-04-07 12:38:09 +00:00
if self . thin_volume :
parents = [ pool ]
else :
parents = [ vg ]
if self . thin_pool :
pool_args = { " metadatasize " : self . metadata_size ,
" chunksize " : self . chunk_size / 1024.0 }
else :
pool_args = { }
request = storage . newLV ( format = fmt ,
2011-01-18 09:24:57 +00:00
name = self . name ,
2014-04-07 12:38:09 +00:00
parents = parents ,
2011-01-18 09:24:57 +00:00
size = self . size ,
2014-04-07 12:38:09 +00:00
thin_pool = self . thin_pool ,
thin_volume = self . thin_volume ,
2011-01-18 09:24:57 +00:00
grow = self . grow ,
maxsize = self . maxSizeMB ,
2014-04-07 12:38:09 +00:00
percent = self . percent ,
* * pool_args )
2011-01-18 09:24:57 +00:00
storage . createDevice ( request )
2014-04-07 12:38:09 +00:00
if ty == " swap " :
storage . addFstabSwap ( request )
2011-01-18 09:24:57 +00:00
if self . encrypted :
if self . passphrase and not storage . encryptionPassphrase :
storage . encryptionPassphrase = self . passphrase
2013-01-23 17:28:19 +00:00
cert = getEscrowCertificate ( storage . escrowCertificates , self . escrowcert )
2011-01-18 09:24:57 +00:00
if self . preexist :
2014-04-07 12:38:09 +00:00
luksformat = fmt
2011-01-18 09:24:57 +00:00
device . format = getFormat ( " luks " , passphrase = self . passphrase , device = device . path ,
2013-01-23 17:28:19 +00:00
cipher = self . cipher ,
2011-01-18 09:24:57 +00:00
escrow_cert = cert ,
add_backup_passphrase = self . backuppassphrase )
luksdev = LUKSDevice ( " luks %d " % storage . nextID ,
format = luksformat ,
parents = device )
else :
luksformat = request . format
request . format = getFormat ( " luks " , passphrase = self . passphrase ,
2013-01-23 17:28:19 +00:00
cipher = self . cipher ,
2011-01-18 09:24:57 +00:00
escrow_cert = cert ,
add_backup_passphrase = self . backuppassphrase )
luksdev = LUKSDevice ( " luks %d " % storage . nextID ,
format = luksformat ,
parents = request )
storage . createDevice ( luksdev )
class Logging ( commands . logging . FC6_Logging ) :
2013-01-23 17:28:19 +00:00
def execute ( self , * args ) :
2011-01-18 09:24:57 +00:00
if logger . tty_loglevel == DEFAULT_TTY_LEVEL :
# not set from the command line
level = logLevelMap [ self . level ]
logger . tty_loglevel = level
setHandlersLevel ( log , level )
setHandlersLevel ( storage_log , level )
if logger . remote_syslog == None and len ( self . host ) > 0 :
# not set from the command line, ok to use kickstart
remote_server = self . host
if self . port :
remote_server = " %s : %s " % ( self . host , self . port )
logger . updateRemote ( remote_server )
2014-04-07 12:38:09 +00:00
class Network ( commands . network . F20_Network ) :
2013-01-23 17:28:19 +00:00
def execute ( self , storage , ksdata , instClass ) :
network . write_network_config ( storage , ksdata , instClass , ROOT_PATH )
2011-01-18 09:24:57 +00:00
class MultiPath ( commands . multipath . FC6_MultiPath ) :
def parse ( self , args ) :
raise NotImplementedError ( " The multipath kickstart command is not currently supported " )
class DmRaid ( commands . dmraid . FC6_DmRaid ) :
def parse ( self , args ) :
raise NotImplementedError ( " The dmraid kickstart command is not currently supported " )
2014-04-07 12:38:09 +00:00
class Partition ( commands . partition . F20_Partition ) :
2013-01-23 17:28:19 +00:00
def execute ( self , storage , ksdata , instClass ) :
for p in self . partitions :
p . execute ( storage , ksdata , instClass )
if self . partitions :
doPartitioning ( storage )
class PartitionData ( commands . partition . F18_PartData ) :
def execute ( self , storage , ksdata , instClass ) :
2011-01-18 09:24:57 +00:00
devicetree = storage . devicetree
kwargs = { }
storage . doAutoPart = False
if self . onbiosdisk != " " :
for ( disk , biosdisk ) in storage . eddDict . iteritems ( ) :
2013-01-23 17:28:19 +00:00
if " %x " % biosdisk == self . onbiosdisk :
2011-01-18 09:24:57 +00:00
self . disk = disk
break
2013-01-23 17:28:19 +00:00
if not self . disk :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " Specified BIOS disk %s cannot be determined " % self . onbiosdisk ) )
2011-01-18 09:24:57 +00:00
if self . mountpoint == " swap " :
2014-04-07 12:38:09 +00:00
ty = " swap "
2011-01-18 09:24:57 +00:00
self . mountpoint = " "
2013-01-23 17:28:19 +00:00
if self . recommended or self . hibernation :
2014-04-07 12:38:09 +00:00
disk_space = getAvailableDiskSpace ( storage )
self . size = swap . swapSuggestion ( hibernation = self . hibernation , disk_space = disk_space )
2013-01-23 17:28:19 +00:00
self . grow = False
2011-01-18 09:24:57 +00:00
# if people want to specify no mountpoint for some reason, let them
# this is really needed for pSeries boot partitions :(
elif self . mountpoint == " None " :
self . mountpoint = " "
if self . fstype :
2014-04-07 12:38:09 +00:00
ty = self . fstype
2011-01-18 09:24:57 +00:00
else :
2014-04-07 12:38:09 +00:00
ty = storage . defaultFSType
2011-01-18 09:24:57 +00:00
elif self . mountpoint == ' appleboot ' :
2014-04-07 12:38:09 +00:00
ty = " appleboot "
2011-01-18 09:24:57 +00:00
self . mountpoint = " "
elif self . mountpoint == ' prepboot ' :
2014-04-07 12:38:09 +00:00
ty = " prepboot "
2013-01-23 17:28:19 +00:00
self . mountpoint = " "
elif self . mountpoint == ' biosboot ' :
2014-04-07 12:38:09 +00:00
ty = " biosboot "
2011-01-18 09:24:57 +00:00
self . mountpoint = " "
elif self . mountpoint . startswith ( " raid. " ) :
2014-04-07 12:38:09 +00:00
ty = " mdmember "
2011-01-18 09:24:57 +00:00
kwargs [ " name " ] = self . mountpoint
2013-01-23 17:28:19 +00:00
self . mountpoint = " "
2011-01-18 09:24:57 +00:00
if devicetree . getDeviceByName ( kwargs [ " name " ] ) :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " RAID partition defined multiple times " ) )
2011-01-18 09:24:57 +00:00
if self . onPart :
2013-01-23 17:28:19 +00:00
ksdata . onPart [ kwargs [ " name " ] ] = self . onPart
2011-01-18 09:24:57 +00:00
elif self . mountpoint . startswith ( " pv. " ) :
2014-04-07 12:38:09 +00:00
ty = " lvmpv "
2011-01-18 09:24:57 +00:00
kwargs [ " name " ] = self . mountpoint
2013-01-23 17:28:19 +00:00
self . mountpoint = " "
2011-01-18 09:24:57 +00:00
if devicetree . getDeviceByName ( kwargs [ " name " ] ) :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " PV partition defined multiple times " ) )
2011-01-18 09:24:57 +00:00
if self . onPart :
2013-01-23 17:28:19 +00:00
ksdata . onPart [ kwargs [ " name " ] ] = self . onPart
elif self . mountpoint . startswith ( " btrfs. " ) :
2014-04-07 12:38:09 +00:00
ty = " btrfs "
2013-01-23 17:28:19 +00:00
kwargs [ " name " ] = self . mountpoint
2011-01-18 09:24:57 +00:00
self . mountpoint = " "
2013-01-23 17:28:19 +00:00
if devicetree . getDeviceByName ( kwargs [ " name " ] ) :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " BTRFS partition defined multiple times " ) )
2013-01-23 17:28:19 +00:00
if self . onPart :
ksdata . onPart [ kwargs [ " name " ] ] = self . onPart
2011-01-18 09:24:57 +00:00
elif self . mountpoint == " /boot/efi " :
2014-04-07 12:38:09 +00:00
if blivet . arch . isMactel ( ) :
ty = " macefi "
2013-01-23 17:28:19 +00:00
else :
2014-04-07 12:38:09 +00:00
ty = " EFI System Partition "
2013-01-23 17:28:19 +00:00
self . fsopts = " defaults,uid=0,gid=0,umask=0077,shortname=winnt "
2011-01-18 09:24:57 +00:00
else :
if self . fstype != " " :
2014-04-07 12:38:09 +00:00
ty = self . fstype
2011-01-18 09:24:57 +00:00
elif self . mountpoint == " /boot " :
2014-04-07 12:38:09 +00:00
ty = storage . defaultBootFSType
2011-01-18 09:24:57 +00:00
else :
2014-04-07 12:38:09 +00:00
ty = storage . defaultFSType
2011-01-18 09:24:57 +00:00
# If this specified an existing request that we should not format,
# quit here after setting up enough information to mount it later.
if not self . format :
if not self . onPart :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " --noformat used without --onpart " ) )
2011-01-18 09:24:57 +00:00
2014-04-07 12:38:09 +00:00
dev = devicetree . getDeviceByName ( udev . udev_resolve_devspec ( self . onPart ) )
2011-01-18 09:24:57 +00:00
if not dev :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " No preexisting partition with the name \" %s \" was found. " % self . onPart ) )
2011-01-18 09:24:57 +00:00
2013-01-23 17:28:19 +00:00
if self . resize :
if self . size < dev . currentSize :
# shrink
try :
devicetree . registerAction ( ActionResizeFormat ( dev , self . size ) )
devicetree . registerAction ( ActionResizeDevice ( dev , self . size ) )
except ValueError :
raise KickstartValueError ( formatErrorMsg ( self . lineno ,
msg = " Invalid target size ( %d ) for device %s " % ( self . size , dev . name ) ) )
else :
# grow
try :
devicetree . registerAction ( ActionResizeDevice ( dev , self . size ) )
devicetree . registerAction ( ActionResizeFormat ( dev , self . size ) )
except ValueError :
raise KickstartValueError ( formatErrorMsg ( self . lineno ,
msg = " Invalid target size ( %d ) for device %s " % ( self . size , dev . name ) ) )
2011-01-18 09:24:57 +00:00
dev . format . mountpoint = self . mountpoint
dev . format . mountopts = self . fsopts
2014-04-07 12:38:09 +00:00
if ty == " swap " :
storage . addFstabSwap ( dev )
2011-01-18 09:24:57 +00:00
return
# Now get a format to hold a lot of these extra values.
2014-04-07 12:38:09 +00:00
kwargs [ " format " ] = getFormat ( ty ,
2011-01-18 09:24:57 +00:00
mountpoint = self . mountpoint ,
label = self . label ,
2013-01-23 17:28:19 +00:00
fsprofile = self . fsprofile ,
2014-04-07 12:38:09 +00:00
mountopts = self . fsopts ,
size = self . size )
2013-01-23 17:28:19 +00:00
if not kwargs [ " format " ] . type :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " The \" %s \" filesystem type is not supported. " % ty ) )
2011-01-18 09:24:57 +00:00
# If we were given a specific disk to create the partition on, verify
# that it exists first. If it doesn't exist, see if it exists with
# mapper/ on the front. If that doesn't exist either, it's an error.
if self . disk :
names = [ self . disk , " mapper/ " + self . disk ]
for n in names :
2014-04-07 12:38:09 +00:00
disk = devicetree . getDeviceByName ( udev . udev_resolve_devspec ( n ) )
2013-01-23 17:28:19 +00:00
# if this is a multipath member promote it to the real mpath
if disk and disk . format . type == " multipath_member " :
mpath_device = storage . devicetree . getChildren ( disk ) [ 0 ]
2014-04-07 12:38:09 +00:00
storage_log . info ( " kickstart: part: promoting %s to %s " ,
disk . name , mpath_device . name )
2013-01-23 17:28:19 +00:00
disk = mpath_device
2011-01-18 09:24:57 +00:00
if not disk :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " Specified nonexistent disk %s in partition command " % n ) )
2013-01-23 17:28:19 +00:00
if not disk . partitionable :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " Cannot install to read-only media %s . " % n ) )
2011-01-18 09:24:57 +00:00
2013-01-23 17:28:19 +00:00
should_clear = storage . shouldClear ( disk )
2011-01-18 09:24:57 +00:00
if disk and ( disk . partitioned or should_clear ) :
2013-01-23 17:28:19 +00:00
kwargs [ " parents " ] = [ disk ]
2011-01-18 09:24:57 +00:00
break
elif disk :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " Specified unpartitioned disk %s in partition command " % self . disk ) )
2011-01-18 09:24:57 +00:00
2013-01-23 17:28:19 +00:00
if not kwargs [ " parents " ] :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " Specified nonexistent disk %s in partition command " % self . disk ) )
2011-01-18 09:24:57 +00:00
kwargs [ " grow " ] = self . grow
kwargs [ " size " ] = self . size
kwargs [ " maxsize " ] = self . maxSizeMB
kwargs [ " primary " ] = self . primOnly
# If we were given a pre-existing partition to create a filesystem on,
# we need to verify it exists and then schedule a new format action to
# take place there. Also, we only support a subset of all the options
# on pre-existing partitions.
if self . onPart :
2014-04-07 12:38:09 +00:00
device = devicetree . getDeviceByName ( udev . udev_resolve_devspec ( self . onPart ) )
2011-01-18 09:24:57 +00:00
if not device :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " Specified nonexistent partition %s in partition command " % self . onPart ) )
2011-01-18 09:24:57 +00:00
removeExistingFormat ( device , storage )
2013-01-23 17:28:19 +00:00
if self . resize :
try :
devicetree . registerAction ( ActionResizeDevice ( device , self . size ) )
except ValueError :
raise KickstartValueError ( formatErrorMsg ( self . lineno ,
msg = " Invalid target size ( %d ) for device %s " % ( self . size , device . name ) ) )
2011-01-18 09:24:57 +00:00
devicetree . registerAction ( ActionCreateFormat ( device , kwargs [ " format " ] ) )
2014-04-07 12:38:09 +00:00
if ty == " swap " :
storage . addFstabSwap ( device )
# tmpfs mounts are not disks and don't occupy a disk partition,
# so handle them here
elif self . fstype == " tmpfs " :
request = storage . newTmpFS ( * * kwargs )
storage . createDevice ( request )
2011-01-18 09:24:57 +00:00
else :
# If a previous device has claimed this mount point, delete the
# old one.
try :
if self . mountpoint :
device = storage . mountpoints [ self . mountpoint ]
storage . destroyDevice ( device )
except KeyError :
pass
request = storage . newPartition ( * * kwargs )
storage . createDevice ( request )
2014-04-07 12:38:09 +00:00
if ty == " swap " :
storage . addFstabSwap ( request )
2011-01-18 09:24:57 +00:00
if self . encrypted :
if self . passphrase and not storage . encryptionPassphrase :
2014-04-07 12:38:09 +00:00
storage . encryptionPassphrase = self . passphrase
2011-01-18 09:24:57 +00:00
2013-01-23 17:28:19 +00:00
cert = getEscrowCertificate ( storage . escrowCertificates , self . escrowcert )
2011-01-18 09:24:57 +00:00
if self . onPart :
2014-04-07 12:38:09 +00:00
luksformat = kwargs [ " format " ]
2011-01-18 09:24:57 +00:00
device . format = getFormat ( " luks " , passphrase = self . passphrase , device = device . path ,
2013-01-23 17:28:19 +00:00
cipher = self . cipher ,
2011-01-18 09:24:57 +00:00
escrow_cert = cert ,
add_backup_passphrase = self . backuppassphrase )
luksdev = LUKSDevice ( " luks %d " % storage . nextID ,
format = luksformat ,
parents = device )
else :
luksformat = request . format
request . format = getFormat ( " luks " , passphrase = self . passphrase ,
2013-01-23 17:28:19 +00:00
cipher = self . cipher ,
2011-01-18 09:24:57 +00:00
escrow_cert = cert ,
add_backup_passphrase = self . backuppassphrase )
luksdev = LUKSDevice ( " luks %d " % storage . nextID ,
format = luksformat ,
parents = request )
storage . createDevice ( luksdev )
2014-04-07 12:38:09 +00:00
class Raid ( commands . raid . F20_Raid ) :
2013-01-23 17:28:19 +00:00
def execute ( self , storage , ksdata , instClass ) :
for r in self . raidList :
r . execute ( storage , ksdata , instClass )
2011-01-18 09:24:57 +00:00
2013-01-23 17:28:19 +00:00
class RaidData ( commands . raid . F18_RaidData ) :
def execute ( self , storage , ksdata , instClass ) :
2011-01-18 09:24:57 +00:00
raidmems = [ ]
devicetree = storage . devicetree
2014-04-07 12:38:09 +00:00
devicename = self . device
if self . preexist :
device = devicetree . resolveDevice ( devicename )
if device :
devicename = device . name
2011-01-18 09:24:57 +00:00
kwargs = { }
storage . doAutoPart = False
if self . mountpoint == " swap " :
2014-04-07 12:38:09 +00:00
ty = " swap "
2011-01-18 09:24:57 +00:00
self . mountpoint = " "
elif self . mountpoint . startswith ( " pv. " ) :
2014-04-07 12:38:09 +00:00
ty = " lvmpv "
2011-01-18 09:24:57 +00:00
kwargs [ " name " ] = self . mountpoint
2013-01-23 17:28:19 +00:00
ksdata . onPart [ kwargs [ " name " ] ] = devicename
2011-01-18 09:24:57 +00:00
if devicetree . getDeviceByName ( kwargs [ " name " ] ) :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " PV partition defined multiple times " ) )
2011-01-18 09:24:57 +00:00
2013-01-23 17:28:19 +00:00
self . mountpoint = " "
elif self . mountpoint . startswith ( " btrfs. " ) :
2014-04-07 12:38:09 +00:00
ty = " btrfs "
2013-01-23 17:28:19 +00:00
kwargs [ " name " ] = self . mountpoint
ksdata . onPart [ kwargs [ " name " ] ] = devicename
if devicetree . getDeviceByName ( kwargs [ " name " ] ) :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " BTRFS partition defined multiple times " ) )
2013-01-23 17:28:19 +00:00
2011-01-18 09:24:57 +00:00
self . mountpoint = " "
else :
if self . fstype != " " :
2014-04-07 12:38:09 +00:00
ty = self . fstype
2013-01-23 17:28:19 +00:00
elif self . mountpoint == " /boot " and \
" mdarray " in storage . bootloader . stage2_device_types :
2014-04-07 12:38:09 +00:00
ty = storage . defaultBootFSType
2011-01-18 09:24:57 +00:00
else :
2014-04-07 12:38:09 +00:00
ty = storage . defaultFSType
2011-01-18 09:24:57 +00:00
# Sanity check mountpoint
if self . mountpoint != " " and self . mountpoint [ 0 ] != ' / ' :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " The mount point is not valid. " ) )
2011-01-18 09:24:57 +00:00
# If this specifies an existing request that we should not format,
# quit here after setting up enough information to mount it later.
if not self . format :
if not devicename :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " --noformat used without --device " ) )
2011-01-18 09:24:57 +00:00
dev = devicetree . getDeviceByName ( devicename )
if not dev :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " No preexisting RAID device with the name \" %s \" was found. " % devicename ) )
2011-01-18 09:24:57 +00:00
dev . format . mountpoint = self . mountpoint
dev . format . mountopts = self . fsopts
return
# Get a list of all the RAID members.
for member in self . members :
2014-04-07 12:38:09 +00:00
dev = devicetree . resolveDevice ( member )
if not dev :
# if member is using --onpart, use original device
mem = ksdata . onPart . get ( member , member )
dev = devicetree . resolveDevice ( mem ) or lookupAlias ( devicetree , member )
2011-01-18 09:24:57 +00:00
if dev and dev . format . type == " luks " :
try :
dev = devicetree . getChildren ( dev ) [ 0 ]
except IndexError :
dev = None
2014-04-07 12:38:09 +00:00
if dev and dev . format . type != " mdmember " :
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " RAID member %s has incorrect format ( %s ) " % ( member , dev . format . type ) ) )
2011-01-18 09:24:57 +00:00
if not dev :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " Tried to use undefined partition %s in RAID specification " % member ) )
2011-01-18 09:24:57 +00:00
raidmems . append ( dev )
# Now get a format to hold a lot of these extra values.
2014-04-07 12:38:09 +00:00
kwargs [ " format " ] = getFormat ( ty ,
2013-01-23 17:28:19 +00:00
label = self . label ,
fsprofile = self . fsprofile ,
2011-01-18 09:24:57 +00:00
mountpoint = self . mountpoint ,
mountopts = self . fsopts )
2013-01-23 17:28:19 +00:00
if not kwargs [ " format " ] . type :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " The \" %s \" filesystem type is not supported. " % ty ) )
2011-01-18 09:24:57 +00:00
kwargs [ " name " ] = devicename
kwargs [ " level " ] = self . level
kwargs [ " parents " ] = raidmems
2013-01-23 17:28:19 +00:00
kwargs [ " memberDevices " ] = len ( raidmems ) - self . spares
kwargs [ " totalDevices " ] = len ( raidmems )
2011-01-18 09:24:57 +00:00
# If we were given a pre-existing RAID to create a filesystem on,
# we need to verify it exists and then schedule a new format action
# to take place there. Also, we only support a subset of all the
# options on pre-existing RAIDs.
if self . preexist :
device = devicetree . getDeviceByName ( devicename )
if not device :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " Specifeid nonexistent RAID %s in raid command " % devicename ) )
2011-01-18 09:24:57 +00:00
removeExistingFormat ( device , storage )
devicetree . registerAction ( ActionCreateFormat ( device , kwargs [ " format " ] ) )
else :
2014-04-07 12:38:09 +00:00
if devicename and devicename in ( a . name for a in storage . mdarrays ) :
2013-01-23 17:28:19 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " The Software RAID array name \" %s \" is already in use. " % devicename ) )
2011-01-18 09:24:57 +00:00
# If a previous device has claimed this mount point, delete the
# old one.
try :
if self . mountpoint :
device = storage . mountpoints [ self . mountpoint ]
storage . destroyDevice ( device )
except KeyError :
pass
try :
request = storage . newMDArray ( * * kwargs )
2013-01-23 17:28:19 +00:00
except ValueError as e :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = str ( e ) ) )
2011-01-18 09:24:57 +00:00
storage . createDevice ( request )
if self . encrypted :
if self . passphrase and not storage . encryptionPassphrase :
2014-04-07 12:38:09 +00:00
storage . encryptionPassphrase = self . passphrase
2011-01-18 09:24:57 +00:00
2013-01-23 17:28:19 +00:00
cert = getEscrowCertificate ( storage . escrowCertificates , self . escrowcert )
2011-01-18 09:24:57 +00:00
if self . preexist :
2014-04-07 12:38:09 +00:00
luksformat = kwargs [ " format " ]
2011-01-18 09:24:57 +00:00
device . format = getFormat ( " luks " , passphrase = self . passphrase , device = device . path ,
2013-01-23 17:28:19 +00:00
cipher = self . cipher ,
2011-01-18 09:24:57 +00:00
escrow_cert = cert ,
add_backup_passphrase = self . backuppassphrase )
luksdev = LUKSDevice ( " luks %d " % storage . nextID ,
format = luksformat ,
parents = device )
else :
luksformat = request . format
request . format = getFormat ( " luks " , passphrase = self . passphrase ,
2013-01-23 17:28:19 +00:00
cipher = self . cipher ,
2011-01-18 09:24:57 +00:00
escrow_cert = cert ,
add_backup_passphrase = self . backuppassphrase )
luksdev = LUKSDevice ( " luks %d " % storage . nextID ,
format = luksformat ,
parents = request )
storage . createDevice ( luksdev )
2014-04-07 12:38:09 +00:00
class RepoData ( commands . repo . F15_RepoData ) :
def __init__ ( self , * args , * * kwargs ) :
""" Add enabled kwarg
: param enabled : The repo has been enabled
: type enabled : bool
"""
self . enabled = kwargs . pop ( " enabled " , True )
commands . repo . F15_RepoData . __init__ ( self , * args , * * kwargs )
2013-01-23 17:28:19 +00:00
class RootPw ( commands . rootpw . F18_RootPw ) :
2013-02-12 01:30:33 +00:00
def __init__ ( self , writePriority = 100 , * args , * * kwargs ) :
if ' lock ' not in kwargs :
kwargs [ ' lock ' ] = True
super ( RootPw , self ) . __init__ ( writePriority = writePriority , * args , * * kwargs )
2013-01-23 17:28:19 +00:00
def execute ( self , storage , ksdata , instClass , users ) :
2014-04-07 12:38:09 +00:00
if not self . password and not flags . automatedInstall :
self . lock = True
2013-01-23 17:28:19 +00:00
algo = getPassAlgo ( ksdata . authconfig . authconfig )
users . setRootPassword ( self . password , self . isCrypted , self . lock , algo )
2011-01-18 09:24:57 +00:00
class SELinux ( commands . selinux . FC3_SELinux ) :
2013-01-23 17:28:19 +00:00
def execute ( self , * args ) :
selinux_states = { SELINUX_DISABLED : " disabled " ,
SELINUX_ENFORCING : " enforcing " ,
SELINUX_PERMISSIVE : " permissive " }
2011-01-18 09:24:57 +00:00
2013-01-23 17:28:19 +00:00
if self . selinux not in selinux_states :
2014-04-07 12:38:09 +00:00
log . error ( " unknown selinux state: %s " , self . selinux )
2013-01-23 17:28:19 +00:00
return
2011-01-18 09:24:57 +00:00
2013-01-23 17:28:19 +00:00
try :
selinux_cfg = SimpleConfigFile ( ROOT_PATH + " /etc/selinux/config " )
selinux_cfg . read ( )
selinux_cfg . set ( ( " SELINUX " , selinux_states [ self . selinux ] ) )
selinux_cfg . write ( )
except IOError as msg :
2014-04-07 12:38:09 +00:00
log . error ( " Error setting selinux mode: %s " , msg )
2013-01-23 17:28:19 +00:00
class Services ( commands . services . FC6_Services ) :
def execute ( self , storage , ksdata , instClass ) :
2014-04-07 12:38:09 +00:00
for svc in self . disabled :
if not svc . endswith ( " .service " ) :
svc + = " .service "
2013-01-23 17:28:19 +00:00
2014-04-07 12:38:09 +00:00
iutil . execWithRedirect ( " systemctl " , [ " disable " , svc ] ,
2013-01-23 17:28:19 +00:00
root = ROOT_PATH )
2014-04-07 12:38:09 +00:00
for svc in self . enabled :
if not svc . endswith ( " .service " ) :
svc + = " .service "
iutil . execWithRedirect ( " systemctl " , [ " enable " , svc ] ,
2013-01-23 17:28:19 +00:00
root = ROOT_PATH )
class Timezone ( commands . timezone . F18_Timezone ) :
def __init__ ( self , * args ) :
commands . timezone . F18_Timezone . __init__ ( self , * args )
2014-04-07 12:38:09 +00:00
self . _added_chrony = False
self . _enabled_chrony = False
def setup ( self , ksdata ) :
if self . nontp :
if iutil . service_running ( NTP_SERVICE ) and \
can_touch_runtime_system ( " stop NTP service " ) :
ret = iutil . stop_service ( NTP_SERVICE )
if ret != 0 :
log . error ( " Failed to stop NTP service " )
if self . _added_chrony and NTP_PACKAGE in ksdata . packages . packageList :
ksdata . packages . packageList . remove ( NTP_PACKAGE )
self . _added_chrony = False
if self . _enabled_chrony and NTP_SERVICE in ksdata . services . enabled :
ksdata . services . enabled . remove ( NTP_SERVICE )
self . _enabled_chrony = False
else :
if not iutil . service_running ( NTP_SERVICE ) and \
can_touch_runtime_system ( " start NTP service " ) :
ret = iutil . start_service ( NTP_SERVICE )
if ret != 0 :
log . error ( " Failed to start NTP service " )
if not NTP_PACKAGE in ksdata . packages . packageList :
ksdata . packages . packageList . append ( NTP_PACKAGE )
self . _added_chrony = True
if not NTP_SERVICE in ksdata . services . enabled and \
not NTP_SERVICE in ksdata . services . disabled :
ksdata . services . enabled . append ( NTP_SERVICE )
self . _enabled_chrony = True
2013-01-23 17:28:19 +00:00
def execute ( self , * args ) :
# write out timezone configuration
if not timezone . is_valid_timezone ( self . timezone ) :
# this should never happen, but for pity's sake
log . warning ( " Timezone %s set in kickstart is not valid, falling " \
2014-04-07 12:38:09 +00:00
" back to default (America/New_York). " , self . timezone )
2013-01-23 17:28:19 +00:00
self . timezone = " America/New_York "
timezone . write_timezone_config ( self , ROOT_PATH )
# write out NTP configuration (if set)
if not self . nontp and self . ntpservers :
chronyd_conf_path = os . path . normpath ( ROOT_PATH + ntp . NTP_CONFIG_FILE )
try :
ntp . save_servers_to_config ( self . ntpservers ,
conf_file_path = chronyd_conf_path )
except ntp . NTPconfigError as ntperr :
2014-04-07 12:38:09 +00:00
log . warning ( " Failed to save NTP configuration: %s " , ntperr )
2013-01-23 17:28:19 +00:00
2014-04-07 12:38:09 +00:00
class User ( commands . user . F19_User ) :
2013-01-23 17:28:19 +00:00
def execute ( self , storage , ksdata , instClass , users ) :
algo = getPassAlgo ( ksdata . authconfig . authconfig )
for usr in self . userList :
kwargs = usr . __dict__
kwargs . update ( { " algo " : algo , " root " : ROOT_PATH } )
2014-04-07 12:38:09 +00:00
users . createUser ( usr . name , * * kwargs )
2013-01-23 17:28:19 +00:00
2014-04-07 12:38:09 +00:00
class VolGroup ( commands . volgroup . F20_VolGroup ) :
2013-01-23 17:28:19 +00:00
def execute ( self , storage , ksdata , instClass ) :
for v in self . vgList :
v . execute ( storage , ksdata , instClass )
class VolGroupData ( commands . volgroup . FC16_VolGroupData ) :
def execute ( self , storage , ksdata , instClass ) :
2011-01-18 09:24:57 +00:00
pvs = [ ]
devicetree = storage . devicetree
storage . doAutoPart = False
# Get a list of all the physical volume devices that make up this VG.
for pv in self . physvols :
2014-04-07 12:38:09 +00:00
dev = devicetree . resolveDevice ( pv )
if not dev :
# if pv is using --onpart, use original device
pv_name = ksdata . onPart . get ( pv , pv )
dev = devicetree . resolveDevice ( pv_name ) or lookupAlias ( devicetree , pv )
2011-01-18 09:24:57 +00:00
if dev and dev . format . type == " luks " :
try :
dev = devicetree . getChildren ( dev ) [ 0 ]
except IndexError :
dev = None
2014-04-07 12:38:09 +00:00
if dev and dev . format . type != " lvmpv " :
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " Physical Volume %s has incorrect format ( %s ) " % ( pv , dev . format . type ) ) )
2011-01-18 09:24:57 +00:00
if not dev :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " Tried to use undefined partition %s in Volume Group specification " % pv ) )
2011-01-18 09:24:57 +00:00
pvs . append ( dev )
if len ( pvs ) == 0 and not self . preexist :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " Volume group defined without any physical volumes. Either specify physical volumes or use --useexisting. " ) )
2011-01-18 09:24:57 +00:00
if self . pesize not in getPossiblePhysicalExtents ( floor = 1024 ) :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " Volume group specified invalid pesize " ) )
2011-01-18 09:24:57 +00:00
# If --noformat or --useexisting was given, there's really nothing to do.
if not self . format or self . preexist :
if not self . vgname :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " --noformat or --useexisting used without giving a name " ) )
2011-01-18 09:24:57 +00:00
dev = devicetree . getDeviceByName ( self . vgname )
if not dev :
2014-04-07 12:38:09 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " No preexisting VG with the name \" %s \" was found. " % self . vgname ) )
elif self . vgname in ( vg . name for vg in storage . vgs ) :
2013-01-23 17:28:19 +00:00
raise KickstartValueError ( formatErrorMsg ( self . lineno , msg = " The volume group name \" %s \" is already in use. " % self . vgname ) )
2011-01-18 09:24:57 +00:00
else :
2013-01-23 17:28:19 +00:00
request = storage . newVG ( parents = pvs ,
2011-01-18 09:24:57 +00:00
name = self . vgname ,
peSize = self . pesize / 1024.0 )
storage . createDevice ( request )
2013-01-23 17:28:19 +00:00
if self . reserved_space :
request . reserved_space = self . reserved_space
elif self . reserved_percent :
request . reserved_percent = self . reserved_percent
2014-04-07 12:38:09 +00:00
# in case we had to truncate or otherwise adjust the specified name
ksdata . onPart [ self . vgname ] = request . name
2013-01-23 17:28:19 +00:00
class XConfig ( commands . xconfig . F14_XConfig ) :
def execute ( self , * args ) :
desktop = Desktop ( )
2011-01-18 09:24:57 +00:00
if self . startX :
2014-04-07 12:38:09 +00:00
desktop . runlevel = 5
2011-01-18 09:24:57 +00:00
if self . defaultdesktop :
2014-04-07 12:38:09 +00:00
desktop . desktop = self . defaultdesktop
2011-01-18 09:24:57 +00:00
2013-01-23 17:28:19 +00:00
# now write it out
desktop . write ( )
2011-01-18 09:24:57 +00:00
2013-01-23 17:28:19 +00:00
class ZFCP ( commands . zfcp . F14_ZFCP ) :
2011-01-18 09:24:57 +00:00
def parse ( self , args ) :
2013-01-23 17:28:19 +00:00
fcp = commands . zfcp . F14_ZFCP . parse ( self , args )
2011-01-18 09:24:57 +00:00
try :
2014-04-07 12:38:09 +00:00
blivet . zfcp . ZFCP ( ) . addFCP ( fcp . devnum , fcp . wwpn , fcp . fcplun )
2013-01-23 17:28:19 +00:00
except ValueError as e :
2011-01-18 09:24:57 +00:00
log . warning ( str ( e ) )
return fcp
2013-01-23 17:28:19 +00:00
class Keyboard ( commands . keyboard . F18_Keyboard ) :
def execute ( self , * args ) :
keyboard . write_keyboard_config ( self , ROOT_PATH )
def dracutSetupArgs ( self , * args ) :
2014-04-07 12:38:09 +00:00
return keyboard . dracut_setup_args ( )
class SpokeRegistry ( dict ) :
""" This class represents the ksdata.firstboot object and
maintains the ids of all user configured spokes .
The information is then used by inital_setup and GIE
to hide already configured spokes .
"""
def __str__ ( self ) :
# do not write anything into kickstart
return " "
def execute ( self , storage , ksdata , instClass , users ) :
path = os . path . join ( ROOT_PATH , " var " , " lib " , " inital-setup " )
try :
os . makedirs ( path , 0755 )
except OSError :
pass
f = open ( os . path . join ( path , " configured.ini " ) , " a " )
for k , v in self . iteritems ( ) :
f . write ( " %s = %s \n " % ( k , v ) )
f . close ( )
2013-01-23 17:28:19 +00:00
2011-01-18 09:24:57 +00:00
###
### HANDLERS
###
# This is just the latest entry from pykickstart.handlers.control with all the
# classes we're overriding in place of the defaults.
commandMap = {
" auth " : Authconfig ,
" authconfig " : Authconfig ,
" autopart " : AutoPart ,
2013-01-23 17:28:19 +00:00
" btrfs " : BTRFS ,
2011-01-18 09:24:57 +00:00
" bootloader " : Bootloader ,
" clearpart " : ClearPart ,
" dmraid " : DmRaid ,
2014-04-07 12:38:09 +00:00
" eula " : Eula ,
2011-01-18 09:24:57 +00:00
" fcoe " : Fcoe ,
" firewall " : Firewall ,
2013-01-23 17:28:19 +00:00
" firstboot " : Firstboot ,
" group " : Group ,
2011-01-18 09:24:57 +00:00
" ignoredisk " : IgnoreDisk ,
" iscsi " : Iscsi ,
" iscsiname " : IscsiName ,
" keyboard " : Keyboard ,
" lang " : Lang ,
" logging " : Logging ,
2013-01-23 17:28:19 +00:00
" logvol " : LogVol ,
2011-01-18 09:24:57 +00:00
" multipath " : MultiPath ,
2013-01-23 17:28:19 +00:00
" network " : Network ,
" part " : Partition ,
" partition " : Partition ,
" raid " : Raid ,
2014-04-07 12:38:09 +00:00
" realm " : Realm ,
2011-01-18 09:24:57 +00:00
" rootpw " : RootPw ,
" selinux " : SELinux ,
2013-01-23 17:28:19 +00:00
" services " : Services ,
2011-01-18 09:24:57 +00:00
" timezone " : Timezone ,
2013-01-23 17:28:19 +00:00
" user " : User ,
" volgroup " : VolGroup ,
2011-01-18 09:24:57 +00:00
" xconfig " : XConfig ,
" zfcp " : ZFCP ,
}
dataMap = {
2013-01-23 17:28:19 +00:00
" BTRFSData " : BTRFSData ,
2011-01-18 09:24:57 +00:00
" LogVolData " : LogVolData ,
" PartData " : PartitionData ,
" RaidData " : RaidData ,
2014-04-07 12:38:09 +00:00
" RepoData " : RepoData ,
2011-01-18 09:24:57 +00:00
" VolGroupData " : VolGroupData ,
}
superclass = returnClassForVersion ( )
class AnacondaKSHandler ( superclass ) :
2014-04-07 12:38:09 +00:00
AddonClassType = AddonData
def __init__ ( self , addon_paths = None , commandUpdates = None , dataUpdates = None ) :
if addon_paths is None :
addon_paths = [ ]
if commandUpdates is None :
commandUpdates = commandMap
if dataUpdates is None :
dataUpdates = dataMap
superclass . __init__ ( self , commandUpdates = commandUpdates , dataUpdates = dataUpdates )
2011-01-18 09:24:57 +00:00
self . onPart = { }
2014-04-07 12:38:09 +00:00
# collect all kickstart addons for anaconda to addons dictionary
# which maps addon_id to it's own data structure based on BaseData
# with execute method
addons = { }
# collect all AddonData subclasses from
# for p in addon_paths: <p>/<plugin id>/ks/*.(py|so)
# and register them under <plugin id> name
for module_name , path in addon_paths :
addon_id = os . path . basename ( os . path . dirname ( os . path . abspath ( path ) ) )
if not os . path . isdir ( path ) :
continue
classes = collect ( module_name , path , lambda cls : issubclass ( cls , self . AddonClassType ) )
if classes :
addons [ addon_id ] = classes [ 0 ] ( name = addon_id )
# Prepare the structure to track configured spokes
self . configured_spokes = SpokeRegistry ( )
# Prepare the final structures for 3rd party addons
self . addons = AddonRegistry ( addons )
def __str__ ( self ) :
return superclass . __str__ ( self ) + " \n " + str ( self . addons )
2011-01-18 09:24:57 +00:00
class AnacondaPreParser ( KickstartParser ) :
# A subclass of KickstartParser that only looks for %pre scripts and
# sets them up to be run. All other scripts and commands are ignored.
def __init__ ( self , handler , followIncludes = True , errorsAreFatal = True ,
missingIncludeIsFatal = True ) :
KickstartParser . __init__ ( self , handler , missingIncludeIsFatal = False )
def handleCommand ( self , lineno , args ) :
pass
2013-01-23 17:28:19 +00:00
def setupSections ( self ) :
self . registerSection ( PreScriptSection ( self . handler , dataObj = AnacondaKSScript ) )
self . registerSection ( NullSection ( self . handler , sectionOpen = " % post " ) )
self . registerSection ( NullSection ( self . handler , sectionOpen = " % traceback " ) )
self . registerSection ( NullSection ( self . handler , sectionOpen = " % packages " ) )
2014-04-07 12:38:09 +00:00
self . registerSection ( NullSection ( self . handler , sectionOpen = " %a ddon " ) )
2011-01-18 09:24:57 +00:00
class AnacondaKSParser ( KickstartParser ) :
def __init__ ( self , handler , followIncludes = True , errorsAreFatal = True ,
2013-01-23 17:28:19 +00:00
missingIncludeIsFatal = True , scriptClass = AnacondaKSScript ) :
self . scriptClass = scriptClass
2011-01-18 09:24:57 +00:00
KickstartParser . __init__ ( self , handler )
def handleCommand ( self , lineno , args ) :
if not self . handler :
return
2013-01-23 17:28:19 +00:00
return KickstartParser . handleCommand ( self , lineno , args )
def setupSections ( self ) :
self . registerSection ( PreScriptSection ( self . handler , dataObj = self . scriptClass ) )
self . registerSection ( PostScriptSection ( self . handler , dataObj = self . scriptClass ) )
self . registerSection ( TracebackScriptSection ( self . handler , dataObj = self . scriptClass ) )
self . registerSection ( PackageSection ( self . handler ) )
2014-04-07 12:38:09 +00:00
self . registerSection ( AddonSection ( self . handler ) )
2011-01-18 09:24:57 +00:00
2013-01-23 17:28:19 +00:00
def preScriptPass ( f ) :
2011-01-18 09:24:57 +00:00
# The first pass through kickstart file processing - look for %pre scripts
# and run them. This must come in a separate pass in case a script
# generates an included file that has commands for later.
2013-01-23 17:28:19 +00:00
ksparser = AnacondaPreParser ( AnacondaKSHandler ( ) )
2011-01-18 09:24:57 +00:00
try :
2013-01-23 17:28:19 +00:00
ksparser . readKickstart ( f )
except KickstartError as e :
2014-04-07 12:38:09 +00:00
# We do not have an interface here yet, so we cannot use our error
# handling callback.
print e
2013-01-23 17:28:19 +00:00
sys . exit ( 1 )
2011-01-18 09:24:57 +00:00
# run %pre scripts
2013-01-23 17:28:19 +00:00
runPreScripts ( ksparser . handler . scripts )
2011-01-18 09:24:57 +00:00
2013-01-23 17:28:19 +00:00
def parseKickstart ( f ) :
# preprocessing the kickstart file has already been handled in initramfs.
2011-01-18 09:24:57 +00:00
2014-04-07 12:38:09 +00:00
addon_paths = collect_addon_paths ( ADDON_PATHS )
handler = AnacondaKSHandler ( addon_paths [ " ks " ] )
2011-01-18 09:24:57 +00:00
ksparser = AnacondaKSParser ( handler )
# We need this so all the /dev/disk/* stuff is set up before parsing.
2014-04-07 12:38:09 +00:00
udev . udev_trigger ( subsystem = " block " , action = " change " )
2011-01-18 09:24:57 +00:00
# So that drives onlined by these can be used in the ks file
2014-04-07 12:38:09 +00:00
blivet . iscsi . iscsi ( ) . startup ( )
blivet . fcoe . fcoe ( ) . startup ( )
blivet . zfcp . ZFCP ( ) . startup ( )
2011-01-18 09:24:57 +00:00
# Note we do NOT call dasd.startup() here, that does not online drives, but
# only checks if they need formatting, which requires zerombr to be known
try :
2013-01-23 17:28:19 +00:00
ksparser . readKickstart ( f )
except KickstartError as e :
2014-04-07 12:38:09 +00:00
# We do not have an interface here yet, so we cannot use our error
# handling callback.
print e
2013-01-23 17:28:19 +00:00
sys . exit ( 1 )
2011-01-18 09:24:57 +00:00
return handler
2013-01-23 17:28:19 +00:00
def appendPostScripts ( ksdata ) :
scripts = " "
2011-01-18 09:24:57 +00:00
2013-01-23 17:28:19 +00:00
# Read in all the post script snippets to a single big string.
for fn in glob . glob ( " /usr/share/anaconda/post-scripts/*ks " ) :
f = open ( fn , " r " )
scripts + = f . read ( )
f . close ( )
# Then parse the snippets against the existing ksdata. We can do this
# because pykickstart allows multiple parses to save their data into a
# single data object. Errors parsing the scripts are a bug in anaconda,
# so just raise an exception.
ksparser = AnacondaKSParser ( ksdata , scriptClass = AnacondaInternalScript )
ksparser . readKickstartFromString ( scripts , reset = False )
def runPostScripts ( scripts ) :
postScripts = filter ( lambda s : s . type == KS_SCRIPT_POST , scripts )
2011-01-18 09:24:57 +00:00
if len ( postScripts ) == 0 :
return
# Remove environment variables that cause problems for %post scripts.
for var in [ " LIBUSER_CONF " ] :
if os . environ . has_key ( var ) :
del ( os . environ [ var ] )
log . info ( " Running kickstart %% post script(s) " )
2013-01-23 17:28:19 +00:00
map ( lambda s : s . run ( ROOT_PATH ) , postScripts )
2011-01-18 09:24:57 +00:00
log . info ( " All kickstart %% post script(s) have been run " )
2013-01-23 17:28:19 +00:00
def runPreScripts ( scripts ) :
2011-01-18 09:24:57 +00:00
preScripts = filter ( lambda s : s . type == KS_SCRIPT_PRE , scripts )
if len ( preScripts ) == 0 :
return
log . info ( " Running kickstart %% pre script(s) " )
2013-01-23 17:28:19 +00:00
stdoutLog . info ( _ ( " Running pre-installation scripts " ) )
map ( lambda s : s . run ( " / " ) , preScripts )
2011-01-18 09:24:57 +00:00
log . info ( " All kickstart %% pre script(s) have been run " )
2013-01-23 17:28:19 +00:00
def runTracebackScripts ( scripts ) :
2011-01-18 09:24:57 +00:00
log . info ( " Running kickstart %% traceback script(s) " )
2013-01-23 17:28:19 +00:00
for script in filter ( lambda s : s . type == KS_SCRIPT_TRACEBACK , scripts ) :
script . run ( " / " )
2011-01-18 09:24:57 +00:00
log . info ( " All kickstart %% traceback script(s) have been run " )
2013-01-23 17:28:19 +00:00
def doKickstartStorage ( storage , ksdata , instClass ) :
""" Setup storage state from the kickstart data """
ksdata . clearpart . execute ( storage , ksdata , instClass )
2014-04-07 12:38:09 +00:00
if not any ( d for d in storage . disks
if not d . format . hidden and not d . protected ) :
2011-01-18 09:24:57 +00:00
return
2013-01-23 17:28:19 +00:00
ksdata . bootloader . execute ( storage , ksdata , instClass )
ksdata . autopart . execute ( storage , ksdata , instClass )
ksdata . partition . execute ( storage , ksdata , instClass )
ksdata . raid . execute ( storage , ksdata , instClass )
ksdata . volgroup . execute ( storage , ksdata , instClass )
ksdata . logvol . execute ( storage , ksdata , instClass )
ksdata . btrfs . execute ( storage , ksdata , instClass )
2014-04-07 12:38:09 +00:00
# also calls ksdata.bootloader.execute
2013-01-23 17:28:19 +00:00
storage . setUpBootLoader ( )
2011-01-18 09:24:57 +00:00