#!/bin/ksh93 LIC='[-?$Id$] [-copyright?Copyright (c) 2012 Jens Elkner. All rights reserved.] [-license?CDDL 1.0]' ############################################################################ # "bootstrap" stuff ############################################################################ typeset -r LIBNAME="${.sh.file}" . ${LIBNAME%/*}/log.kshlib . ${LIBNAME%/*}/man.kshlib . ${LIBNAME%/*}/utils.kshlib PROG=${.sh.file##*/} Man.addVar REPOBASE 'TopLevel Directory unter dem alle Repos angelegt werden' REPOBASE='/data/repos' Man.addVar HTTPDBASE 'Base directory für den httpd proxy' HTTPDBASE='/data/httpd' Man.addVar POOLBASE 'ZFS pool der benutzt werden soll, um die jeweiligen Filesysteme für die Repos anzulegen, falls $REPOBASE noch nicht existiert. Wir gehen davon aus, daß die zone einen _dataset_ mit dem alias \bpool1\b bekommt, der für alle Daten genutzt wird (siehe zonecfg).' POOLBASE='pool1' Man.addVar ME 'Offizieller FQDN dieses servers, der in URLs verwendet werden soll' ME=${ uname -n; }'.cs.ovgu.de' typeset -ft $(typeset +f) typeset -T Repo_t=( typeset -h 'Name des Repositories (<= 16 Zeichen)' Name='' typeset -h 'Publisher prefix des Repositories' Prefix='' typeset -h 'optional: Für das Spiegeln zu verwendender URL' Src='' typeset -h 'optional: Datei mit dem SSL-Schlüssel zwecks Zugriff auf das .SslCert' SslKey='' typeset -h 'optional: für den Zugriff auf den Mirror zu verwendendes SSL Zertifikat' SslCert='' typeset -h 'eineindeutiger Port der nach html requests abgehört wird' -i Port=0 typeset -h 'Anzahl der HTTP threads (use ~ 20/client)' -i Threads=64 typeset -h 'Kurzbeschreibung des Repositories (<= 60 Zeichen)' Desc='' ) Man.addVar REPOS 'Definition aller Repositories auf diesem Server. Der Eintrag mit Index 0 wird immer dem SMF-Service \bpkg/server:default\b zugewiesen.' Repo_t -a REPOS=( (Name=solaris Prefix=solaris Port=81 Threads=512 Src=https://pkg.oracle.com/solaris/support/ SslKey=/var/pkg/ssl/Oracle_Solaris_11_Support.key.pem SslCert=/var/pkg/ssl/Oracle_Solaris_11_Support.certificate.pem Desc="Solaris 11 Support Mirror" ) (Name=studio Prefix=solarisstudio Port=82 Src=https://pkg.oracle.com/solarisstudio/release/ SslKey=/var/pkg/ssl/Oracle_Solaris_Studio.key.pem SslCert=/var/pkg/ssl/Oracle_Solaris_Studio.certificate.pem Desc="Solaris Studio Mirror (C, C++, Fortran Dev Suite)" ) (Name=lnf Prefix=lnf Port=83 Desc="Elke's Solaris 11 Pakete" ) (Name=fin Prefix=fin Port=84 Desc="Pakete zum Anpassen von lokalen Zonen/AI-Installationen" ) (Name=idr Prefix=idr Port=85 Desc="Solaris 11+ IDRs" ) # (Name=glassfish Prefix=source Port=85 # Src=http://pkg.glassfish.org/v3/stable/ # Desc="Glassfish stable mirror" # ) # (Name=glassfish.contrib Prefix=source Port=86 # Src=http://pkg.glassfish.org/v3/contrib/ # Desc="Glassfish contrib mirror" # ) ) export PATH=/usr/sbin:$PATH Man.addFunc getRepoIndex '' '[+NAME?getRepoIndex - finde Index zu einem Repo-Name] [+DESCRIPTION?Ermittelt den Index des Repos mit dem angegebenen Namen und gibt diesen aus, oder nichts falls unbekannt.] [+ENVIRONMENT VARIABLES]{' "${ Man.varUsage REPOS ; }" '} \n\n\arepoName\a ' function getRepoIndex { [[ -z $1 ]] && Log.warn 'Repository Name nicht angegeben!' && return typeset IDX for IDX in ${!REPOS[*]}; do [[ ${REPOS[$IDX].Name} == "$1" ]] && print $IDX && return done Log.warn 'Repository "$1" ist unbekannt!' } unsetLocale() { OLDLC=$LC_CTYPE ; OLDMSG=$LC_MESSAGES ; OLDLANG=$LANG unset LC_CTYPE LC_MESSAGES LANG } resetLocale() { LC_CTYPE=$OLDLC ; LC_MESSAGES=$OLDMSG ; LANG=$OLDLANG } Man.addVar REPOZFS 'ZFS das an \b$REPOBASE\b gemountet ist, alle Repos enthält.' REPOZFS='' Man.addFunc checkDirs '' '[+NAME?checkDirs - check Repo-Base-ZFS and -Verzeichnisse.] [+DESCRIPTION?Setzt \b$REPOZFS\b und prüft, ob alle Repo-Base-ZFS und -Verzeichnisse (dort, wo alle Repos reinkommen) vorhanden sind und properties/permissions korrekt gesetzt sind. Falls nicht, wird versucht, selbige zu erstellen bzw. zu korrigieren.] [+ENVIRONMENT VARIABLES]{' "${ Man.varUsage REPOBASE POOLBASE REPOZFS ; }" '} [+SEE ALSO?\bzfs\b(1M)] ' function checkDirs { typeset X if [[ -d $REPOBASE ]]; then REPOZFS=${ /usr/bin/df -h $REPOBASE | tail -1; } REPOZFS=${REPOZFS%%[[:space:]]*} X=${ zfs list -H -o mountpoint $REPOZFS ; } if [[ $X != $REPOBASE ]]; then Log.fatal "$REPOBASE ist kein separates ZFS" exit 1 fi else REPOZFS=$POOLBASE/repos X=${ zfs list -H -o mountpoint $REPOZFS 2>/dev/null ; } if [[ -z $X ]]; then X=${ + zfs create -o compression=on -o atime=off \ -o mountpoint=$REPOBASE $REPOZFS 2>&1 ; } (( $? != 0 )) && Log.fatal "\n$X\n" && exit 1 else REPOBASE=$X fi fi X=${ zfs list -H -o compression $REPOZFS 2>/dev/null ; } [[ $X == 'off' ]] && \ + zfs set compression=on $REPOZFS } Man.addFunc checkRepo '' '[+NAME?checkRepo - ZFS und Verzeichnis-Check für das angegebene Repo.] [+DESCRIPTION?Prüft, ob es das ZFS für das angegebene Repo \arepoName\a existiert, Properties korrekt gesetzt sind und selbiges unterhalb \b$REPOBASE\b gemountet ist. Falls nicht, wird versucht, das fehlende ZFS/Verzeichnis zu erstellen bzw. zu korrigieren.] [+ENVIRONMENT VARIABLES]{' "${ Man.varUsage REPOBASE REPOZFS REPOS ; }" '} [+SEE ALSO?\bgetRepoIndex()\b, \bcheckDirs()\b, \bzfs\b(1M), \bpkgrepo\b(1M), \bchmod\b(1), \bchown\b(1M)] \n\n\arepoName\a ' function checkRepo { typeset I=${ getRepoIndex $1; } [[ -z $I ]] && return [[ -z $REPOZFS ]] && checkDirs typeset REPO=${REPOS[$I].Name} typeset X=${ zfs list -H -o mountpoint $REPOZFS/$REPO 2>/dev/null ; } typeset UID=${ id -un ; } if [[ -z $X ]]; then + zfs create -o atime=off -p $REPOZFS/$REPO (( $? )) && exit 1 + chown ${UID}:root $REPOBASE/$REPO + chmod 0775 $REPOBASE/$REPO elif [[ $X != $REPOBASE/$REPO ]]; then + zfs set mountpoint=$REPOBASE/$REPO $REPOZFS/$REPO (( $? )) && exit 1 fi typeset -a LSI=( ${ ls -ld $REPOBASE/$REPO; } ) # must be owned by root, since depot-srv runs as root but drops privs # required to modify "foreign" files. [[ ${LSI[2]} != $UID || ${LSI[3]} != "root" ]] && \ + chown ${UID}:root $REPOBASE/$REPO [[ ${LSI[0]} != 'drwxrwxr-x' ]] && + chmod 0775 $REPOBASE/$REPO X=${ pkgrepo info -s $REPOBASE/$REPO 2>/dev/null ; } if [[ -z $X ]]; then # create the repo unsetLocale pkgrepo create $REPOBASE/$REPO pkgrepo set -s $REPOBASE/$REPO publisher/prefix=${REPOS[$I].Prefix} \ repository/description="${REPOS[$I].Desc}" \ repository/name="$REPO" resetLocale fi X=${ zfs get -H -o value share.desc $REPOZFS/${REPO}%${REPO} 2>/dev/null ; } if [[ -z $X ]]; then typeset DESC=${REPOS[$I].Desc} DESC=${DESC//,/ /} + zfs share -o share.desc="$DESC" -o share.nfs.anon=0 \ -o share.nfs.sec.none.ro='*' $REPOZFS/${REPO}%${REPO} fi X=${ zfs get -H -o value share.nfs $REPOZFS/${REPO}%${REPO} ; } [[ $X == 'off' ]] && + zfs set share.nfs='on' $REPOZFS/${REPO}%${REPO} } Man.addFunc getService '' '[+NAME?getService - SMF service name für das repo mit angegebenem Index.] [+DESCRIPTION?Gibt den SMF-Servicename für den Package-Service aus, welcher für das Repo mit dem angegebenen Index verantwortlich ist.] [+ENVIRONMENT VARIABLES]{' "${ Man.varUsage REPOS ; }" '} \n\n\aidx\a ' function getService { typeset REPO=${REPOS[$1].Name} [[ $1 == "0" ]] && print 'application/pkg/server:default' && return typeset RSVC=${REPO//./_} print "application/pkg/server:$RSVC" } Man.addFunc updateRepo '' '[+NAME?updateRepo - repo spiegeln/aktualisieren.] [+DESCRIPTION?Spiegelt das Repo mit dem angegebenen Namen (falls ein Mirror hinterlegt ist) und frischt das Repo auf (Re-Indizierung).] [+ENVIRONMENT VARIABLES]{' "${ Man.varUsage REPOS ; }" '} [+SEE ALSO?\bgetRepoIndex()\b, \bcheckRepo()\b, \bpkgrecv\b(1M), \bpkgrepo\b(1M)] \n\n\arepoName\a ' function updateRepo { typeset I=${ getRepoIndex $1 ; } [[ -z $I ]] && return checkRepo $1 typeset MIRROR=${REPOS[$I].Src} if [[ -z $MIRROR ]]; then Log.info "Repo '$1': Src ist nicht gesetzt - gibt nix zu spiegeln" return fi typeset REPO="$1" KEY='' CERT='' TF [[ -n ${REPOS[$I].SslKey} ]] && KEY="--key ${REPOS[$I].SslKey} " [[ -n ${REPOS[$I].SslCert} ]] && CERT="--cert ${REPOS[$I].SslCert} " unsetLocale if [[ ! -d /var/tmp/repo ]] ; then mkdir /var/tmp/repo || exit 1 fi TF=/var/tmp/repo/repo:"$1"-${ date +%Y-%m-%d ; } [[ -r $TF ]] && TF="${TF}-${ date +%H:%M:%S ; }" pkgrecv -s $MIRROR -d $REPOBASE/$REPO/ $KEY $CERT -m all-versions '*' >$TF grep -q '^Republish' $TF if (( $? == 0 )); then print "Neue updates fuer Repo ${REPOS[$I].Name} auf mirror $ME" /usr/bin/egrep -v '^(Processing|Skipping)' $TF # re-indizieren, dauert ca. 40s/GB pkgrepo -s $REPOBASE/$REPO refresh typeset SVC=${ getService $I ; } X=${ svcs -H -o state $SVC 2>/dev/null ; } [[ $X == 'online' ]] && svcadm restart $SVC else rm "$TF" fi resetLocale } Man.addFunc updateSvc '' '[+NAME?updateSvc - update and refresh service parameters.] [+DESCRIPTION?Prüft die SMF service parameter für den Package-Server des angegebenen Repos (Verzeichnis, Threads, Port, Read-Only, Proxy-Base), setzt/korrigiert jene und re-startet den Dienst bei Bedarf. Falls ein zweiter parameter übergeben wird, wird das Repo auf read-write gesetzt, anderenfalls auf read-only. Diese Function prüft nicht, ob die entsprechenden Verzeichnisse existieren.] [+ENVIRONMENT VARIABLES]{' "${ Man.varUsage REPOS REPOBASE ; }" '} [+SEE ALSO?\bgetRepoIndex()\b, \bgetService()\b, \bsvccfg\b(1M), \bsvcadm\b(1M), \bsvcs\b(1)] \n\n\arepoName\a [\aread_write\a] ' function updateSvc { typeset I=${ getRepoIndex $1 ; } [[ -z $I ]] && return typeset SVC=${ getService $I ; } integer CHANGED=0 # configure the service typeset -A cfg cfg[inst_root]=$REPOBASE/${REPOS[$I].Name} cfg[threads]=${REPOS[$I].Threads} cfg[port]=${REPOS[$I].Port} cfg[readonly]='true' cfg[proxy_base]="http://$ME/$1" [[ -n $2 && -z ${REPOS[$I].Src} ]] && cfg[readonly]='false' typeset INSTANCE=${SVC%:default} X KEY VAL if [[ $INSTANCE == $SVC ]]; then X=${ svccfg -s ${SVC%:*} list ${SVC#*:} | grep -v ^: ; } if [[ -z $X ]]; then # need to add svccfg -s ${SVC%:*} add ${SVC#*:} svccfg -s $SVC addpg pkg application svccfg -s $SVC addpg general framework svccfg -s $SVC addpropvalue general/complete astring: ${SVC#*:} svccfg -s $SVC addpropvalue general/enabled boolean: true fi fi for KEY in ${!cfg[@]}; do VAL=${ svcprop -p pkg/$KEY $SVC 2>/dev/null ; } if [[ $VAL != ${cfg[$KEY]} ]]; then (( CHANGED++ )) svccfg -s $INSTANCE setprop pkg/$KEY=${cfg[$KEY]} fi done (( ! CHANGED )) && return svccfg -s $SVC refresh X=${ svcs -H -o state $SVC 2>/dev/null ; } [[ -n $X ]] && svcadm restart $SVC # check Log.info "$SVC rekonfiguriert. Check: firefox http://${ME}:${REPOS[$I].Port}/" # todo: setup apache and redirect so we can use http://$ME/$REPO/ # redirected to the pkg.depotd on different ports of this machine } Man.addFunc enableDisableSvc '' '[+NAME?enableDisableSvc - [de]]aktiviere Package Service] [+DESCRIPTION?Deaktiviert bzw. aktiviert (falls zweiter Parameter angegeben) den Package Service für das angegebene Repo. Bei lezterem werden die repo-Verzeichnisse als auch Dienst-Properties auf Konsistenz und Korrektheit geprüft.] [+ENVIRONMENT VARIABLES]{' "${ Man.varUsage REPOS REPOBASE ; }" '} [+SEE ALSO?\bgetRepoIndex()\b, \bgetService()\b, \bcheckRepo()\b, \bupdateSvc()\b, \bsvcadm\b(1M)] \n\n\arepoName\a [\aenable\a] ' function enableDisableSvc { typeset I=${ getRepoIndex $1 ; } [[ -z $I ]] && return typeset SVC=${ getService $I ; } X X=${ svcs -H -o state $SVC 2>/dev/null ; } if [[ -z $2 ]]; then # disable [[ -n $X && $X != 'disabled' ]] && svcadm disable $SVC else checkRepo $1 updateSvc $1 [[ $X != 'online' ]] && svcadm enable $SVC fi } Man.addFunc deleteSvc '' '[+NAME?deleteSvc - deaktivierte und löscht Package Service] [+DESCRIPTION?Deaktiviert und löscht den Package Service fuer das angegebene Repo, soweit das nicht das default Repo ist.] [+SEE ALSO?\bgetRepoIndex()\b, \bgetService()\b, \bsvccfg\b(1M)] \n\n\arepoName\a ' function deleteSvc { typeset I=${ getRepoIndex $1 ; } [[ -z $I ]] && return enableDisableSvc $1 typeset SVC=${ getService $I ; } if [[ ${SVC%:default} != $SVC ]]; then Log.warn 'Der default service kann nicht geloescht werden.' return fi svccfg -s ${SVC%:*} delete $1 } Man.addFunc listRepos '' '[+NAME?listRepos - Liste alle Repos.] [+DESCRIPTION?Listet alle Repo-Namen inkl. Beschreibung. Wird ein Parameter übergeben, werden ebenfalls die ZFS infos mit ausgegeben.] [+ENVIRONMENT VARIABLES]{' "${ Man.varUsage REPOS REPOZFS ; }" '} [+SEE ALSO?\bcheckDirs()\b, \bzfs\b(1M)] \n\n[\alistZFS\a] ' function listRepos { printf '%16s %s\n' REPOSITORY BESCHREIBUNG typeset I ERRORS for I in ${!REPOS[*]}; do printf '%16s %s\n' "${REPOS[$I].Name}" "${REPOS[$I].Desc}" done [[ -z $1 ]] && return [[ -z $REPOZFS ]] && checkDirs typeset -a LREPOS=( $REPOZFS ) for I in ${!REPOS[*]}; do X=${ zfs list -H $REPOZFS/${REPOS[$I].Name} 2>&1 ; } if (( ! $? )); then LREPOS+=" $REPOZFS/${REPOS[$I].Name}" else ERRORS+="$X\n" fi done print zfs list $LREPOS [[ -n $ERRORS ]] && Log.warn "$ERRORS" } Man.addFunc showClientInfo '' '[+NAME?showClientInfo - Client usage info anzeigen.] [+DESCRIPTION?Zeigt die pkg Kommando-Varianten, wie das angegegbene Repo genutzt werden kann.] [+ENVIRONMENT VARIABLES]{' "${ Man.varUsage REPOS ; }" '} [+SEE ALSO?\bgetRepoIndex()\b, \bpkg\b(1)] \n\n\arepoName\a ' function showClientInfo { typeset I=${ getRepoIndex $1 ; } [[ -z $I ]] && return typeset REPO=$1 TITLE="$REPO Mirror Nutzung - eine der folgenden Varianten:" typeset UL='===============================================================================' integer LEN=${#TITLE} print "$TITLE\n${UL:0:$LEN} pkg set-publisher \\ --remove-origin=${REPOS[$I].Src} \\ --add-origin=file:///net/$ME/$REPOBASE/$REPO/ \\ ${REPOS[$I].Prefix} pkg set-publisher \\ --remove-origin=${REPOS[$I].Src} \\ --add-origin=http://${ME}/$REPO/ \\ ${REPOS[$I].Prefix} pkg set-publisher \\ --remove-origin=${REPOS[$I].Src} \\ --add-origin=http://${ME}:${REPOS[$I].Port}/$REPO/ \\ ${REPOS[$I].Prefix} " } Man.addVar APACHE 'Apache HTTPd relevante Konfigurationen. Siehe \bgetApacheEnv()\b' typeset -A APACHE=( ) Man.addFunc getApacheEnv '' '[+NAME?getApacheEnv - Bestimmt Apache HTTPd relevante Infos.] [+DESCRIPTION?Prüft, ob ein \bhttp:apache\b SMF service installiert ist, sowie die Basis-Verzeichnisse der Apache-Installation und sichert selbige in der Variable \bAPACHE\b.] [+ENVIRONMENT VARIABLES]{' "${ Man.varUsage APACHE ; }" '} [+SEE ALSO?\bsvcs\b(1), \bsvcprop\b(1), \bpkg\b(1)] ' function getApacheEnv { [[ -n ${APACHE[SVC]} ]] && return typeset X=${ svcs -a | grep /http:apache | sort -b -k 3 | tail -1 ; } if [[ -z $X ]]; then Log.fatal 'Es gibt keinen http:apache* Service.\nPackage /web/server/apache-22 oder höher nicht installiert?' exit 1 fi APACHE[SVC]=${X##*svc:} X=${ svcprop -p tm_man_httpd8/manpath ${APACHE[SVC]} 2>/dev/null ; } X=${X%/*} if [[ -z $X || ! -x $X/bin/64/httpd ]]; then X=${ pkg search -l -H -o search.match '*/bin/httpd' 2>/dev/null ; } X=/${X%/bin/httpd} fi if [[ ! -x $X/bin/64/httpd ]]; then Log.fatal 'Konnte ServerRoot nicht bestimmen.\nPackage /web/server/apache-22 oder höher nicht installiert?' exit 1 fi APACHE[ROOT]=$X APACHE[VERS]=${X##*/} APACHE[DEFBASE]=/var/apache2/${APACHE[VERS]} APACHE[ETC]=/etc/apache2/${APACHE[VERS]} APACHE[LOGS]=${APACHE[DEFBASE]}/logs/$ME APACHE[MYUID]=${ id -un ; } APACHE[MYGID]=${ id -gn ; } APACHE[BASE]=$HTTPDBASE } Man.addFunc checkApacheHttpdDirs '' '[+NAME?checkApacheHttpdDirs - Check Apache HTTPd relevanter Verzeichnisse und ZFS] [+DESCRIPTION?Prüft ob Apache HTTPd relevanten ZFS und Verzeichnisse existieren und Permissions/Properties korrekt gesetzt sind. Falls nicht, wird versucht ZFS/Verzeichnsse zu erstellen und ggf. Parameter/Properties zu korrigieren.] [+ENVIRONMENT VARIABLES]{' "${ Man.varUsage APACHE POOLBASE ; }" '} [+SEE ALSO?\bgetApacheEnv()\b, \bzfs\b(1M), \bchown\b(1), \bchmod\b(1), \bmkdir\b(1)] ' function checkApacheHttpdDirs { getApacheEnv [[ -n ${APACHE[DIRSOK]} ]] && return if [[ ! -d ${APACHE[BASE]} ]]; then typeset HTTPDZFS=$POOLBASE/httpd typeset X=${ zfs list -H -o mountpoint $HTTPDZFS 2>/dev/null ; } if [[ -z $X ]]; then X=${ + zfs create -o compression=on -o atime=off \ -o mountpoint=${APACHE[BASE]} $HTTPDZFS 2>&1 ; } (( $? )) && Log.fatal "\n$X\n" && exit 1 + chown ${APACHE[MYUID]}:${APACHE[MYGID]} ${APACHE[BASE]} else APACHE[BASE]=$X X=${ zfs list -H -o compression $HTTPDZFS 2>/dev/null ; } [[ $X == 'off' ]] && + zfs set compression=on $HTTPDZFS fi fi typeset -a LSI=( ${ ls -ld ${APACHE[BASE]} ; } ) [[ ${LSI[2]} != ${APACHE[MYUID]} ]] && \ + chown ${APACHE[MYUID]} ${APACHE[BASE]} typeset DIR for DIR in conf conf/proxies htdocs cgi-bin ssl.key ssl.crt; do if [[ ! -d ${APACHE[BASE]}/$DIR ]]; then + mkdir ${APACHE[BASE]}/$DIR + chown ${APACHE[MYUID]} ${APACHE[BASE]}/$DIR fi done LSI=( ${ ls -ld ${APACHE[BASE]}/ssl.key ; } ) [[ ${LSI[0]} != "drwxr-x---" ]] && + chmod 0750 ${APACHE[BASE]}/ssl.key [[ ${LSI[2]} != ${APACHE[MYUID]} || ${LSI[3]} != webservd ]] && \ + chown ${APACHE[MYUID]}:webservd ${APACHE[BASE]}/ssl.key [[ ! -d ${APACHE[LOGS]} ]] && + mkdir -p ${APACHE[LOGS]} LSI=( ${ ls -ld ${APACHE[LOGS]} ; } ) [[ ${LSI[2]} != webservd ]] && + chown webservd ${APACHE[LOGS]} APACHE[DIRSOK]=true } Man.addFunc updateApacheHttpdSvc '' '[+NAME?updateApacheHttpdSvc - check Apache HTTPd service parameters.] [+DESCRIPTION?Prüft und korrigiert ggf. die SMF Service Properties für den Apache HTTPd. Falls noch keine Apache Konfig exisitiert, wird diese erstellt.] [+ENVIRONMENT VARIABLES]{' "${ Man.varUsage APACHE ; }" '} [+SEE ALSO?\bcheckApacheHttpdDirs()\b, \bcreateApacheHttpdConf()\b, \bsvcprop\b(1), \bsvccfg\b(1M)] ' function updateApacheHttpdSvc { checkApacheHttpdDirs [[ ! -f ${APACHE[BASE]}/conf/httpd.conf ]] && createApacheHttpdConf # what we want typeset -A tcfg=( ) tcfg[httpd/enable_64bit]='true' tcfg[httpd/server_type]='worker' tcfg[httpd/startup_options]="-f ${APACHE[BASE]}/conf/httpd.conf" tcfg[start/user]='webservd' tcfg[start/group]='webservd' tcfg[start/limit_privileges]=':default' tcfg[start/privileges]='basic,!proc_session,!proc_info,!file_link_any,net_privaddr' tcfg[stop/user]='webservd' tcfg[stop/group]='webservd' integer CHANGED=0 typeset KEY VAL X for KEY in ${!tcfg[@]}; do VAL=${ svcprop -p $KEY ${APACHE[SVC]} 2>/dev/null ; } if [[ ${tcfg[$KEY]} != $VAL ]]; then if [[ $KEY == "httpd/startup_options" ]]; then # quick und dirty - alles andere macht zuviel Arbeit bei Listen svccfg -s ${APACHE[SVC]} setprop \ "$KEY=(\"-f\" \"${APACHE[BASE]}/conf/httpd.conf\")" else svccfg -s ${APACHE[SVC]} "setprop $KEY=${tcfg[$KEY]}" fi CHANGED=$((CHANGED+1)) fi done X=${ svcprop -p start/environment ${APACHE[SVC]} 2>/dev/null ; } if [[ $X != 'LD_PRELOAD=libmtmalloc.so' ]]; then svccfg -s ${APACHE[SVC]} setenv -m start LD_PRELOAD libmtmalloc.so ((CHANGED++)) fi (( $CHANGED )) && svccfg -s ${APACHE[SVC]} refresh } Man.addFunc createApacheHttpdConf '' '[+NAME?createApacheHttpdConf - erstellt Apache HTTPd config.] [+DESCRIPTION?Erstellt eine standard httpd.conf in \b$APACHE[BASE]]/conf/\b inklusive proxy configs. Falls es bereits eine gibt, wird diese als \bhttpd.conf-\b\atimestamp\a zuvor gesichert.] [+ENVIRONMENT VARIABLES]{' "${ Man.varUsage APACHE ; }" '} [+SEE ALSO?\bcheckApacheHttpdDirs()\b, \bupdateProxyConf()\b] ' function createApacheHttpdConf { checkApacheHttpdDirs typeset CONF=${APACHE[BASE]}/conf/httpd.conf I X if [[ -r $CONF ]]; then + cp -p $CONF ${CONF}-$(date +%Y%m%d-%H:%M:%S) fi integer SSTART=2 integer MINSPARE=48 integer MAXSPARE=$((2*MINSPARE)) # max. number of simultaneous connections excl. proxy pools integer MAXCCON=64 integer MAXPCON=0 # + satisfy those requesting the proxied pkg servers for I in ${!REPOS[@]}; do MAXCCON=$((MAXCCON+${REPOS[$I].Threads})) (( ${REPOS[$I].Threads} > $MAXPCON )) && MAXPCON=${REPOS[$I].Threads} done integer MAXPROC=${ psrinfo | wc -l ; } integer CTHREADS=$((MAXCCON/MAXPROC)) (( $CTHREADS > $MINSPARE )) && SSTART=1 (( $MAXSPARE < $((MAXCCON/3)) )) && MAXSPARE=$((MAXCCON/3)) (( $MAXSPARE < $MINSPARE )) && MAXSPARE=$MINSPARE (( $CTHREADS > $MAXSPARE )) && SSTART=1 typeset TLIMIT="" (( $CTHREADS > 64 )) && TLIMIT="ThreadLimit $CTHREADS" cat >$CONF<s \"%r\" \"%{Referer}i\" \"%{User-Agent}i\"" extended # As long as no access files are in use, avoid the lookup overhead, but avoid # compromising such files, if accidently put into the directory. #AccessFileName .htaccess Order allow,deny Deny from all AddHandler cgi-script .cgi AddHandler send-as-is asis Listen 443 SSLRandomSeed startup file:/dev/urandom 512 SSLRandomSeed connect file:/dev/urandom 512 SSLCryptoDevice pkcs11 AddType application/x-x509-ca-cert .crt AddType application/x-pkcs7-crl .crl SSLSessionCacheTimeout 300 SSLMutex sem SSLCipherSuite ALL:!ADH:!kEDH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL SSLHonorCipherOrder on SSLOptions +StdEnvVars SSLOptions +StdEnvVars BrowserMatch ".*MSIE.*" nokeepalive ssl-unclean-shutdown \ downgrade-1.0 force-response-1.0 LogFormat "%h %{%F %T %z}t %X %I %O %B %D %{SSL_PROTOCOL}x %{SSL_CIPHER}x %u %>s \"%r\" \"%{Referer}i\" \"%{User-Agent}i\"" extendedssl Options -FollowSymLinks AllowOverride None Order allow,deny Allow from all Alias /icons/ "${APACHE[DEFBASE]}/icons/" Options Indexes MultiViews AllowOverride None Order allow,deny Allow from all AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip AddIconByType (TXT,/icons/text.gif) text/* AddIconByType (IMG,/icons/image2.gif) image/* AddIconByType (SND,/icons/sound2.gif) audio/* AddIconByType (VID,/icons/movie.gif) video/* AddIcon /icons/binary.gif .bin .exe AddIcon /icons/binhex.gif .hqx AddIcon /icons/tar.gif .tar AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip AddIcon /icons/a.gif .ps .ai .eps AddIcon /icons/layout.gif .html .shtml .htm .pdf AddIcon /icons/text.gif .txt AddIcon /icons/c.gif .c AddIcon /icons/p.gif .pl .py AddIcon /icons/f.gif .for AddIcon /icons/dvi.gif .dvi AddIcon /icons/uuencoded.gif .uu AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl AddIcon /icons/tex.gif .tex AddIcon /icons/bomb.gif core AddIcon /icons/back.gif .. AddIcon /icons/hand.right.gif README AddIcon /icons/folder.gif ^^DIRECTORY^^ AddIcon /icons/blank.gif ^^BLANKICON^^ DefaultIcon /icons/unknown.gif ReadmeName README.html HeaderName HEADER.html IndexIgnore .ht* *~ *# HEADER* RCS CVS *,v *,t Alias /error/ "${APACHE[DEFBASE]}/error/" AllowOverride None Options IncludesNoExec AddOutputFilter Includes html AddHandler type-map var Order allow,deny Allow from all LanguagePriority de en fr es cs it ja ko nl pl pt-br ro sv tr ForceLanguagePriority Prefer Fallback ErrorDocument 400 /error/HTTP_BAD_REQUEST.html.var ErrorDocument 401 /error/HTTP_UNAUTHORIZED.html.var ErrorDocument 403 /error/HTTP_FORBIDDEN.html.var ErrorDocument 404 /error/HTTP_NOT_FOUND.html.var ErrorDocument 405 /error/HTTP_METHOD_NOT_ALLOWED.html.var ErrorDocument 408 /error/HTTP_REQUEST_TIME_OUT.html.var ErrorDocument 410 /error/HTTP_GONE.html.var ErrorDocument 411 /error/HTTP_LENGTH_REQUIRED.html.var ErrorDocument 412 /error/HTTP_PRECONDITION_FAILED.html.var ErrorDocument 413 /error/HTTP_REQUEST_ENTITY_TOO_LARGE.html.var ErrorDocument 414 /error/HTTP_REQUEST_URI_TOO_LARGE.html.var ErrorDocument 415 /error/HTTP_UNSUPPORTED_MEDIA_TYPE.html.var ErrorDocument 500 /error/HTTP_INTERNAL_SERVER_ERROR.html.var ErrorDocument 501 /error/HTTP_NOT_IMPLEMENTED.html.var ErrorDocument 502 /error/HTTP_BAD_GATEWAY.html.var ErrorDocument 503 /error/HTTP_SERVICE_UNAVAILABLE.html.var ErrorDocument 506 /error/HTTP_VARIANT_ALSO_VARIES.html.var ScriptAlias /cgi-bin/printenv ${APACHE[DEFBASE]}/cgi-bin/printenv Order allow,deny Allow from 127.0.0.1/32 10.0.0.0/24 ExtendedStatus On SetHandler server-status Order allow,deny Allow from 127.0.0.1 10.0.0.0/24 88.150.13.240 SetHandler server-info Order allow,deny Allow from 127.0.0.1 10.0.0.0/24 88.150.13.240 DirectoryIndex index.shtml index.html index.html.var IndexOptions FancyIndexing FoldersFirst VersionSort NameWidth=* DescriptionWidth=* AddOutputFilterByType DEFLATE \\ text/html application/javascript text/css text/plain AllowEncodedSlashes NoDecode DocumentRoot "${APACHE[BASE]}/htdocs" Options Indexes MultiViews -FollowSymLinks AllowOverride None Order allow,deny Allow from all ScriptAlias /cgi-bin/ "${APACHE[BASE]}/cgi-bin/" AllowOverride None Options None Order allow,deny Allow from all RewriteLogLevel 0 RewriteLog "|${APACHE[ROOT]}/bin/rotatelogs ${APACHE[LOGS]}/%Y%m%d-%H%M%S-rewrite.log 86400" ErrorLog "|${APACHE[ROOT]}/bin/rotatelogs ${APACHE[LOGS]}/%Y%m%d-%H%M%S-error.log 86400" CustomLog "|${APACHE[ROOT]}/bin/rotatelogs ${APACHE[LOGS]}/%Y%m%d-%H%M%S-access.log 86400" extended env=!SSL_PROTOCOL ScriptSock ${APACHE[LOGS]}/cgid.sock CustomLog "|${APACHE[ROOT]}/bin/rotatelogs ${APACHE[LOGS]}/%Y%m%d-%H%M%S-ssl.log 86400" extendedssl env=SSL_PROTOCOL SSLSessionCache shmcb:${APACHE[LOGS]}/ssl_scache(512000) SSLPassPhraseDialog exec:${APACHE[BASE]}/conf/pass SSLCACertificatePath ${APACHE[BASE]}/conf/ssl.crt SSLCARevocationPath ${APACHE[BASE]}/conf/ssl.crl SSLCertificateFile ${APACHE[BASE]}/conf/ssl.crt/$ME.crt SSLCertificateKeyFile ${APACHE[BASE]}/conf/ssl.key/$ME.key SSLEngine on # Include all files in the given directory Include ${APACHE[BASE]}/conf/proxies/ EOF for I in ${!REPOS[@]}; do updateProxyConf ${REPOS[$I].Name} done X=${APACHE[BASE]}/htdocs/intern cat >${APACHE[BASE]}/conf/proxies/intern.conf< Options +Indexes +Includes +MultiViews AllowOverride None Order Allow,Deny Allow from 141.44.0.0/16 EOF } Man.addFunc updateProxyConf '' '[+NAME?updateProxyConf - Aktualisiert Apache HTTPd proxy config include Datei] [+DESCRIPTION?Aktualisiert bzw. löscht die proxy config include Datei für das angegebene Repo.] [+ENVIRONMENT VARIABLES]{' "${ Man.varUsage APACHE ; }" '} [+SEE ALSO?\bgetApacheEnv()\b] \n\n\arepoName\a ' function updateProxyConf { typeset REPO="$1" getApacheEnv typeset I=${ getRepoIndex $REPO ; } typeset CONF=${APACHE[BASE]}/conf/proxies/${REPO}.proxy if [[ -z $I ]]; then [[ -r $CONF ]] && rm -f $CONF [[ -d ${APACHE[BASE]}/htdocs/$REPO ]] && \ rmdir ${APACHE[BASE]}/htdocs/$REPO return fi # can't use this var directly because of ksh bug typeset PORT=${REPOS[$I].Port} typeset MAX=${REPOS[$I].Threads} cat>|$CONF</dev/null ; } if [[ -z $1 ]]; then # disable [[ -n $X && $X != "disabled" ]] && svcadm disable ${APACHE[SVC]} else updateApacheHttpdSvc if [[ $X != 'online' ]]; then [[ ! -r ${APACHE[BASE]}/conf/httpd.conf ]] && createApacheHttpdConf svcadm enable ${APACHE[SVC]} fi fi } Man.addFunc showUsage '' '[+NAME?showUsage - Zeigt Hilfe zu einer Funktion oder diesem Script.] [+DESCRIPTION?Falls \aarg2\a == \bMAIN\b ist, wird die Hilfe zum Script angezeigt, anderenfalls zu einer Funktion mit entsprechendem Namen, wenn vorhanden. \aarg1\a gibt den in der Synopsis angezeigten Programm- bzw. Funktions-Namen an.] \n\nprogname fname ' function showUsage { typeset WHAT="$2" getopts -a "$PROG" "${ print ${Man.FUNC[$WHAT]}; }" OPT --man } Man.addFunc MAIN '' '[+NAME?'"$PROG"' - Script zum Managen von [gespiegelten]] IPS Repositories.] [+DESCRIPTION?Diese Script dient zum Managen von [gespiegelten]] IPS Repositories. Ist kein \arepoName\a angegeben, bezieht sich der jeweilige Befehl auf alle Repos, anderenfalls nur auf die angegebenen. Alle Repositories müssen in diesem Script (ziemlich am Anfang) inkl. notwendiger Parameter in der Variablen \bREPOS\b eingetragen werden.] [+?Initialisierung (einmalig):]{ [+0) REPOS? Variable in diesem Script anpassen] [+1) '"$PROG"' -u?Repos initialisieren und aktualisieren] [+2) '"$PROG"' -A?Apache Httpd conf ersetzen (optional)] [+3) '"$PROG"' -e?Package Server aktivieren] [+4) '"$PROG"' -E?Apache Httpd als Proxy aktivieren] [+5) pkg set-publisher -g http://'"${ME}/${REPOS[0].Prefix}"'/ solaris?Repository verfügbar machen (optional)] } [+?Wie man die Schlüssel/Client-Zertifikate zum Spiegeln des Solaris Support Repositories bekommt, steht unter http://www.oracle.com/technetwork/server-storage/solaris11/overview/solaris11expfaq-186202.html. Für http://pkg.oracle.com/solaris/release/ braucht man keine Zertifikate.] [+EXAMPLES?] [+?Falls ein neues Repository z.B. namens "test" hinzugefügt werden soll, reicht folgendes:] { [+?\bREPOS\b variable mit entsprechendem Eintrag ergänzen] [+?'"$PROG"' -u test] [+?'"$PROG"' -P test] [+?'"$PROG"' -e test] [+?svcadm restart apache22] } [h:help?Diese Hilfe ausgeben und Programm beenden.] [v:verbose?Verbose Mode aktivieren.] [c:client?Client Infos (Repo usage) anzeigen.] [l:list?Alle derzeit eingetragenen Repositories auflisten.] [A:http-conf?Erstellt default Apache HTTPd conf zwecks Proxy inkl. aller Ordner.] [P:proxy-conf?Aktualisiert Apache HTTPd Proxy-Konfiguration (\bconf/\b\arepoName\a\b.proxy\b).] [e:enable-pkg?Package Server aktivieren (\bpkg/server:\b\arepoName\a).] [E:enable-httpd?Apache HTTPd Server aktivieren (\bhttp:apache\b*).] [d:disable-pkg?Package Server deaktivieren (\bpkg/server:\b\arepoName\a).] [D:disable-httpd?Apache HTTPd Server deaktivieren (\bhttp:apache\b*).] [s:svcparams-pkg?Package Server Service Parameter aktualisieren (setzt read-only Mode).] [S:svcparams-httpd?Aktualisiert Apache HTTPd Service Parameter (\bhttp:apache\b*).] [r:remove?Package Server deaktivieren und Service loeschen (\bpkg/server:\b\arepoName\a).] [u:update?Repo spiegeln/aktualisieren.] [w:writeable?Repository auf read-write Mode setzen.] [F:functions?Gebe eine Liste aller derzeit definierten Funktionen aus und beende das Script. Ruft einfach nur das \btypeset +f\b builtin auf.] [H:usage]:[function?Zeige die Beschreibung für die angegebene Funktion an (falls vorhanden) und beende das Script. Siehe auch Option \b-F\b.] [T:trace]:[fname_list?Eine durch Komma der Leerzeichen getrennte List von Funktionen, die während ihrer Ausführung getracet werden soll. Sollte als erste Option angegeben werden (wenn benötigt), da das Tracing für die jeweilige(n) Funktion(en) erst bei der Verarbeitung der Option aktiviert wird, d.h. bei der Verarbeitung anderer Optionen bereits vorher eine der fraglichen Funktionen aufgerufen werden könnte.] \n\n[\arepoName\a]... ' (( ${ id -u ; } == 0 )) \ && Log.fatal "Script nicht als root ausführbar" && exit 1 CMD='' VERBOSE='' while getopts "${ print ${Man.FUNC[MAIN]}; }" option ; do case "$option" in v) VERBOSE=1 ;; c) CMD="CLIENT" ;; l) CMD="LIST" ;; A) CMD="ACONF" ;; P) CMD="PCONF" ;; e) CMD="ENABLE" ;; E) CMD="AENABLE" ;; d) CMD="DISABLE" ;; D) CMD="ADISABLE" ;; s) CMD="SVC" ;; S) CMD="ASVC" ;; r) CMD="DEL" ;; u) CMD="UPDATE" ;; w) CMD="RW" ;; h) showUsage $PROG MAIN ; exit 0 ;; F) typeset +f ; exit 0 ;; H) if [[ ${OPTARG%_t} != $OPTARG ]]; then $OPTARG --man # self-defined types else showUsage "$OPTARG" "$OPTARG" # functions fi exit 0 ;; T) typeset -ft ${OPTARG//,/ } ;; esac done X=$((OPTIND-1)) shift $X [[ -z $CMD ]] && showUsage $PROG MAIN && exit 0 [[ $CMD == 'LIST' ]] && CMD=DONE && listRepos $VERBOSE [[ $CMD == 'ACONF' ]] && CMD=DONE && createApacheHttpdConf [[ $CMD == 'ASVC' ]] && CMD=DONE && updateApacheHttpdSvc [[ $CMD == 'AENABLE' ]] && CMD=DONE && enableDisableApache enable [[ $CMD == 'ADISABLE' ]] && CMD=DONE && enableDisableApache if [[ $CMD != DONE ]]; then integer INFO=0 if [[ -z $1 ]]; then X='' for I in ${!REPOS[@]}; do X="$X ${REPOS[$I].Name}" done [[ -n $X ]] && set -- $X fi while [[ -n $1 ]]; do case $CMD in CLIENT) (( ! $INFO )) && Log.info 'Der Unterschied zwischen ' \ '-[Ori]g[in] und -m[irror]: Metadaten werden immer von' \ 'Origin geholt, nur Pakete selbst werden vom Mirror' \ 'gezogen (siehe auch "pkg publisher").' && (( INFO++ )) showClientInfo $1 ;; ENABLE) enableDisableSvc $1 enable ;; DISABLE) enableDisableSvc $1 ;; UPDATE) updateRepo $1 ;; SVC) updateSvc $1 ;; RW) updateSvc $1 rw ;; DEL) deleteSvc $1 ;; PCONF) updateProxyConf $1 ;; esac shift done fi