diff --git a/conf/opsi-builder.cfg b/conf/opsi-builder.cfg index ac9928d..74939ec 100644 --- a/conf/opsi-builder.cfg +++ b/conf/opsi-builder.cfg @@ -1,16 +1,15 @@ ################################################### -# build-default.cfg -# Default values for OPSI builder system +# opsi-builder.cfg +# Default values for opsi-builder system #################################################### - ################################## # Global variables ################################# TMP_DIR=/tmp # Setup debug level, be more verbose -# Valid values: debug, +# Optional parameter. Valid values: debug|info. Default: DEBUG_LEVEL= # STATUS - defines the stabability of the build diff --git a/doc/README-7zip.txt b/doc/README-7zip.txt new file mode 100644 index 0000000..07a4192 --- /dev/null +++ b/doc/README-7zip.txt @@ -0,0 +1,12 @@ +- the 7zip version in CentOS does include all features. + You can install the version from sf.net + + wget "https://sourceforge.net/projects/p7zip/files/p7zip/9.20.1/p7zip_9.20.1_x86_linux_bin.tar.bz2/download" + tar xfvj p7zip_9.20.1_x86_linux_bin.tar.bz2 + cd p7zip_9.20.1* + + sh install.sh + emacs -nw /etc/profile + PATH=/usr/local/bin:$PATH + export PATH + source /etc/profile diff --git a/lib/builder-targets.sh b/lib/builder-targets.sh index 9d6bc2d..3df69ef 100644 --- a/lib/builder-targets.sh +++ b/lib/builder-targets.sh @@ -16,7 +16,7 @@ builder_config() { # project dependent configuration local config=${PRODUCT_DIR}/builder-product.cfg - test -f ${config} || builder_check_error "can't read product config: ${config}" + test -f ${config} || builder_check_error "cannot read product config: ${config}" . ${config} # set default build configuration and source the user dependent file @@ -49,6 +49,11 @@ builder_config() { echo "configuration error: OPSI_REPOS_BASE_DIR directory does not exist: $OPSI_REPOS_BASE_DIR" exit 2 fi + + if [ "$TYPE" != "public" ] && [ "$TYPE" != "restrict" ] ; then + fatal_error "unknown TYPE: $TYPE" + fi + } ##################### @@ -81,10 +86,10 @@ builder_prepare() { #################### builder_retrieve() { - for (( i = 0 ; i < ${#SOURCE[@]} ; i++ )) ; do - local basename=${FILE[$i]} - local urls=${SOURCE[$i]} - local arch=${ARCH[$i]} + for (( i = 0 ; i < ${#DL_SOURCE[@]} ; i++ )) ; do + local basename=${DL_FILE[$i]} + local urls=${DL_SOURCE[$i]} + local arch=${DL_ARCH[$i]} local downloaded=0 # Add private repos to the urls @@ -102,19 +107,22 @@ builder_retrieve() { echo "Downloading $basename" # check downloading from the defined URLs - for src in `echo $urls | sed -e 's/;/\n/g'` ; do + for src in `echo $urls | sed -e 's/[;,]/\n/g'` ; do if [ $downloaded == 1 ]; then continue; fi echo " Info: Downloding from $src" + local downloader=${DL_DOWNLOADER[$i]} + if [ -z $downloader ]; then downloader="wget" ; fi + mkdir -p ${DIST_CACHE_DIR}/$arch - DIST_FILE[$i]=${DIST_CACHE_DIR}/$arch/$basename - retrieve_file $src ${DIST_FILE[$i]} + DL_DIST_FILE[$i]=${DIST_CACHE_DIR}/$arch/$basename + retrieve_file $downloader $src ${DL_DIST_FILE[$i]} if [ $? == 0 ] ; then # testing the checksum of the downloaded files - SHA1SUM=`cat ${PRODUCT_DIR}/${basename}.sha1sum | cut -d " " -f1` - CHECKSUM=`sha1sum ${DIST_FILE[$i]} | cut -d " " -f1` - if [ "$CHECKSUM" == "$SHA1SUM" ] ; then + local sha1sum_val=`cat ${PRODUCT_DIR}/${basename}.sha1sum | cut -d " " -f1` + local checksum_val=`sha1sum ${DL_DIST_FILE[$i]} | cut -d " " -f1` + if [ "$checksum_val" == "$sha1sum_val" ] ; then downloaded=1 echo " Info: Downloaded successfully" else @@ -146,51 +154,24 @@ builder_create() { find $INST_DIR/CLIENT_DATA -type f | xargs -n1 -iREP sh -c 'file -i $0 | grep "text/plain" && unix2dos $0' REP # converting icon file - local iconfile_src=${DIST_FILE[$ICON_FILE_INDEX]} + local iconfile_src=${DL_DIST_FILE[$ICON_DL_INDEX]} ICONFILE=$OUTPUT_DIR/$PN.png convert_image $iconfile_src $ICONFILE cp -a $ICONFILE $INST_DIR/CLIENT_DATA # copy binaries - for (( i = 0 ; i < ${#SOURCE[@]} ; i++ )) ; do - distfile=${DIST_FILE[$i]} - if [ ! -z "${INSTALL[$i]}" ] ; then - mkdir -p $INST_DIR/CLIENT_DATA/${ARCH[$i]}/${EXTRACTTO[$i]} - extract_file ${DIST_FILE[$i]} $INST_DIR/CLIENT_DATA/${ARCH[$i]}/${EXTRACTTO[$i]} - else - mkdir -p $INST_DIR/CLIENT_DATA/${ARCH[$i]} - cp ${DIST_FILE[$i]} $INST_DIR/CLIENT_DATA/${ARCH[$i]} - fi + for (( i = 0 ; i < ${#DL_SOURCE[@]} ; i++ )) ; do + DL_EXTRACT_PATH[$i]=${INST_DIR}/CLIENT_DATA/${DL_ARCH[$i]}/${DL_EXTRACT_TO[$i]} + local format=${DL_EXTRACT_FORMAT[$i]} + if [ -z "$format" ] ; then format="cp"; fi + + mkdir -p ${DL_EXTRACT_PATH[$i]} + process_file $format ${DL_DIST_FILE[$i]} ${DL_EXTRACT_PATH[$i]} done - # create variables - local var_file=$OUTPUT_DIR/variable.ins - echo -n >$var_file - for (( i = 0 ; i < ${#SOURCE[@]} ; i++ )) ; do - if [ -z ${WINST[$i]} ] ; then continue ; fi - if [ ! -z "${ARCH[$i]}" ] ; then arch_str="${ARCH[$i]}\\" ; fi - if [ ! -z "${EXTRACTTO[$i]}" ] ; then extractto_str="${EXTRACTTO[$i]}\\" ; fi - if [ ! $i -eq $ICON_FILE_INDEX ] ; then - echo "DefVar \$${WINST[$i]}\$" >>$var_file - if [ ! -z "${INSTALL[$i]}" ] ; then - echo "Set \$${WINST[$i]}\$ = \"%ScriptPath%\\$arch_str$extractto_str${INSTALL[$i]}\"" >>$var_file - else - echo "Set \$${WINST[$i]}\$ = \"%ScriptPath%\\$arch_str${FILE[$i]}\"" >>$var_file - fi - fi - done - - # publish some other variables - for var in VENDOR PN VERSION RELEASE PRIORITY ADVICE TYPE CREATOR_TAG CREATOR_NAME CREATOR_EMAIL ; do - echo "DefVar \$${var}\$" >>$var_file - echo "Set \$${var}\$ = \"${!var}\"" >>$var_file - done - - # copy image and create variable - echo "DefVar \$IconFile\$" >>$var_file - echo "Set \$IconFile\$ = \"%ScriptPath%\\`basename $ICONFILE`\"" >>$var_file - - echo >>$var_file + # create winst variables + local var_file=${OUTPUT_DIR}/variable.ins + create_winst_varfile $var_file # add the new vaiables to all *.ins winst files for inst_file in `find ${INST_DIR}/CLIENT_DATA -type f -name "*.ins"` ; do @@ -200,7 +181,7 @@ builder_create() { }" $inst_file done - # replace variables from OPSI control + # replace variables from file OPSI/control local release_new=${CREATOR_TAG}${RELEASE} sed -e "s!VERSION!$VERSION!g" -e "s!RELEASE!${release_new}!g" -e "s!PRIORITY!$PRIORITY!g" -e "s!ADVICE!$ADVICE!g" ${PRODUCT_DIR}/OPSI/control >$INST_DIR/OPSI/control @@ -226,6 +207,7 @@ builder_package() { # creating package local release_new=${CREATOR_TAG}${RELEASE} local opsi_file=${PN}_${VERSION}-${release_new}.opsi + pushd ${OUTPUT_DIR} rm -f ${opsi_file} ${OPSI_REPOS_FILE_PATTERN}.opsi LANG="C" opsi-makeproductfile -v $INST_DIR @@ -240,10 +222,9 @@ builder_package() { # create source package zip -r ${OUTPUT_DIR}/${OPSI_REPOS_FILE_PATTERN}.zip $INST_DIR - - } + ##################### # publish ##################### @@ -268,7 +249,7 @@ builder_publish() { builder_commit() { if [ -d "${PRODUCT_DIR}/.git" ]; then echo -n - # echo "builder_commit() not implemented yet." + log_debug "builder_commit() not implemented yet." fi } diff --git a/lib/builder-utils.sh b/lib/builder-utils.sh index b7d5477..996a6f7 100644 --- a/lib/builder-utils.sh +++ b/lib/builder-utils.sh @@ -4,13 +4,15 @@ # Description: retrieve file from an URL # # Parameter +# downloader: program to download the files # src: source url to get file from # dst: path to store file to # ############################################# function retrieve_file() { - local src=$1 - local dst=$2 + local downloader=$1 + local src=$2 + local dst=$3 # Check, if the URL is a file URL starting with file:// if [ -f $dst ] && [ -z ${DIST_FORCE_DOWNLOAD} ]; then @@ -20,30 +22,46 @@ function retrieve_file() { cp $fileurl $dst 2>/dev/null else rm -f $dst - wget --tries=1 -O $dst --timeout=5 -q --no-verbose $src + if [ "$downloader" = "wget" ]; then + wget --tries=1 -O $dst --timeout=5 -q --no-verbose "$src" + if [ "$?" == "1" ] ; then + rm $dst + fi + elif [ "$downloader" = "plowdown" ]; then + fatal_error "plowdown not implemented yet" + else + fatal_error "Downloader not implemented: $downloader" + fi fi } ############################################# -# void extract_file (src, dst) +# void extract_file (format, src, dst) # # Description: Extract a file # # Parameter +# format: compression format # src: source file to be used # dst: path to extract the file # ############################################# -function extract_file() { - local src=$1 - local dst=$2 +function process_file() { - if [ "${EXTRACTWITH}" = "7zip" ]; then + local format=$1 + local src=$2 + local dst=$3 + + log_debug "Compression format: $format" + + if [ "$format" = "cp" ]; then + cp $src $dst + elif [ "$format" = "7zip" ]; then 7z x -o$dst $src - elif [ "${EXTRACTWITH}" = "unzip" ]; then + elif [ "$format}" = "unzip" ]; then unzip $src -d $dst else - 7z x -o$dst $src + fatal_error "Unknown compression format: $format" fi } @@ -66,17 +84,26 @@ function call_entry_point() { } +################### +# Fata Error +################### +fatal_error() { + echo "FATAL: $1" + exit 0 +} ################### # Check error ################### builder_check_error() { - if [ $? == 1 ] ; then - echo "FATAL: $1" - exit 0 + if [ "$?" == "1" ] ; then + fatal_error "$1" fi } +################### +# Logging Debug +################### log_debug() { local str=$1 @@ -85,6 +112,17 @@ log_debug() { fi } +################### +# Logging Info +################### +log_info() { + local str=$1 + + if [ "$DEBUG_LEVEL" = "info" ] ; then + echo $str + fi +} + ################### # Convert image ################### @@ -119,7 +157,7 @@ convert_image() { else # Imagemagic is unable to detect the aspect ratio so just force 160x160 # this could result in streched images - log_debug "Icon Wight: $wight Hight: $hight" + log_debug "Icon Wight: $wight unknown Hight: $hight" convert $src -transparent white -background transparent -resize 160x160 \ xc:transparent +swap -gravity center -composite $dst builder_check_error "converting image" @@ -131,4 +169,58 @@ convert_image() { wight=`identify -format "%w" $dst` log_debug "Opsi Icon Wight: $wight Hight: $hight" -} \ No newline at end of file +} + + +################### +# Create variable file +# +# Create a file containing all important winst variables +# (declaration and setings) +# +# Parameter +# file: file to create +# +################### +create_winst_varfile() { + local var_file=$1 + + echo -n >$var_file + for (( i = 0 ; i < ${#DL_SOURCE[@]} ; i++ )) ; do + if [ -z ${DL_WINST_NAME[$i]} ] ; then continue ; fi + + if [ ! -z "${DL_ARCH[$i]}" ] ; then arch_str="${DL_ARCH[$i]}\\" ; fi + echo "DefVar \$${DL_WINST_NAME[$i]}\$" >>$var_file + echo "Set \$${DL_WINST_NAME[$i]}\$ = \"%ScriptPath%\\${arch_str}${DL_FILE[$i]}\"" >>$var_file + done + + # publish some other variables + for var in VENDOR PN VERSION RELEASE PRIORITY ADVICE TYPE CREATOR_TAG CREATOR_NAME CREATOR_EMAIL ; do + echo "DefVar \$${var}\$" >>$var_file + echo "Set \$${var}\$ = \"${!var}\"" >>$var_file + done + + # copy image and create variable + echo "DefVar \$IconFile\$" >>$var_file + echo "Set \$IconFile\$ = \"%ScriptPath%\\`basename $ICONFILE`\"" >>$var_file + + # publish custom variables + for (( i = 0 ; i < ${#WINST_NAME[@]} ; i++ )) ; do + + # replace DL_EXTRACT_WINST_PATH + local index=`echo ${WINST_VALUE[$i]} | sed -e "s#.*@DL_EXTRACT_WINST_PATH\[\([0-9]\)\]@.*#\1#"` + log_debug "calculated (DL_EXTRACT_WINST_PATH), Index: $index" + if [ "$index" != "${WINST_VALUE[$i]}" ] ; then + if [ ! -z "${DL_ARCH[$index]}" ] ; then arch_part="\\\\${DL_ARCH[$index]}" ; fi + if [ ! -z "${DL_EXTRACT_WINST_PATH[$index]}" ] ; then extr_part="\\\\${DL_EXTRACT_WINST_PATH[$index]}" ; fi + local new_val="%ScriptPath%$arch_part$extr_part" + WINST_VALUE[$i]=`echo ${WINST_VALUE[$i]} | sed -e "s#@DL_EXTRACT_WINST_PATH\[[0-9]\]@#$new_val#"` + log_debug "calculated (DL_EXTRACT_WINST_PATH) WINST_VALUE: ${WINST_VALUE[$i]}" + fi + + echo "DefVar \$${WINST_NAME[$i]}\$" >>$var_file + echo "Set \$${WINST_NAME[$i]}\$ = \"${WINST_VALUE[$i]}\"" >>$var_file + done + + echo >>$var_file +} diff --git a/sample/builder-product.cfg b/sample/builder-product.cfg index 5c632d2..89fc4a6 100644 --- a/sample/builder-product.cfg +++ b/sample/builder-product.cfg @@ -27,74 +27,104 @@ TYPE="public" ################# -# File object array +# Downloader (DL) object array ################ # # To build the opsi-packet, some files are needed. The files are defined by a file object. # A file object contains different attributes. All attributes (FILE, SOURCE, ..) are binded together -# using a file index. +# using a file index. +# +# Target "prepare" : Working directory INST_DIR and OUTPUT_DIR are prepared +# Target "retrieve" : the files are downloaded to the the caching storage ${DIST_CACHE_DIR}/$DL_ARCH[i]/$DL_FILE[i] +# Target "create" : the files are extrated/copied to ${INST_DIR}/CLIENT_DATA/${DL_ARCH[$i]} +# Target "package" : opsi-makeproductfile is called processing ${INST_DIR} directory # # - Filename # Filename used inside the builder and opsi package -# This parameter is mandatory. -# FILE[index]="cool-stuff.exe" +# Mandatory parameter. +# DL_FILE[index]="cool-stuff.exe" # # - Source URL -# The source URL to download the file from. Multiple URLs are separted by a ";" +# The source URL to download the file from. Multiple URLs are separted by a ";" or "," # The $DIST_PRIVATE_REPOS variable will be added as the first URL automatically # Therefore, you download the non-public programs to your local/privagte repository. # You can use variable like $PN or $Version inside the URLs -# This parameter is mandatory -# SOURCE[index]="http://cool-stuff.de/download/cool-stuff_1.001.exe;http://mirro5.cool-stuff.at/$PN_$VERSION.exe" +# DL_SOURCE[index]="http://cool-stuff.de/download/cool-stuff_1.001.exe;http://mirro5.cool-stuff.at/$PN_$VERSION.exe" # # - Architecture # Definition of the architecture to separate different files. This will be used in # the file structure inside the opsi-package. Also, you can use it in your repos-URL's # or filenames (OPSI_REPOS_FILE_PATTERN, OPSI_REPOS_PRODUCT_DIR) to structure the repos. # If it's a file for all architecture, the variable have not to be set. -# This parameter is optional, default value: , +# Optional parameter. Default value: # Valid values: , "X86", "X86_64" -# ARCH[index]="X86" +# DL_ARCH[index]="X86" # -# - WINST Variabels: +# - WINST variable: # You can access the file (included in the opsi-package) using WINST script language. # The target "package" will replace all occurence of the string "@@BUILDER_VARIABLES@@" # by pairs of "DefVar/Set"-commands, if the WINST attribute is set. Default value: -# This parameter is ptional, default value: , -# WINST[index]=itWESS +# Optional parameter. Default value: , +# DL_WINST_NAME[index]=itWESS # -################# -# Optional Array Elements -################ +# - Compression format +# If the retrieved file is compressed, the compression format is specified to +# extract it. If the parameter is not set, no extraction happens +# Optional parameter. Valid values: unzip, 7zip. Default value: . +# DL_EXTRACT_FORMAT="zip" # -# - INSTALL Variabels: -# If you specify the INSTALL Array Element Builder expects that the specified FILE is a -# compressed archive and extract it. -# INSTALL[index]="libreoffice34.msi" -# -# - EXTRACTTO Variabels: +# - Extraction directory for compressed files # This Variable only works in combination with INSTALL and forces the extraction # to be done into the specified directory. -# This will result in the files to be extracted to ARCH/EXTRACTTO. +# This will result in the files to be extracted to ${OUTPUT_DIR}/${DL_ARCH}/${DL_EXTRACT_TO}. # This feature is mostly needed if a package includes more setup programms that are nemed the # same. This way you place the setups into diffent dirs -# EXTRACTTO[index]="office" +# Optional parameter. Default value: +# DL_EXTRACT_TO[index]="office" # - -FILE[0]="itWatchLogo.jpg" -SOURCE[0]="http://www.itwatch.de/logos/itWatchLogo.jpg" -WINST[0]=IconFile +# - Specify Downloader +# Defines the downloader to use to retrieve the SOURCE file +# Optional parameter. Valid values: wget|plowdown. Default value: wget +# + +DL_FILE[0]="itWatchLogo.jpg" +DL_SOURCE[0]="http://www.itwatch.de/logos/itWatchLogo.jpg" -FILE[1]="itWESS-Client_German.msi" -SOURCE[1]="http://repos.dtnet.de/v-$PN/itwatch/itwatch/4.10.19/itWESS-Client_German.msi;http://internal.graz.disconnected-by-peer.at/Orig/itWatch/itWESS/HB/4.10.19/itWESS-Client_German.msi" -ARCH[1]="X86" -WINST[1]=itWESS +DL_FILE[1]="itWESS-Client_German.msi" +DL_SOURCE[1]="http://repos.dtnet.de/itwatch/itwatch/4.10.19/itWESS-Client_German.msi;http://internal.graz.disconnected-by-peer.at/Orig/itWatch/itWESS/HB/4.10.19/itWESS-Client_German.msi" +DL_ARCH[1]="X86" +DL_WINST_NAME[1]=itWESS -FILE[2]="itWESS-64bit_German.msi" -SOURCE[2]="http://repos.dtnet.de/itwatch/itwatch/4.10.19/itWESS-64bit_German.msi;http://internal.graz.disconnected-by-peer.at/Orig/itWatch/itWESS/HB/4.10.19/itWESS-64bit_German.msi" -ARCH[2]="X86_64" -WINST[2]=itWESS64 +DL_FILE[2]="itWESS-64bit_German.msi" +DL_SOURCE[2]="http://repos.dtnet.de/itwatch/itwatch/4.10.19/itWESS-64bit_German.msi;http://internal.graz.disconnected-by-peer.at/Orig/itWatch/itWESS/HB/4.10.19/itWESS-64bit_German.msi" +DL_ARCH[2]="X86_64" +DL_WINST_NAME[2]=itWESS64 + +DL_FILE[3]="AiO-Runtimes-x86-v1.7.1.7z" +DL_SOURCE[3]="http://ftp.computerbase.de/dl-758/weJMhoTGCTbFI5mzRnMlAg/1327825564/AiO-Runtimes-x86-v1.7.1.7z" +DL_ARCH[3]="X86" +DL_DOWNLOADER="wget" +DL_EXTRACT_FORMAT[3]="unzip" +DL_EXTACT_TO[3]="office" # File array index for the image showing while installing the program -ICON_FILE_INDEX=0 +ICON_DL_INDEX=0 + +######################### +# Setup additional, custom WINST variables +# which will be injected to the *.ins files +# +# The following tokens inside the WINST_VALUE will be replaced dynamically +# +# @DL_EXTRACT_WINST_PATH[]@ : contains the WINST location of the directory, the files from DL_FILE[] was extracted to. +# Sample: +# WINST_VALUE[1]="@DL_EXTRACT_WINST_PATH[]@\\svcpack\\aio-runtimes.exe" +# results in "%ScriptPath%\X86_64\svcpack\aio-runtimes.exe" +# +######################### +WINST_NAME[0]="InstallExe" +WINST_VALUE[0]="@DL_EXTRACT_WINST_PATH[2]@\\svcpack\\aio-runtimes.exe" + +WINST_NAME[1]="MyVar" +WINST_VALUE[1]="My content"