Converting from Spacewalk Profiles to Foreman Kickstart template - %pre script question

I am converting Spacewalk Profiles that have been developed over a decade to Foreman Kickstart templates. Kickstart files allow %pre and %post scripts to specify of an interpreter (i.e. python, perl, etc.) to run the script. In Spacewalk Profiles, script definitions have a field to specify this value (defaults to bash). I am new to Embedded Ruby, and need some guidance on possible capabilities.

Is there a method of examining an object or snippet to look for a shebang (#!) in the first line and select the interpreter accordingly?

Example:

<% if @dynamic -%>
# Put code here to analyze first line of @host.diskLayout and read any shebang into a variable
# Then dynamically build the %pre line
%pre --interpreter /usr/bin/python --log /tmp/ks-part.log
<%= @host.diskLayout %>
<%= section_end -%>
<% end -%>

Thank you,

1 Like

Hello, I am afraid I don’t understand what you need to do. However, our ERB is just Ruby standard ERB - grab any tutorial and you should be good to go. There is a list of available macros and variables on the Help tab on the Edit template page.

I’m in the same boat, the better part of 10 years of fairly highly customized installs through Spacewalk/RHSat5. I started going down the road of converting the kickstarts, and it took me a bit to figure out that I’d be better off to not try to pull Spacewalk constructs & methodology over. Far better off to start from scratch and figure out how to do the tasks natively.

You’ve referenced disk layouts… At least using the Katello plug-in, I can define my own partition table. What is important is that it begins:

#Dynamic

The pre-script execution during the kickstart does use basic shells, not ERB, etc. At least from initial trials, I can successfully generate a partition tables to the standard here.

As far as post-execution scripts go, I’m pretty sure that the majority of those will get handled through Puppet or Ansible tasks, rather than modifying the default provisioning templates. I suspect that only madness lies down that road.

Probably lack of understanding of how this works in Satellite 5, I am really not able to understand you both or help. However if you break the problem into smaller parts I might be able to provide guidance on how to write your templates.

You can of course generate either static content or scripts (Python, Shell) via ERB. It gets tricky a bit, but it’s definitely possible.

I already have a Dynamic partition table script, but it is complex and written in Python, instead of Bash.

If I modify a Kickstart Provisioning template to replace:
<% if @dynamic -%>
%pre
<%= @host.diskLayout %>
<%= section_end -%>
<% end -%>

with:
<% if @dynamic -%>
%pre --interpreter /usr/bin/python --log /tmp/ks-part.log
<%= @host.diskLayout %>
<%= section_end -%>
<% end -%>

It works, but I was wondering if there was a way to test the first line of the the Partition Table template for a shebahg (#! /usr/bin/python) and dynamically select the correct interpreter.

It should be possible (untested, expecially not in safe mode rendering):

<% if @host.diskLayout.start_with?('#!/usr/bin/python') -%>
%pre --interpreter /usr/bin/python --log /tmp/ks-part.log
<% else -%>
...
<% end -%>

Thanks TimoGoebel,

I cloned the Kickstart default provisioning template and replaced:

<% if @dynamic -%>
%pre
<%= @host.diskLayout %>
<%= section_end -%>
<% end -%>

with the following:

<% if @dynamic -%>
<% if @host.diskLayout.start_with?('#!') -%>
<% endOfLine = @host.diskLayout.index(/\n/) - 1 -%>
%pre --interperter <%= "#{@host.diskLayout[2..endOfLine]}" -%> --log /tmp/diskpart.log
<% else -%>
%pre --log /tmp/diskpart.log
<% end -%>
<%= @host.diskLayout %>
<%= section_end -%>
<% end %>

This is my Partition table template:

#!/usr/bin/python
#Dynamic
# ------------------------------------------------------------------------------
# RHEL Version 7.x Kickstart script to probe for storage devices (hard drives,
# LUNs, etc.) and create Kickstart bootloader, clearpart, partition, and logical
# volume options in the file /tmp/diskpart.cfg. Kickstart variables may be used to 
# control script behavior
# Kickstart variables: (sizes ae in MB)
#     rootMax      - maximum size of / file system. Default: 16384
#     tmpMax       - maximum size of /tmp file system. Default: 4096
#     varMax       - maximum size of /var file system. Default: 4096
#     logMax       - maximum size of /var/log file system. Default: 4096
#     optMax       - maximum size of /var/log file system. Default: 4096
#     auditMax     - maximum size of /var/log/audit file system. Default: 2048
#     homeMax      - maximum size of /home file system. Default: Default: 4096
#     rootPercent  - percent of boot drive to use for / file system. Default: 25% (0.25)
#     tmpPercent   - percent of boot drive to use for /tmp file system. Default: 10% (0.1)
#     varPercent   - percent of boot drive to use for /var file system. Default: 10% (0.1)
#     logPercent   - percent of boot drive to use for /var/log file system. Default: 10% (0.1)
#     optPercent   - percent of boot drive to use for /var/opt file system. Default: 10% (0.1)
#     auditPercent - percent of boot drive to use for /var/log/audit file system. Default: 5% (0.05)
#     homePercent  - percent of boot drive to use for /home file system. Default: 10% (0.1)
#     opt          - flag (True|False) to create the /opt file system. Default: True
#     lastBiosDisk - highest BIOS Int13 Disk ID (0x80, 0x81 ...) to include in
#                    the configuration, all additional BIOS drives will be
#                    treated as "otherDisks". Default: 0x8f
#     otherDisks   - Python dictionary like list of drive models and number
#                    of each model of drive to include in configuration
#                    (i.e. 'Dell PERC 6/i': 2, 'HITACHI OPEN-V': 4, 'NETAPP LUN': 0, 'HP HSV400': 0, 'VMware Virtual disk': 0)
#                    Default: {} (empty dictionary)
#    lvCount       - Maximum number of optional Logical Volumes to create. Default: 16
#    lvName#       - Name of optional LV to create (where # is integer up to lvCount)
#    lvMount#      - Mount point for optional LV (where # is integer up to lvCount) Default: '/'
#    lvGroup#      - Preferred Voulme Group for optional LV (where # is integer up to lvCount) Default: 1 => datavg1
#    lvSize#       - LV Size in GB (where # is integer up to lvCount). Default: 1024
#    lvFsType#     - LV File System Type. Default: ext4
# Version 1.00 Released 05/10/2019
# ------------------------------------------------------------------------------
<%#
kind: ptable
name: Kickstart dynamic
model: Ptable
oses:
- CentOS
- Fedora
- RedHat
-%>
<%#
This template accepts the following parameters:
- fsType       - file system type for default file systems. Default: xfs
- rootMax      - maximum size of / file system. Default: 16384
- tmpMax       - maximum size of /tmp file system. Default: 4096
- varMax       - maximum size of /var file system. Default: 4096
- logMax       - maximum size of /var/log file system. Default: 4096
- optMax       - maximum size of /var/log file system. Default: 4096
- auditMax     - maximum size of /var/log/audit file system. Default: 2048
- homeMax      - maximum size of /home file system. Default: Default: 4096
- rootPercent  - percent of boot drive to use for / file system. Default: 25% (0.25)
- tmpPercent   - percent of boot drive to use for /tmp file system. Default: 10% (0.1)
- varPercent   - percent of boot drive to use for /var file system. Default: 10% (0.1)
- logPercent   - percent of boot drive to use for /var/log file system. Default: 10% (0.1)
- optPercent   - percent of boot drive to use for /var/opt file system. Default: 10% (0.1)
- auditPercent - percent of boot drive to use for /var/log/audit file system. Default: 5% (0.05)
- homePercent  - percent of boot drive to use for /home file system. Default: 10% (0.1)
- opt          - flag (True|False) to create the /opt file system. Default: True
- lastBiosDisk - highest BIOS Int13 Disk ID (0x80, 0x81 ...) to include in
-                the configuration, all additional BIOS drives will be
-                treated as "otherDisks". Default: 0x8f
- otherDisks   - Python dictionary like list of drive models and number
-                of each model of drive to include in configuration
-                (i.e. 'Dell PERC 6/i': 2, 'HITACHI OPEN-V': 4, 'NETAPP LUN': 0, 'HP HSV400': 0, 'VMware Virtual disk': 0)
-                Default: {} (empty dictionary)
- lvCount       - Maximum number of optional Logical Volumes to create. Default: 16
- lvName-   - Name of optional LV to create (where # is integer up to lvCount)
- lvMount-  - Mount point for optional LV (where # is integer up to lvCount) Default: '/'
- lvGroup-  - Preferred Voulme Group for optional LV (where # is integer up to lvCount) Default: 1 => datavg1
- lvSize-   - LV Size in GB (where # is integer up to lvCount). Default: 1024
- lvFsType- - LV File System Type. Default: ext4
-%>
#
# ------------------------------------------------------------------------------
# Set sizing rule values, defaults can be overridden with Host parameters
# ------------------------------------------------------------------------------
fsType       = <%= host_param('fsType') || 'xfs' %>
rootMax      = <%= host_param('rootMax') || '8192' %>
tmpMax       = <%= host_param('tmpMax') || '4096' %>
varMax       = <%= host_param('varMax') || '4096' %>
logMax       = <%= host_param('logMax') || '4096' %>
optMax       = <%= host_param('optMax') || '4096' %>
auditMax     = <%= host_param('auditMax') || '2048' %>
homeMax      = <%= host_param('homeMax') || '4096' %>
rootPercent  = <%= host_param('rootPercent') || '0.25' %>
tmpPercent   = <%= host_param('tmpPercent') || '0.1' %>
varPercent   = <%= host_param('varPercent') || '0.1' %>
logPercent   = <%= host_param('logPercent') || '0.1' %>
optPercent   = <%= host_param('optPercent') || '0.1' %>
auditPercent = <%= host_param('auditPercent') || '0.05' %>
homePercent  = <%= host_param('homePercent') || '0.1' %>
opt          = <%= host_param('opt') || 'True' %>
lastBiosDisk = <%= host_param('lastBiosDisk') || '0x81' %>
otherDisks   = {<%= host_param('otherDisks') || "'VMware Virtual disk': 4" %>}

optionalLVs   = {}
<% 
    lvCount = host_param('lvCount') || '16'
    (1..lvCount.to_i).each do |i|
    iStr = i.to_s
-%>
<% if host_param('lvName' + iStr) -%>
optionalLVs ['<%= host_param('lvName' + iStr) -%>'] = ('<%= host_param('lvMount' + iStr).to_s.sub(/\/\z/, '') -%>', '<%= host_param('lvGroup' + iStr) || '1' -%>', <%= host_param('lvSize' + iStr) || '1024' -%>, '<%= host_param('lvFsType' + iStr) || 'xfs' -%>')
<% end -%>
<% end -%>

# ------------------------------------------------------------------------------
# Import libraries
# ------------------------------------------------------------------------------
import sys, os, re, parted                      # Import standard libraries
from itertools import repeat
import blivet

# ------------------------------------------------------------------------------
# Define local functions
# ------------------------------------------------------------------------------
def sortedDictValues(aDict):                    # Function to sort a dictionary by its keys
    items = aDict.items()                       # Get the dictionarys items as a lit of tuples (key, value)
    items.sort()                                # Sort the list
    return [value for key, value in items]      # Return a list of the values

                                                # Function to return Subset of a Dictionary
dictSubset = lambda x, y: dict(zip(x, map(y.get, x)))

# ------------------------------------------------------------------------------
# Create empty dictionaries and lists
# ------------------------------------------------------------------------------
biosDisks           = {}                        # Dictinary of BOIS Disk Names, by BIOS ID (0x80, 0x81, 0x82 ...)
allDiskModelsSizes  = {}                        # Dictionary of Disk Models/Sizes by Device Name
mpathNames          = {}                        # Dictionary of Multipath Devices by Member Name
mpathMemberNames    = {}                        # Dictionary of Member Names by Multipath Device Name
lstOtherDisks       = []                        # List of non-BIOS Disks
lstMPathNames       = []                        # List of Multipath Device Names
lstMPathMemberNames = []                        # List of Multipath Member Names

# ------------------------------------------------------------------------------
# Check if system is UEFI
# ------------------------------------------------------------------------------
if os.path.isdir('/sys/firmware/efi'):
    uEFI = True
else:
    uEFI = False

# ------------------------------------------------------------------------------
# Find Physical Memory size by analyzing the memory map
# ------------------------------------------------------------------------------
iomemFile = open('/proc/iomem', 'r')            # Open /proc/meminfo read-only
for line in iomemFile:                          # For each line in the "file"
                                                # Look for lines containing "System RAM"
    if re.search('System RAM', line) is not None:
                                                # Get the memory range from the line
        memRange = tuple(map(int, line.split(':', 1)[0].split('-'), repeat(16, 2)))
iomemFile.close()                               # Close the file
                                                # Convert the highest memory range to GB
sysMem = (memRange[1] + 1.0) / (1024 * 1024 * 1024)
if sysMem > 4:                                  # If the result is greater than 4GB
    sysMem = sysMem - 1                         # Adjust for Extended Memory mapping

# ------------------------------------------------------------------------------
# Find the Single and Multipath disks
# ------------------------------------------------------------------------------
storageConfig = blivet.Blivet()                 # Create a storage configuration object
storageConfig.reset()                           # Read the current storage config
drives = storageConfig.disks                    # Get a list of all Storage Device objects

for drive in drives:                            # For each discovered drive
                                                # Get the Vendor/Model string and Size
    allDiskModelsSizes[drive.path[5:]] = (drive.vendor +
                                          ' ' +
                                          drive.model,
                                          int(drive.size.convertTo('MiB')))
                                     
    if drive.type == 'dm-multipath':            # If the drive is a Multipath device
        lstMPathNames.append(drive.path[5:])    # Add the drive name to the list of Multipath devices
        for parent in drive.parents:            # For each parent of the Multipath device
                                                # Add the parent name to the list of Multipath Member devices
            lstMPathMemberNames.append(parent.name)

lstSPathNames = list(x.path[5:] for x           # Get a list of non-Multipath Member drives            
                             in drives
                             if x.type != 'dm-multipath'
                            and x.name not in lstMPathMemberNames)

lstAllDisks = lstSPathNames + lstMPathNames     # Combine both lists

# ------------------------------------------------------------------------------
# Locate the 'BIOS' drives for compatibility with RHEL5/6
# ------------------------------------------------------------------------------
firstDisk = lstAllDisks[0]                      # Get the first disk from combined lists
                                                # Get the Vendor/Model string and Size
firstDiskModel, firstDiskSize = allDiskModelsSizes[firstDisk]

for biosDev in range(0x80, lastBiosDisk + 1):   # For BIOS drives 0x80 through lastBiosDisk
    if biosDev - 0x80 < len(lstAllDisks):       # If a matching entry exists
                                                # Get its Vendor/Model string and Size
        diskModel = allDiskModelsSizes[lstAllDisks[biosDev - 0x80]][0]
        if diskModel == firstDiskModel:         # If the Model is the same as the first drive
                                                # Add to the list of 'BIOS' drives
            biosDisks[biosDev] = lstAllDisks[biosDev - 0x80]

lstBiosDisks = sortedDictValues(biosDisks)      # Convert the dictionary of BIOS Disks to a list sorted by their Int 0x13 ID
strBiosDisks = ','.join(lstBiosDisks)           # Convert the list of BIOS Disks to a string

# ------------------------------------------------------------------------------
# Locate the 'Other' drives for compatibility with RHEL5/6
# ------------------------------------------------------------------------------
lstOtherDisks = list(x for x                    # Get a list of any other drives
                        in lstAllDisks
                        if x not in lstBiosDisks)

# ------------------------------------------------------------------------------
# Get information for the boot drive
# ------------------------------------------------------------------------------
                                                # Find the "Size" of the boot Disk
bootDiskModel, bootDiskSize = allDiskModelsSizes[biosDisks[0x80]]

clearDrives = biosDisks[0x80]                   # Clear partitions on the boot Disk

# ------------------------------------------------------------------------------
# Build Dictionaries of lists BIOS and other Disks with Disk Model/Size as the keys 
# ------------------------------------------------------------------------------
                                                # Build a dictionary with each BIOS disk model as the key
                                                # and a list of the corresponding devices as the values
biosDiskModelsSizes = dict((v, list(key for key, value in allDiskModelsSizes.items() if value == v and key in lstBiosDisks[1:])) for v in set(dictSubset(lstBiosDisks[1:], allDiskModelsSizes).values()))
                                                # Build a dictionary with each non-BIOS disk model as the key
                                                # and a list of the corresponding devices as the values
otherDiskModelsSizes = dict((v, list(key for key, value in allDiskModelsSizes.items() if value == v and key in lstOtherDisks)) for v in set(dictSubset(lstOtherDisks, allDiskModelsSizes).values()))

# ------------------------------------------------------------------------------
# Open a file (/tmp/diskpart.cfg) to save all Partitioning options
# ------------------------------------------------------------------------------
myFile = open('/tmp/diskpart.cfg', 'w+')        # Save all output in /tmp/diskpart.cfg
myFile.write('# Memory Size = %s GB\n' % sysMem)


# ------------------------------------------------------------------------------
# Create the bootloader option
# ------------------------------------------------------------------------------
myFile.write('bootloader --location=mbr       --driveorder=%s --append="crashkernel=auto"\n' % lstBiosDisks[0])

# ------------------------------------------------------------------------------
# Create the boot disk options
# ------------------------------------------------------------------------------
                                                # Add a comment with the boot disk model
myFile.write('# Boot Disk Model: %s - %d GB\n' % (bootDiskModel, bootDiskSize/1024))
                                                # Create the /boot partition option
bootPartSize = 512
myFile.write('part /boot --fstype=ext4 --size=%s --ondisk=%s --asprimary\n' % (str(bootPartSize), lstBiosDisks[0]))
if uEFI:
    myFile.write('part /boot/efi --fstype=efi --size=%s --ondisk=%s --label=EFI --asprimary\n' % (str(bootPartSize), lstBiosDisks[0]))
                                                # Create a partition option for the rest of the boot drive
myFile.write('part pv.1000 --size=1 --grow --ondisk=%s --asprimary\n'        % lstBiosDisks[0])
myFile.write('volgroup rootvg pv.1000\n')       # Create the rootvg VG using the boot drive only
volumeGroups = {0: 'rootvg'}                    # Create an indexed list of volume groups

# ------------------------------------------------------------------------------
# Build partition options for additional BIOS disks, grouped by disk model
# ------------------------------------------------------------------------------
dataVgCount = 0                                 # Volume Group Counter
pvCount = 0                                     # Physical Volume Counter
                                                # For each model/size (sorted by model/size)
for model, size in sorted(biosDiskModelsSizes.iterkeys()): # For each model/size (sorted by model)
    drives = biosDiskModelsSizes[(model, size)] # Get the list of drives for this model/size
    dataVgCount = dataVgCount + 1               # Increment the Data VG Count
    lstPartitions = []                          # Start with an empty list of partitions
    drives.sort()                               # Sort the drives
                                                # Add a comment with the disk model/size
    myFile.write('# Disk Model: %s - %d GB\n' % (model, size/1024))
    pvCount = pvCount + 1                       # Increment the Physical Volume counter
    for drive in drives:                        # For each drive in the drive list
                                                # Create a partiton Option
        myFile.write('part pv.%d%03d --size=1 --grow --ondisk=%s --asprimary\n' % (pvCount, drives.index(drive) + 1, drive))
        clearDrives = clearDrives + ',' + drive # Add the drive to the string of drives to have their partitions cleared
                                                # Add the partition to a list of partitions in this VG
        lstPartitions.append('pv.%d%03d' % (pvCount, drives.index(drive) + 1))
                                                # Create a data VG option using all the disks of this model
    myFile.write('volgroup datavg%d %s\n' % (dataVgCount, ' '.join(lstPartitions)))
    volumeGroups[dataVgCount] = 'datavg' + str(dataVgCount)

# ------------------------------------------------------------------------------
# Build partition options for non-BIOS disks, grouped by disk model
# ------------------------------------------------------------------------------
if len(otherDisks) > 0:                         # If non-BIOS Disks Exist
                                                # For each model/size and drive in the list of other drives
    for model, size in sorted(otherDiskModelsSizes.iterkeys()):
                                                # Get the list of drives for this model/size
        drives = otherDiskModelsSizes[(model, size)]
                                                # If this model is in the dictionary of models to configure
        if model in otherDisks.keys() and otherDisks[model] > 0:
            dataVgCount = dataVgCount + 1       # Increment the Data VG Count
            lstPartitions = []                  # Start with an empty list of partitions
            drives.sort()                       # Sort the drives
                                                # Add a comment with the disk model/size
            myFile.write('# Disk Model: %s - %d GB\n' % (model, size/1024))
                                                # For each drive in the drive list, up to the specified number
            pvCount = pvCount + 1               # Increment the Physical Volume counter
            for drive in drives[0:otherDisks[model]]:
                                                # Create a partiton option
                myFile.write('part pv.%d%03d --size=1 --grow --ondisk=%s --asprimary\n' % (pvCount, drives.index(drive) + 1, drive))
                                                # Add the drive to the string of drives to have their partitions cleared
                clearDrives = clearDrives + ',' + drive
                                                # Add the partition to a list of partitions in this VG
                lstPartitions.append('pv.%d%03d' % (pvCount, drives.index(drive) + 1))
                                                # Create a data VG option using all the disks of this model
            myFile.write('volgroup datavg%d %s\n' % (dataVgCount, ' '.join(lstPartitions)))
            volumeGroups[dataVgCount] = 'datavg' + str(dataVgCount)
        else:                                   # If model not in dictionary of models to be configured
                                                # Write a comment listing model skipped
            myFile.write('# Skipping Disk Model: %s - %10.4f\n' % (model, size))

# ------------------------------------------------------------------------------
# Create Clear Partition Option including all selected disks
# ------------------------------------------------------------------------------
if uEFI:
    myFile.write('clearpart --none\n')          # Do not clear partitions on EFI Disks during Kickstart
    from subprocess import call, Popen, PIPE    # Import subprocess functions
    from stat import S_ISBLK                    # Import the Is Block Device value
    for drive in clearDrives.split(','):        # For each Drive to be cleared
        drivePath = '/dev/' + drive         # Get the device path
        mode = os.stat(drivePath).st_mode       # Get the mode of the path
        if S_ISBLK(mode):                       # If the path is a Block Special Device
                                                # Zero the MBR and create a GUID Partition Table
            call(['/usr/bin/dd', 'if=/dev/zero', 'of=' + drivePath, 'bs=512', 'count=256'])
            call(['/usr/sbin/parted', '--script', drivePath, 'mklabel', 'gpt'])
else:
                                                # Create the BIOS clear partiton option
    myFile.write('clearpart --drives=%s --all --initlabel\n'   % clearDrives)

# ------------------------------------------------------------------------------
# Calculate size for swap
# ------------------------------------------------------------------------------
if        sysMem <= 2:
    swapSize = int(sysMem * 1.5 * 1024)
elif  2 < sysMem <= 16:
    swapSize = int(sysMem * 1024)
else:
    swapSize = 16384
                                                # Write a comment listing model skipped

bootDiskSize = bootDiskSize - swapSize          # Deduct swapSize from bootDiskSize
bootDiskSize = bootDiskSize - bootPartSize      # Deduct bootPartSize from bootDiskSize
if uEFI:                                        # I this is an EFI system
    bootDiskSize = bootDiskSize - bootPartSize  # Deduct EFI partition size
    
# ------------------------------------------------------------------------------
# calculate sizes for rootvg logical volumes
# ------------------------------------------------------------------------------
rootSize = int(min(rootMax, bootDiskSize * rootPercent))
tmpSize = int(min(tmpMax, bootDiskSize * tmpPercent))
varSize = int(min(varMax, bootDiskSize * varPercent))
logSize = int(min(logMax, bootDiskSize * logPercent))
optSize = int(min(optMax, bootDiskSize * optPercent))
auditSize = int(min(auditMax, bootDiskSize * auditPercent))
homeSize = int(min(homeMax, bootDiskSize * homePercent))

# ------------------------------------------------------------------------------
# Write rootvg Logical Volume options
# ------------------------------------------------------------------------------
myFile.write('logvol /              --fstype=%s --name=root      --vgname=rootvg  --size=%d --fsoptions="defaults,noatime"\n' % (fsType, rootSize))
myFile.write('logvol swap                       --name=swap      --vgname=rootvg  --size=%d\n' % swapSize)
myFile.write('logvol /tmp           --fstype=%s --name=tmp       --vgname=rootvg  --size=%d  --fsoptions="defaults,noatime,nodev,nosuid,noexec"\n' % (fsType, tmpSize))
myFile.write('logvol /var           --fstype=%s --name=var       --vgname=rootvg  --size=%d  --fsoptions="defaults,noatime,nodev"\n' % (fsType, varSize))
myFile.write('logvol /var/log       --fstype=%s --name=log       --vgname=rootvg  --size=%d  --fsoptions="defaults,noatime,nodev"\n' % (fsType, logSize))
if opt:
    myFile.write('logvol /opt           --fstype=%s --name=opt       --vgname=rootvg  --size=%d  --fsoptions="defaults,noatime,nodev"\n' % (fsType, optSize))
myFile.write('logvol /var/log/audit --fstype=%s --name=audit     --vgname=rootvg  --size=%d  --fsoptions="defaults,noatime,nodev"\n' % (fsType, auditSize))
myFile.write('logvol /home          --fstype=%s --name=home      --vgname=rootvg  --size=%d  --fsoptions="defaults,noatime,nodev"\n' % (fsType, homeSize))

# ------------------------------------------------------------------------------
# Build optional logical volumes
# ------------------------------------------------------------------------------
for lvName, (lvMount, lvGroup, lvSize, lvFsType) in optionalLVs.iteritems():
    myFile.write('logvol %s --fstype=%s --name=%s --vgname=%s --size=%d --fsoptions="defaults,noatime,nodev"\n' % (lvMount + '/' + lvName, 
                                                                                                                   lvFsType, 
                                                                                                                   lvName, 
                                                                                                                   volumeGroups[min(lvGroup, dataVgCount)], 
                                                                                                                   lvSize))

# ------------------------------------------------------------------------------
# Close file and exit
# ------------------------------------------------------------------------------
myFile.close()
sys.exit()
1 Like

Note: posted Script has a typo,

fsType       = <%= host_param('fsType') || 'xfs' %>

should be

fsType       = '<%= host_param('fsType') || 'xfs' %>'