Linux Installation mit Autoyast und Kickstart

SUSE basierende Linux-Distributionen (openSUSE, SUSE Linux Enterprise Server) verwenden AutoYast und eine auf XML basierende Konfigurationsdatei. Auf Red Hat basierende Linux-Distributionen (Red Hat, CentOS, Fedora) verwenden Kickstart. Folgende Lösung bietet eine Kombination beider Varianten fuer ein heterogenes Linux-Umfeld, in dem viele Linux-Geschmacksrichtungen automatisch installiert werden sollen. Beim Boot ab der Installations-DVD kann mit einer einzigen URL bestimmt werden, welche Linux-Variante installiert werden soll und wie der Hostname heissen soll. Die Netzwerk-Einstellungen werden dann je nach IP-Adresse von einem PHP-Script geliefert und in die Autoyast/Kickstart Templates eingefüllt.

Linux Distribution Ver.Arch Method Install Parameters
openSUSE 11.3i586 Autoyast info=http://install.example.com/opensuse11.3/hostname
openSUSE 11.3x86_64Autoyast info=http://install.example.com/opensuse11.3-64/hostname
SUSE Linux Enterprise Server11 i386 Autoyast info=http://install.example.com/sles11/hostname
SUSE Linux Enterprise Server11 x86_64Autoyast info=http://install.example.com/sles11-64/hostname
CentOS 5.5 i386 Kickstartlinux ks=http://install.example.com/centos5.5/hostname
CentOS 5.5 x86_64Kickstartlinux ks=http://install.example.com/centos5.5-64/hostname
Red Hat Enterprise Linux 5.6 i386 Kickstartlinux ks=http://install.example.com/rhel5.6/hostname
Red Hat Enterprise Linux 5.6 x86_64Kickstartlinux ks=http://install.example.com/rhel5.6-64/hostname

Apache Webserver

Für jede Linux-Version und Architektur jeweils ein Alias auf das PHP-Skript myconfig.php.

# Autoyast & Kickstart Linux Installation
Alias /myconfig.php    /export/scripts/myconfig.php
Alias /centos5.5       /export/scripts/myconfig.php
Alias /centos5.5-64    /export/scripts/myconfig.php
Alias /fedora14        /export/scripts/myconfig.php
Alias /opensuse11.3    /export/scripts/myconfig.php
Alias /opensuse11.3-64 /export/scripts/myconfig.php
Alias /rhel4.7         /export/scripts/myconfig.php
Alias /rhel4.7-64      /export/scripts/myconfig.php
Alias /rhel5.5         /export/scripts/myconfig.php
Alias /rhel5.5-64      /export/scripts/myconfig.php
Alias /rhel5.6         /export/scripts/myconfig.php
Alias /rhel5.6-64      /export/scripts/myconfig.php
Alias /sles11          /export/scripts/myconfig.php
Alias /sles11-64       /export/scripts/myconfig.php
Alias /sles11sp1       /export/scripts/myconfig.php
Alias /sles11sp1-64    /export/scripts/myconfig.php

Skripts

PHP-Skript myconfig.php

Dieses Script entscheided anhand der URI, um welche Linux-Version es sich handelt und wie der Hostname des zu installierenden Systems lauten soll. Anhand des DNS-Eintrages wird die IP-Adresse und die dazugehörigen Netzwerk-Parameter angepasst. Je nach Linux-Version wird das richtige Template (Autoyast oder Kickstart) gelesen und alle Variablen der Form $C[KEY] abgeändert.

Enthält die URI weder Linux-Version noch Hostname, sondern lautet http://install.example.com/myconfig.php, dann werden Shell-Variablen und Funktionen passend zur Client IP-Adresse der Anfrage ausgegeben, damit diese Angaben in den Post-Install Scripts verwendet werden können.

<?php

###### G L O B A L S ######

$LINUX_FLAVOURS = array
( 
  "centos5.5" => array
  ( "name"    => "CentOS 5.5 i386", 
    "repo"    => "centos/5.5/os/i386",
    "updates" => "centos/5.5/updates/i386",
    "config"  => "templates/centos-5.ks"
  ),

  "centos5.5-64" => array
  ( "name"    => "CentOS 5.5 x86_64",
    "repo"    => "centos/5.5/os/x86_64",
    "updates" => "centos/5.5/updates/x86_64",
    "config"  => "templates/centos-5.ks"
  ),

  "opensuse11.3" => array
  ( "name"    => "openSUSE 11.3",
    "repo"    => "opensuse/distribution/11.3/repo/oss", 
    "updates" => "opensuse/update/11.3",
    "config"  => "templates/opensuse-11.3-i386.xml"
  ),

  "opensuse11.3-64" => array
  ( "name"    => "openSUSE 11.3 x86_64",
    "repo"    => "opensuse/distribution/11.3/repo/oss",
    "updates" => "opensuse/update/11.3",
    "config"  => "templates/opensuse-11.3-x86_64.xml"
  ),

  "rhel5.6" => array
  ( "name"    => "Red Hat Enterprise Linux 5.6 i386",
    "repo"    => "rhel/5.6/os/i386",
    "updates" => "rhel/5.6/updates/i386",
    "config"  => "templates/rhel-5.ks"
  ),

  "rhel5.6-64" => array
  ( "name"    => "Red Hat Enterprise Linux 5.6 x86_64",
    "repo"    => "rhel/5.6/os/x86_64",
    "updates" => "rhel/5.6/updates/x86_64",
    "config"  => "templates/rhel-5.ks"
  ),

  "sles11" => array
  ( "name"    => "SUSE Linux Enterprise Server 11",
    "repo"    => "sles/11/CD1",
    "updates" => "sles/smt/repo/\$RCE/SLES11-Updates/sle-11-i586",
    "config"  => "templates/sles-11-i386.xml"
  ),

  "sles11-64" => array
  ( "name"    => "SUSE Linux Enterprise Server 11 x86_64",
    "repo"    => "sles/11-64/CD1",
    "updates" => "sles/smt/repo/\$RCE/SLES11-Updates/sle-11-x86_64",
    "config"  => "templates/sles-11-x86_64.xml"
  ),
);

$SUBNETS = array
( "10.0.204.0"  => array("255.255.252.0", "10.0.204.1",   "ZH"),
  "10.0.208.0"  => array("255.255.252.0", "10.0.208.1",   "ZH"),
  "10.0.212.0"  => array("255.255.252.0", "10.0.212.1",   "ZH"),
  "10.10.204.0" => array("255.255.252.0", "10.20.204.1",  "NY"),
  "10.10.208.0" => array("255.255.252.0", "10.20.208.1",  "NY"),
  "10.10.212.0" => array("255.255.252.0", "10.20.212.1",  "NY"),
);

$LOCATIONS = array
( "ZH" => array( "LOCATION" => "Zurich",
                 "INSTSERVER"  => "install.zh.example.com",
                 "LOGSERVER"   => "log.zh.example.com",
                 "DNSSERVER1"  => "10.0.204.7",
                 "DNSSERVER2"  => "10.0.208.8",
                 "DNSDOMAIN"   => "zh.example.com",
                 "DNSSEARCH1"  => "zh.example.com",
                 "DNSSEARCH2"  => "ny.example.com",
                 "DNSSEARCH3"  => "example.com",
                 "TIMEZONE"    => "Europe/Zurich",
                 "NFSSERVER"   => "install.zh.example.com",
                 "NFSSHARE"    => "/export",
                 "NTPSERVER1"  => "ntp1.zh.example.com",
                 "NTPSERVER2"  => "ntp2.zh.example.com",
                 "LDAPSERVER"  => "ldap.zh.example.com",
                 "LDAPBASEDN"  => "dc=example,dc=com",
                 "LDAPBASELOC" => "ou=zh,dc=example,dc=com",
                 "SMTPSERVER"  => "smtp.example.com",
                 "SMTPDOMAIN"  => "example.com",
                 "PRINTERDEF"  => "printer-zh",
                 "PROXYSERVER" => "proxy.zh.example.com",
                 "SOCKSSERVER" => "proxy.zh.example.com",
               ),

  "NY" => array( "LOCATION" => "New York",
                 "INSTSERVER"  => "install.ny.example.com",
                 "LOGSERVER"   => "log.zh.example.com",
                 "DNSSERVER1"  => "10.10.204.7",
                 "DNSSERVER2"  => "10.10.208.8",
                 "DNSDOMAIN"   => "ny.example.com",
                 "DNSSEARCH1"  => "ny.example.com",
                 "DNSSEARCH2"  => "zh.example.com",
                 "DNSSEARCH3"  => "example.com",
                 "TIMEZONE"    => "USA/New York",
                 "NFSSERVER"   => "install.ny.example.com",
                 "NFSSHARE"    => "/export",
                 "NTPSERVER1"  => "ntp1.ny.example.com",
                 "NTPSERVER2"  => "ntp2.ny.example.com",
                 "LDAPSERVER"  => "ldap.ny.example.com",
                 "LDAPBASEDN"  => "dc=example,dc=com",
                 "LDAPBASELOC" => "ou=ny,dc=example,dc=com",
                 "SMTPSERVER"  => "smtp.example.com",
                 "SMTPDOMAIN"  => "example.com",
                 "PRINTERDEF"  => "printer-zh",
                 "PROXYSERVER" => "proxy.ny.example.com",
                 "SOCKSSERVER" => "proxy.ny.example.com",
               ),
);



###### F U N C T I O N S #####################################################

function isInNet($ip, $net, $mask)
{ $binIP   = ip2long($ip);
  $binNet  = ip2long($net);
  $binMask = ip2long($mask);
  $res = $binIP & $binMask;
  return($res == $binNet);
}

function abortWithError($message)
{ global $C; 
  header("Status: 404 Not Found");
  print "<h1>ERROR: $message</h1>\n";
  print "<pre>\n\$C = ";
  print_r($C);
  print "</pre>\n";
  exit(1);
}

function getRootPassword()
{ global $C;
  $pw = crypt(preg_replace("/^[0-9]+\.[0-9]+\.[0-9]+\./", "hades", $C["HOSTIP"]));
  return($pw); 
}

function getNetworkSettingsFromIP($ip)
{ global $LOCATIONS, $SUBNETS, $C; 
  $subnet = false;
  foreach (array_keys($SUBNETS) as $net)
  { if (isInNet($ip, $net, $SUBNETS[$net][0]))
    { $C["SUBNET"]  = $net;
      $C["NETMASK"] = $SUBNETS[$net][0];
      $C["GATEWAY"] = $SUBNETS[$net][1];
      $C = array_merge($C, $LOCATIONS[$SUBNETS[$net][2]]);
      break;
    }
  }
  if (!isset($C["SUBNET"]))
  { abortWithError("No subnet defined for IP address $ip");
  }
}



###### M A I N ################################################################

$C = array();
$C["REMOTE_ADDR"] = $_SERVER["REMOTE_ADDR"];
$C["REQUEST_URI"] = $_SERVER["REQUEST_URI"];
$C["REQUEST_URI"] = preg_replace("/^\/\./", "", $C["REQUEST_URI"]); # Fix for RHEL4

if (preg_match('/^\/myconfig.php$/',$C["REQUEST_URI"]))
{ 
  # Called with http://install.zh.example.com/myconfig.php
  # Return SHELL variables and functions

  getNetworkSettingsFromIP($C["REMOTE_ADDR"]);

  header("Content-Type: text/plain");
  foreach (array_keys($C) as $key)
  { printf("%s='%s'\n", $key, $C[$key]);
  }
  print "\n";
  readfile($_SERVER["DOCUMENT_ROOT"] . "/scripts/.myfunctions");
}
elseif (preg_match("/^\/([A-Za-z0-9_\.-]+)\/([A-Za-z0-9-]+)/", $C["REQUEST_URI"], $matches))
{ 
  $C["LINUX"]    = strtolower($matches[1]);
  $C["HOSTNAME"] = strtolower($matches[2]);
  $C["HOSTIP"]   = gethostbyname($C["HOSTNAME"]);

  if ($C["HOSTIP"] == $C["HOSTNAME"])
  { abortWithError("No IP address found for host '$C[HOSTNAME]'");
  }

  if (!array_key_exists($C["LINUX"], $LINUX_FLAVOURS))
  { abortWithError("Undefined Linux flavour: $C[LINUX]");
  }

  getNetworkSettingsFromIP($C["HOSTIP"]);

  $C["LINUXNAME"]  = $LINUX_FLAVOURS[$C["LINUX"]]["name"];
  $C["REPOSITORY"] = $LINUX_FLAVOURS[$C["LINUX"]]["repo"];
  $C["UPDATES"]    = $LINUX_FLAVOURS[$C["LINUX"]]["updates"];
  $C["ROOTPW"]     = getRootPassword();
  $C["TEMPLATE"]   = $_SERVER["DOCUMENT_ROOT"] . "/" . $LINUX_FLAVOURS[$C["LINUX"]]["config"];;
  if (!file_exists($C["TEMPLATE"]))
  { abortWithError("Template $C[TEMPLATE] not found.");
    exit(1);
  }
  header("Content-Type: text/plain");
  foreach (file($C["TEMPLATE"]) as $line)
  { print preg_replace('/\$C\[([[:alnum:]]+)\]/e', '$C[$1]', $line);
  }
}
else
{
  abortWithError("Undefined request method: $C[REQUEST_URI]");
}
?>

Shell Funktionen .myfunctions

Diese Datei wird von myconfig.php gelesen und 1:1 ausgegeben, wenn die URL http://install.example.com/myconfig.php lautet. Hier befinden sich Funktionen, welche auf dem Install-Client ausgeführt werden und feststellen, um welche Linux-Variante oder Hardware es sich handelt.

function backupFile()
{ timestamp=`date +"%Y%m%d-%H%M%S"`
  for file in $@; do
    if [ -f $file ]; then
      echo "Backing up $file ..."
      cp -f $file $file.$timestamp
    fi
  done
}

PATH="/bin:/sbin:/usr/bin:/usr/sbin"


# OS_RELEASE
# -------------
# CentOS release 5.5 (Final)
# Fedora release 14 (Laughlin)
# openSUSE 11.0 (i586)
# openSUSE 11.2 (i586)
# openSUSE 11.3 (i586)
# Red Hat Enterprise Linux Server release 5.2 (Tikanga)
# SUSE LINUX Enterprise Server 9 (i586)
# SUSE Linux Enterprise Server 10 (x86_64)
# SUSE Linux Enterprise Server 11 (i586)
# SUSE Linux Enterprise Server 11 (x86_64)
# Solaris 10 5/08 s10s_u5wos_10 SPARC
#
if [ -f /etc/SuSE-release ]; then
  OS_RELEASE=`head -1 /etc/SuSE-release | sed -re 's/^ +//; s/ +$//'`
elif [ -f /etc/redhat-release ]; then
  OS_RELEASE=`head -1 /etc/redhat-release | sed -re 's/^ +//; s/ +$//'`
elif [ -f /etc/release ]; then
  OS_RELEASE=`head -1 /etc/release | sed -re 's/^ +//; s/ +$//'`
else
  echo "ERROR: Unknown OS release"
  test -f /etc/issue && cat /etc/issue
  uname -a
  exit 1
fi



# SYSTEM_PRODUCT
# --------------
# VMware Virtual Platform
# Precision WorkStation 650    
# Precision WorkStation 670    
# Precision WorkStation 490    
# Precision WorkStation T5400  
# Precision WorkStation T5500
# PowerEdge 2650
# 
case "$OS_RELEASE" in
  SUSE*10*|SUSE*11*|openSUSE*|Red*Hat*5*|CentOS*5*)
    SYSTEM_PRODUCT=`dmidecode -s system-product-name | sed -re 's/^ +//; s/ +$//'`
    ;;
  SUSE*9*|Red*Hat*4*)
    SYSTEM_PRODUCT=`dmidecode | grep -A6 "System Information" \
      | awk -F: '($1~/Product Name/){print $2}' \
      | sed -re 's/^ +//; s/ +$//'`
    ;;
  Solaris*)
    SYSTEM_PRODUCT=`prtdiag | head -1 | sed 's/^.* Sun/Sun/'`
    ;;
  *)
    echo "Don't know how to get SYSTEM_PRODUCT on $OS_RELEASE"
    uname -a 
    exit 1
    ;;
esac

Autoyast / Kickstart Templates

Jeweils ein Beispiel für eine Kickstart und eine Autoyast Konfiguration. Die Platzhalter $C[KEY] werden vom PHP Script myconfig.php ersetzt. Bei jeder Version ändert die Syntax leicht.

Kickstart Template für CentOS 5.5

#
# CentOS 5
# Kickstart Configuration for $C[HOSTNAME] ($C[HOSTIP])
#
install
url --url=http://$C[INSTSERVER]/$C[REPOSITORY]
logging --host=$C[LOGSERVER] --port=514 --level=debug
cmdline
reboot --eject
firstboot --disable

# Disk Partitioning
ignoredisk --drives=sdb,sdc,hdb,hdc
bootloader --location=mbr --driveorder=sda
clearpart --all --drives=sda --initlabel
partition /boot --asprimary --fstype=ext3 --label BOOT --size=128
partition swap  --asprimary --fstype=swap --label SWAP --recommended 
partition /     --asprimary --fstype=ext3 --label ROOT --size=4096 --grow

# Language & Keyboard
lang en_US.UTF-8
keyboard us

# Networking
network --bootproto=static --hostname=$C[HOSTNAME] --ip=$C[HOSTIP] \
        --netmask=$C[NETMASK] --gateway=$C[GATEWAY] --nameserver="$C[DNSSERVER1],$C[DNSSERVER2]"
timezone --utc $C[TIMEZONE]

# Users & Security Settings
firewall --disabled
authconfig --enableshadow --enablemd5 --enableldap --ldapserver=$C[LDAPSERVER] \
           --ldapbasedn="$C[LDAPBASEDN]" --enableldapauth --enableldaptls
rootpw --iscrypted "$C[ROOTPW]"
selinux --disabled

# Graphical Desktop
xconfig --startxonboot

services --enabled nscd,ntpd,autofs

%packages
@admin-tools
@authoring-and-publishing
@base
@base-x
@clustering
@cluster-storage
@core
@development-libs
@development-tools
@dialup
@editors
@emacs
@engineering-and-scientific
@games
@gnome-desktop
@gnome-software-development
@graphical-internet
@graphics
@java-development
@java
@kde-desktop
@kde-software-development
@kvm
@legacy-network-server
@legacy-software-development
@legacy-software-support
@mail-server
@miscallvars
@mysql
@network-server
@office
@printing
@ruby
@server-cfg
@sound-and-video
@sql-server
@system-tools
@text-internet
@web-server
@x-software-development
#end packages



%post
exec < /dev/tty3 > /dev/tty3
chvt 3
echo "################################"
echo "# Running Post Configuration   #"
echo "################################"
(

cat >/etc/hosts <<EOF
127.0.0.1	localhost.localdomain	localhost
$C[HOSTIP]	$C[HOSTNAME].$C[DNSDOMAIN]	$C[HOSTNAME]
EOF

# Modify software repositories and update system
sed -e 's/^#baseurl/baseurl/' \
    -e 's/^mirrorlist/#mirrorlist/' \
    -e 's/mirror.centos.org/$C[INSTSERVER]/' \
    -i /etc/yum.repos.d/CentOS-Base.repo
/usr/bin/yum -y update

curl -s http://$C[INSTSERVER]/scripts/setup-dns.sh     | bash
curl -s http://$C[INSTSERVER]/scripts/setup-ntp.sh     | bash
curl -s http://$C[INSTSERVER]/scripts/setup-ldap.sh    | bash
curl -s http://$C[INSTSERVER]/scripts/setup-userfix.sh | bash

) 2>&1 | /usr/bin/tee /root/post_install.log
chvt 1
#end post

AutoYast Template für OpenSUSE 11.3 (i386)

<?xml version="1.0"?>
<!DOCTYPE profile>
<profile xmlns="http://www.suse.com/1.0/yast2ns" xmlns:config="http://www.suse.com/1.0/configns">

<!--
  openSUSE 11.3 i386
  AutoYast Configuration for Host $C[HOSTNAME] ($C[HOSTIP])
-->

<info_file>
<![CDATA[
# start_linuxrc_conf
hostip:     $C[HOSTIP]
netmask:    $C[NETMASK]
gateway:    $C[GATEWAY]
nameserver: $C[DNSSERVER1]
domain:     $C[DNSDOMAIN]
install:    http://$C[INSTSERVER]/$C[REPOSITORY]
autoyast:   http://$C[INSTSERVER]/$C[LINUX]/$C[HOSTNAME]
loghost:    $C[LOGSERVER]
# end_linuxrc_conf
]]>
</info_file>

<timezone>
  <hwclock>UTC</hwclock>
  <timezone>$C[TIMEZONE]</timezone>
</timezone>

<keyboard>
  <keymap>english-us</keymap>
</keyboard>

<language>en_US</language>

<general>
  <mode>
    <confirm config:type="boolean">false</confirm>
    <forceboot config:type="boolean">false</forceboot>
    <second_stage config:type="boolean">true</second_stage>
  </mode>
  <mouse>
    <id>probe</id>
  </mouse>
  <signature-handling>
    <accept_unsigned_file         config:type="boolean">true</accept_unsigned_file>
    <accept_file_without_checksum config:type="boolean">true</accept_file_without_checksum>
    <accept_verification_failed   config:type="boolean">true</accept_verification_failed>
    <accept_unknown_gpg_key       config:type="boolean">true</accept_unknown_gpg_key>
    <import_gpg_key               config:type="boolean">true</import_gpg_key>
  </signature-handling>
</general>

<report>    
  <messages>
    <show config:type="boolean">true</show>
    <timeout config:type="integer">30</timeout>
    <log config:type="boolean">true</log>
  </messages>
  <errors>
    <show config:type="boolean">true</show>
    <timeout config:type="integer">30</timeout>
    <log config:type="boolean">true</log>
  </errors>
  <warnings>
    <show config:type="boolean">true</show>
    <timeout config:type="integer">30</timeout>
    <log config:type="boolean">true</log>
  </warnings>
</report>

<partitioning config:type="list">
  <drive>
    <device>/dev/sda</device>
    <use>all</use>
    <initialize config:type="boolean">true</initialize>
    <partitions config:type="list">
      <partition>
        <mount>/boot</mount>
        <size>128M</size>
        <partition_nr config:type="integer">1</partition_nr>
        <partition_id config:type="integer">131</partition_id>
        <partition_type>primary</partition_type>
        <filesystem config:type="symbol">ext4</filesystem>
        <format config:type="boolean">true</format>
      </partition>
      <partition>
        <mount>swap</mount>
        <size>4G</size>
        <partition_nr config:type="integer">2</partition_nr>
        <partition_id config:type="integer">130</partition_id>
        <partition_type>primary</partition_type>
        <filesystem config:type="symbol">swap</filesystem>
        <format config:type="boolean">true</format>
      </partition>
      <partition>
        <mount>/</mount>
        <size>max</size>
        <partition_nr config:type="integer">3</partition_nr>
        <partition_id config:type="integer">131</partition_id>
        <partition_type>primary</partition_type>
        <filesystem config:type="symbol">ext4</filesystem>
        <format config:type="boolean">true</format>
      </partition>
    </partitions>
  </drive>
</partitioning>

<deploy_image>
  <image_installation config:type="boolean">true</image_installation>
</deploy_image>

<software>
  <kernel>kernel-desktop</kernel>
  <patterns config:type="list">
    <pattern>base</pattern>
    <pattern>console</pattern>
    <pattern>default</pattern>
    <pattern>devel_basis</pattern>
    <pattern>devel_C_C++</pattern>
    <pattern>devel_gnome</pattern>
    <pattern>devel_ide</pattern>
    <pattern>devel_java</pattern>
    <pattern>devel_kde</pattern>
    <pattern>devel_kernel</pattern>
    <pattern>devel_mono</pattern>
    <pattern>devel_perl</pattern>
    <pattern>devel_python</pattern>
    <pattern>devel_qt4</pattern>
    <pattern>devel_rpm_build</pattern>
    <pattern>devel_ruby</pattern>
    <pattern>devel_tcl</pattern>
    <pattern>devel_web</pattern>
    <pattern>directory_server</pattern>
    <pattern>enhanced_base_opt</pattern>
    <pattern>enhanced_base</pattern>
    <pattern>file_server</pattern>
    <pattern>fonts_opt</pattern>
    <pattern>fonts</pattern>
    <pattern>games</pattern>
    <pattern>gateway_server</pattern>
    <pattern>gnome_admin</pattern>
    <pattern>gnome_basis_opt</pattern>
    <pattern>gnome_basis</pattern>
    <pattern>gnome_games</pattern>
    <pattern>gnome_ide</pattern>
    <pattern>gnome_imaging_opt</pattern>
    <pattern>gnome_imaging</pattern>
    <pattern>gnome_internet</pattern>
    <pattern>gnome_laptop</pattern>
    <pattern>gnome_multimedia_opt</pattern>
    <pattern>gnome_multimedia</pattern>
    <pattern>gnome_office_opt</pattern>
    <pattern>gnome_office</pattern>
    <pattern>gnome</pattern>
    <pattern>gnome_utilities</pattern>
    <pattern>gnome_xgl</pattern>
    <pattern>gnome_yast</pattern>
    <pattern>imaging_opt</pattern>
    <pattern>imaging</pattern>
    <pattern>kde4_admin</pattern>
    <pattern>kde4_basis</pattern>
    <pattern>kde4_edutainment</pattern>
    <pattern>kde4_games</pattern>
    <pattern>kde4_ide</pattern>
    <pattern>kde4_imaging</pattern>
    <pattern>kde4_internet</pattern>
    <pattern>kde4_laptop</pattern>
    <pattern>kde4_multimedia</pattern>
    <pattern>kde4_office</pattern>
    <pattern>kde4</pattern>
    <pattern>kde4_utilities_opt</pattern>
    <pattern>kde4_utilities</pattern>
    <pattern>kde4_xgl</pattern>
    <pattern>kde4_yast</pattern>
    <pattern>kde</pattern>
    <pattern>lamp_server</pattern>
    <pattern>laptop</pattern>
    <pattern>lxde_laptop</pattern>
    <pattern>lxde_office</pattern>
    <pattern>lxde</pattern>
    <pattern>mail_server</pattern>
    <pattern>misc_server</pattern>
    <pattern>multimedia_opt</pattern>
    <pattern>multimedia</pattern>
    <pattern>network_admin</pattern>
    <pattern>office_opt</pattern>
    <pattern>office</pattern>
    <pattern>print_server</pattern>
    <pattern>remote_desktop</pattern>
    <pattern>sw_management_gnome</pattern>
    <pattern>sw_management_kde4</pattern>
    <pattern>sw_management</pattern>
    <pattern>tabletpc</pattern>
    <pattern>technical_writing</pattern>
    <pattern>x11_opt</pattern>
    <pattern>x11</pattern>
    <pattern>xfce_office</pattern>
    <pattern>xfce</pattern>
    <pattern>xgl</pattern>
    <pattern>yast2_basis</pattern>
    <pattern>yast2_install_wf</pattern>
  </patterns>

  <packages config:type="list">
    <package>acroread</package>
    <package>cabextract</package>
    <package>gv</package>
    <package>gvim</package>
    <package>mutt</package>
    <package>rsh</package>
    <package>unison</package>
    <package>quota</package>
    <package>wireshark</package>
    <package>xemacs</package>
    <package>MozillaFirefox</package>
    <package>MozillaThunderbird</package>
    <package>pam_ldap</package>
    <package>nss_ldap</package>
    <package>x11-video-nvidiaG02</package>
    <package>nvidia-gfxG02-kmp-desktop</package>
    <package>libstdc++33</package>
    <package>libexpat0</package>
    <package>vlc</package>
  </packages>

  <remove-packages config:type="list">
    <package>kernel-default</package>
    <package>kernel-xen</package>
    <package>pullin-flash-player</package>
    <package>pullin-fluendo-mp3</package>
    <package>pullin-msttf-fonts</package>
    <package>xorg-x11-driver-video-nouveau</package>
  </remove-packages>
</software>

<add-on>
 <add_on_products config:type="list">
   <listentry>
     <media_url>http://$C[INSTSERVER]/opensuse/distribution/11.3/repo/non-oss</media_url>
     <product>$C[LINUXNAME] NonOSS Add on</product>
     <product_dir>/</product_dir>
     <ask_on_error config:type="boolean">false</ask_on_error>
     <name>$C[LINUXNAME] NonOSS addon</name>
   </listentry>
   <listentry>
     <media_url>http://$C[INSTSERVER]/$C[UPDATES]</media_url>
     <product>$C[LINUXNAME] Updates</product>
     <product_dir>/</product_dir>
     <ask_on_error config:type="boolean">false</ask_on_error>
     <name>$C[LINUXNAME] Updates</name>
   </listentry>
   <listentry>
     <media_url>http://$C[INSTSERVER]/addons/download.nvidia.com/opensuse/11.3</media_url>
     <product>NVIDIA Drivers for $C[LINUXNAME]</product>
     <product_dir>/</product_dir>
     <ask_on_error config:type="boolean">false</ask_on_error>
     <name>NVIDIA Drivers for $C[LINUXNAME]</name>
   </listentry>
   <listentry>
     <media_url>http://$C[INSTSERVER]/addons/download.videolan.org/vlc/SuSE/11.3</media_url>
     <product>VLC</product>
     <product_dir>/</product_dir>
     <ask_on_error config:type="boolean">false</ask_on_error>
     <name>VideoLAN for $C[LINUXNAME]</name>
   </listentry>
 </add_on_products>
</add-on>

<sound>
  <autoinstall config:type="boolean">true</autoinstall>
  <configure_detected config:type="boolean">true</configure_detected>
</sound>
  
<firewall>
  <start_firewall config:type="boolean">false</start_firewall>
</firewall>

<networking>
  <managed config:type="boolean">false</managed>
  <dns>
    <domain>$C[DNSDOMAIN]</domain>
    <hostname>$C[HOSTNAME]</hostname>
    <nameservers config:type="list">
      <nameserver>$C[DNSSERVER1]</nameserver>
      <nameserver>$C[DNSSERVER2]</nameserver>
    </nameservers>
    <searchlist config:type="list">
      <search>$C[DNSDOMAIN]</search>
      <search>$C[DNSSEARCH1]</search>
      <search>$C[DNSSEARCH2]</search>
      <search>$C[DNSSEARCH3]</search>
      <search>$C[DNSSEARCH4]</search>
    </searchlist>
  </dns>
  <interfaces config:type="list">
    <interface>
      <bootproto>static</bootproto>
      <device>eth0</device>        
      <startmode>onboot</startmode>
      <ipaddr>$C[HOSTIP]</ipaddr>
      <netmask>$C[NETMASK]</netmask>
      <usercontrol>no</usercontrol>
    </interface>
  </interfaces>
  <routing>
    <ip_forward config:type="boolean">false</ip_forward>
    <routes config:type="list">
      <route>
        <destination>default</destination>
        <device>-</device>
        <gateway>$C[GATEWAY]</gateway>
        <netmask>-</netmask>
      </route>
    </routes>
  </routing>
</networking>



<host>
  <hosts config:type="list">
    <hosts_entry>
      <host_address>127.0.0.1</host_address>
      <names config:type="list">
        <name>localhost.localdomain localhost</name>
      </names>
    </hosts_entry>
    <hosts_entry>
      <host_address>$C[HOSTIP]</host_address>
      <names config:type="list">
        <name>$C[HOSTNAME].$C[DNSDOMAIN] $C[HOSTNAME]</name>
      </names>
    </hosts_entry>
  </hosts>
</host>

<mail>
  <aliases config:type="list">
    <alias>
      <alias>root</alias>
      <destinations>root@example.com</destinations>
    </alias>
  </aliases>
  <connection_type config:type="symbol">permanent</connection_type>
  <from_header>$C[SMTPDOMAIN]</from_header>
  <listen_remote config:type="boolean">false</listen_remote>
  <mta config:type="symbol">postfix</mta>
  <outgoing_mail_server>$C[SMTPSERVER]</outgoing_mail_server>
  <postfix_mda config:type="symbol">local</postfix_mda>
  <use_amavis config:type="boolean">false</use_amavis>
</mail>



<ldap>
  <base_config_dn>ou=ldapconfig,$C[LDAPBASEDN]</base_config_dn>
  <bind_dn>cn=proxyagent,ou=special_users,$C[LDAPBASEDN]</bind_dn>
  <create_ldap config:type="boolean">false</create_ldap>
  <file_server config:type="boolean">false</file_server>
  <ldap_domain>$C[LDAPBASEDN]</ldap_domain>
  <ldap_server>$C[LDAPSERVER]</ldap_server>
  <ldap_tls config:type="boolean">true</ldap_tls>
  <ldap_v2 config:type="boolean">false</ldap_v2>
  <login_enabled config:type="boolean">true</login_enabled>
  <member_attribute></member_attribute>
  <nss_base_group>ou=group,$C[LDAPBASEDN]</nss_base_group>
  <nss_base_passwd>ou=people,$C[LDAPBASEDN]</nss_base_passwd>
  <nss_base_shadow>ou=people,$C[LDAPBASEDN]</nss_base_shadow>
  <pam_password>crypt</pam_password>
  <start_autofs config:type="boolean">true</start_autofs>
  <start_ldap config:type="boolean">true</start_ldap>
</ldap>


<ntp-client>
  <ntp_policy>auto</ntp_policy>
  <peers config:type="list">
    <peer>
      <address>$C[NTPSERVER]</address>
      <options>iburst</options>
      <type>server</type>
    </peer>
  </peers>
  <start_at_boot config:type="boolean">true</start_at_boot>
  <start_in_chroot config:type="boolean">false</start_in_chroot>
</ntp-client>


<runlevel>
  <default>5</default>
  <services config:type="list">
    <service> <service_name>autofs</service_name>   <service_start>3 5</service_start> </service>
    <service> <service_name>cups</service_name>     <service_start>3 5</service_start> </service>
    <service> <service_name>network</service_name>  <service_start>3 5</service_start> </service>
    <service> <service_name>nfs</service_name>      <service_start>3 5</service_start> </service>
    <service> <service_name>ntp</service_name>      <service_start>3 5</service_start> </service>
    <service> <service_name>postfix</service_name>  <service_start>3 5</service_start> </service>
    <service> <service_name>sshd</service_name>     <service_start>3 5</service_start> </service>
  </services>
</runlevel>



<samba-client>
  <global>
    <winbind config:type="boolean">false</winbind>
    <workgroup>EXAMPLE</workgroup>
  </global>
</samba-client>
    


<security>
  <console_shutdown>ignore</console_shutdown>
  <cracklib_dict_path>/usr/lib/cracklib_dict</cracklib_dict_path>
  <cwd_in_root_path>no</cwd_in_root_path>
  <cwd_in_user_path>no</cwd_in_user_path>
  <displaymanager_remote_access>yes</displaymanager_remote_access>
  <enable_sysrq>no</enable_sysrq>
  <fail_delay>6</fail_delay>
  <faillog_enab>yes</faillog_enab>
  <gid_max>60000</gid_max>
  <gid_min>500</gid_min>
  <kdm_shutdown>root</kdm_shutdown>
  <lastlog_enab>yes</lastlog_enab>
  <obscure_checks_enab>no</obscure_checks_enab>
  <encryption>md5</encryption>
  <pass_max_days>99999</pass_max_days>
  <pass_max_len>32</pass_max_len>
  <pass_min_days>1</pass_min_days>
  <pass_min_len>5</pass_min_len>
  <pass_warn_age>14</pass_warn_age>
  <passwd_encryption>md5</passwd_encryption>
  <passwd_use_cracklib>yes</passwd_use_cracklib>
  <permission_security>easy</permission_security>
  <run_updatedb_as>nobody</run_updatedb_as>
  <uid_max>999</uid_max>
  <uid_min>500</uid_min>
</security>



<sysconfig config:type="list">
  <sysconfig_entry>
    <sysconfig_path>/etc/sysconfig/cron</sysconfig_path>
    <sysconfig_key>CLEAR_TMP_DIRS_AT_BOOTUP</sysconfig_key>
    <sysconfig_value>yes</sysconfig_value>
  </sysconfig_entry>
  <sysconfig_entry>
    <sysconfig_path>/etc/sysconfig/boot</sysconfig_path>
    <sysconfig_key>RUN_PARALLEL</sysconfig_key>
    <sysconfig_value>yes</sysconfig_value>
  </sysconfig_entry>
  <sysconfig_entry>
    <sysconfig_path>/etc/sysconfig/displaymanager</sysconfig_path>
    <sysconfig_key>DISPLAYMANAGER_XSERVER_TCP_PORT_6000_OPEN</sysconfig_key>
    <sysconfig_value>yes</sysconfig_value>
  </sysconfig_entry>
</sysconfig>



<users config:type="list">
  <user>
    <username>root</username>
    <user_password>$C[ROOTPW]</user_password>
    <encrypted config:type="boolean">true</encrypted>
    <fullname>$C[HOSTNAME] Super-User</fullname>
  </user>
</users>


<scripts>
  <post-scripts config:type="list">
    <script>
      <filename>setup-userfix.sh</filename>
      <network_needed config:type="boolean">true</network_needed>
      <notification>Change local numerical UID/GID that conflict with entries in LDAP</notification>
      <location>http://$C[INSTSERVER]/scripts/setup-userfix.sh</location>
    </script>
    <script>
      <filename>setup-dns.sh</filename>
      <network_needed config:type="boolean">true</network_needed>
      <notification>Post install: Change DNS Settings</notification>
      <location>http://$C[INSTSERVER]/scripts/setup-dns.sh</location>
    </script>
    <script>
      <filename>setup-sudo.sh</filename>
      <network_needed config:type="boolean">true</network_needed>
      <notification>Post install: Change SUDO Settings</notification>
      <location>http://$C[INSTSERVER]/scripts/setup-sudo.sh</location>
    </script>
    <script>
      <filename>setup-videodriver.sh</filename>
      <network_needed config:type="boolean">true</network_needed>
      <notification>Post install: Video Driver Settings</notification>
      <location>http://$C[INSTSERVER]/scripts/setup-videodriver.sh</location>
    </script>
    <script>
      <filename>setup-x11.sh</filename>
      <network_needed config:type="boolean">true</network_needed>
      <notification>Post install: Change X11 Settings</notification>
      <location>http://$C[INSTSERVER]/scripts/setup-x11.sh</location>
    </script>
    <script>
      <filename>setup-misc.sh</filename>
      <network_needed config:type="boolean">true</network_needed>
      <notification>Post install: Change Misc Settings</notification>
      <location>http://$C[INSTSERVER]/scripts/setup-misc.sh</location>
    </script>
  </post-scripts>

  <init-scripts config:type="list">
    <script>
      <filename>i01_setup-ntp.sh</filename>
      <location>http://$C[INSTSERVER]/scripts/setup-ntp.sh</location>
    </script>
    <script>
      <filename>i02_setup-ldap.sh</filename>
      <location>http://$C[INSTSERVER]/scripts/setup-ldap.sh</location>
    </script>
    <script>
      <filename>i02_setup-printer.sh</filename>
      <location>http://$C[INSTSERVER]/scripts/setup-printer.sh</location>
    </script>
    <script>
      <filename>i03_setup-vmware.sh</filename>
      <location>http://$C[INSTSERVER]/scripts/setup-vmware.sh</location>
    </script>
    <script>
      <filename>i04_setup-nx.sh</filename>
      <location>http://$C[INSTSERVER]/scripts/setup-nx.sh</location>
    </script>
    <script>
      <filename>i05_setup-fonts.sh</filename>
      <location>http://$C[INSTSERVER]/scripts/setup-fonts.sh</location>
    </script>
    <script>
      <filename>i06_setup-grub.sh</filename>
      <location>http://$C[INSTSERVER]/scripts/setup-grub.sh</location>
    </script>
  </init-scripts>
</scripts>

</profile>

Post-Install Scripts

Ein Beispiel fuer ein Post-Install, welches Netzwerk-Parameter aus dem PHP-Script myconfig.php erhält.

setup-dns.sh

#!/bin/bash
PATH="/bin:/sbin:/usr/bin:/usr/sbin"
unset http_proxy https_proxy ftp_proxy no_proxy
unset HTTP_PROXY HTTPS_PROXY FTP_PROXY NO_PROXY

echo "###############################################################################"
echo "# Setup DNS Resover                                                           #"
echo "###############################################################################"

curl -q -s -o /var/tmp/.myconfig http://install.example.com/myconfig.php
source /var/tmp/.myconfig || exit 1


backupFile /etc/nsswitch.conf
backupFile /etc/resolv.conf

sed -i -r -e 's/^hosts:.*/hosts: files dns/' /etc/nsswitch.conf

cat >/etc/resolv.conf <<EOF
nameserver $DNSSERVER1
nameserver $DNSSERVER2
domain $DNSDOMAIN
search $DNSDOMAIN $DNSSEARCH1 $DNSSEARCH2 $DNSSEARCH3 $DNSSEARCH4
options ndots:1
options rotate
EOF