opsi-info

opsi-info.sh

shell script to change version information of available opsi packages

Features:

- Display Version and package-version of any opsi product

- Edit Version and package-version of any opsi product

- Change Product version if defined in setup script (setup.ins)

updates this File String in setup.ins:

Set $ProductVersion$  = "24.1.1"

replacing the version number can be useful if you use the version as parameter in your setup script, for example

"%ScriptPath%\files\Firefox Setup $ProductVersion$esr.exe" -ms -ira

This means, updating Firefox would just require you to place the new setup exe file inside “%ScriptPath%\files\” then setting the the new version with opsi-info.sh

- optionally set “setup” action for the updated product on all clients with the product already installed

Download Link here: http://islamadel.com/en/downloads?func=fileinfo&id=12

############################

opsi-info : view / edit opsi package information

usage:

opsi-info [arguments]

arguments:

-h : display help

-prod [product-id] : view / edit info for product-id

-ver [decimal] : set decimal value for product version

-pver [integer] : set value for package version

example:

opsi-info.sh -prod internet_firefox -ver 25.0.1

sets new version “25.0.1” for product-id “internet_firefox”

############################

opsi-info.sh

#!/bin/bash
 
###############
# opsi-info
# read / edit opsi-package info
# By Islam Adel
 
###############
 
#usage: opsi-info -h (help file)
 
###############
#change log:
# 2013-09-02	view, edit product version, depot file autodetection
# 2013-09-03	view, edit package version, backup all edited files
# 2013-12-10	added option to update clients with product already installed, set correct file rights for edited files
 
# target:	- prompt for software setup on all clients with status "installed"
 
# General-Info to find installed product on client:
 
# installed info:
# in /home/opsiproducts/client-name.ini
#	internet_firefox = installed:none
# function:
# Find string "internet_firefox = installed:none" all "*.ini" Files in "/home/opsiproducts/" (replace internet_firefox by product name)
#
# Set for setup
# change from "internet_firefox = installed:none"
# to: "internet_firefox = installed:setup"
 
#
#target:	- read/edit opsi package information
#			- list all package-ids
#			- error verification / reporting
#			- read / edit package version
#			- backup all relevant files
#			- fix conflict if product version = package version
 
#to-do: auto detect depot files
 
#input: arguments 1. option, 2. product_id, 3. value
 
# option: -ver (product version)
 
 
######################
# global variables
ver="13.12.10"
#set loop delimiter as "newline"
IFS=$'\n'
 
#current_date_time
NOW="$(date '+%Y-%m-%d_%H-%M-%S')"
 
######################
# user variables
# opsi="local" #for local test
# opsi="remote" #for remote usage on server
opsi="remote"
 
######################
#functions
 
#error message
error() {
	echo "ERROR: $@"
	echo
#	echo "use -h argument for help"
#	echo
	#exit
}
 
#display hel
f_printUsage() {
	echo "opsi-info : view / edit opsi package information"
	echo
	echo "usage:"
	echo
	echo "opsi-info [arguments]"
	echo
	echo "arguments:"
	echo
	echo "-h			:	display help"
	echo "-prod [product-id]	:	view / edit info for product-id"
	#echo "-ver | --version	:	view current product version"
	echo "-ver [decimal]		:	set decimal value for product version"
	#echo "-pver | --pkgversion	:	view current package version"
	echo "-pver [integer]		:	set value for package version"
	echo
	echo
	echo "example: opsi-info.sh -prod internet_firefox -ver 25.0.1"
	echo "		sets new version \"25.0.1\" for product-id \"internet_firefox\"" 
	echo
	exit
}
 
# read all passed arguments
f_GetArgs() {
 
#echo "all args=[${@}]"
#echo "number of args=[${#}]"
#echo "1=${1}"
#echo "2=${2}"
#echo "3=${3}"
#echo "4=${4}"
 
i=0
argv=()
for arg in "$@"; do
    argv[$i]="$arg"
    i=$((i + 1))
    #debug# echo $i=$arg
done
 
# Handle OPTIONS and build directory array
 
#n_threads=1
#check_env=1
#run_jobs=0
#set_version="3c4n.15"
#is_2010=""
 
i=0
dir_index=0
while test $i -lt $# ; do
 
    arg="${argv[$i]}"
 
    case "$arg" in
 
        #--2010)    is_2010="--2010";;
 
        -h|--help)  f_printUsage;;
 
        #-j|--jobs) i=$((i + 1)); n_threads=${argv[$i]};;
 
        #-rj|--run-jobs) run_jobs=1;;
 
        #--no-env-check) check_env=0;;
		#verify decimal value before setting
        --version|-ver) i=$((i + 1)); if [ "$(echo "${argv[$i]}" | tr -d ".")" -eq "$(echo "${argv[$i]}" | tr -d ".")" ] > /dev/null 2>&1; then new_version="${argv[$i]}"; else error "value for -ver must be decimal"; fi;;
        #verify integer value before setting
        --pkgversion|-pver) i=$((i + 1)); if [ "$(echo "${argv[$i]}")" -eq "$(echo "${argv[$i]}")" ] > /dev/null 2>&1; then new_pkg_version="${argv[$i]}"; else error "value for -pver must be an integer";fi;;
 
        --product|-prod) i=$((i + 1)); product="${argv[$i]}";;
 
        *) if ! test -d "$arg" ; then
            error "Unknown argument or directory '$arg'"; exit
        else
            source_dirs[$dir_index]="$arg"
            dir_index=$((dir_index + 1))
        fi;;
 
    esac
 
    i=$((i + 1))
 
done
 
}
 
# input file
f_Depot() {
#autodetect depot file
if [ "$opsi" == "remote" ]; then depot_dir="/var/lib/opsi/config/depots/"; fi
#local_test
if [ "$opsi" == "local" ]; then depot_dir="/Users/islam/Documents/rechnerpool/opsi/updater/opsi-server/config/depots/"; fi
 
dep=0
for d in $(ls "$depot_dir"*.ini 2>/dev/null | xargs -n1 basename); do
	# add depot number
	dep=$((dep + 1))
	dep_[$i]="$d"
	#echo "$d"
	#prompt to choose depot number if multiple found
	depot_name="$d"
	depot="$depot_dir""$d"
	#echo $depot_name
	#echo $depot
	if [ "$dep" -gt "1" ]; then
		echo "[ $dep ] depots have been found"
		echo "using: $depot"
			#add this feature later, to choose depot number
	fi	
done
 
if [ ! "$depot" ]; then error "No Depot has been found in: $depot_dir"; exit ; fi
 
depot_bak_dir="$depot_dir""archiv/"
depot_bak_file="$depot_bak_dir""$depot_name""_$NOW.bak"
#create backup folder if not exist
if [ ! -d "$depot_bak_dir" ]; then mkdir -p "$depot_bak_dir"; fi
 
#tmp files
depot_tmp1="$depot.1.tmp"
# remove existing tmp file
if [ -f $depot_tmp1 ]; then rm -f $depot_tmp1; fi
depot_tmp2="$depot.2.tmp"
if [ -f $depot_tmp2 ]; then rm -f $depot_tmp2; fi
}
 
#find clients with installed product and set for setup
f_UpdateClients() {
	# Find string "internet_firefox = installed:none" all "*.ini" Files in "/home/opsiproducts/" (replace internet_firefox by product name)
 
	# first find clients, display names and prompt
	# use: grep -l "internet_firefox = installed:none" /var/lib/opsi/config/clients/*.ini
 
	echo
	echo "Searching for clients with [ ${product} ] status: installed .."
	echo
 
	# Set number of clients found with product already installed
	updclient=0
	#Path of clients Folder
	clientspath="/var/lib/opsi/config/clients/"
	#backup path for clients
	client_bak_dir="/var/lib/opsi/config/clients/archiv/"
	#create backup folder if not exist
	if [ ! -d "$client_bak_dir" ]; then mkdir -p "$client_bak_dir"; fi
 
	# find all clients with product already installed and not set to setup
	for c in $(grep -l "${product} = installed:none" "${clientspath}"*.ini 2>/dev/null); do
		# print client names with product already installed, trim .ini extension
		# print client name only - trim .ini extension, trim dir path
		#echo ${c%.ini}
		echo "$(echo ${c%.ini} | xargs -n1 basename)"
		# Add number of clients and check later if results >0
		updclient=$((updclient + 1))
	done
 
	#If results found, begin interaction
	if [ "${updclient}" == "0" ]; then
		# message if search results is 0 
		echo
		echo "[ ${product} ] is not installed on any client."
		echo
	else
		echo
		echo "[ ${updclient} ] clients found."
		echo
		# Now ask if setup action should be set.
 
		###
		read -n1 -p  " Set SETUP action for [ ${product} ] on listed clients ? : [ y=Yes | n=No ]: [Default: y ] "
		case "${REPLY}" in
			# use last path accepted
			"" | "y" | "Y" | "yes" | "Yes")	
			# yes I want to set product for setup on clients
			#echo
			echo "Setting SETUP action.."
			echo
			for c in $(grep -l "${product} = installed:none" "${clientspath}"*.ini 2>/dev/null); do
				# print client names with product already installed, trim .ini extension
				#echo ${c%.ini}
				# Add number of clients and check later if results >0
				#updclient=$((updclient + 1))
 
				# backup client files first
				#cp -f "${c}" "${c}_$NOW.bak"
				# backup original file to backup dir, trimming source file name only adding date.bak as suffix
				cp -f "${c}" "${client_bak_dir}$(echo ${c} | xargs -n1 basename)_$NOW.bak"
				# begin replacing string into tmp file
				cat "${c}" | sed 's/'${product}' = installed:none/'${product}' = installed:setup/g' >"${c}".tmp
				# replace tmp file with original file
				mv -f "${c}".tmp "${c}"
				# set file rights
				chown opsiconfd:opsifileadmins "${c}"
				chmod 660 "${c}"
 
				#verify edit	
				if grep -q "${product} = installed:setup" "${c}"
				then
  					# code if found
  					echo "OK: SETUP action set for: $(echo ${c} | xargs -n1 basename)"
				else
  					# code if not found
  					error "SETUP action NOT set for: $(echo ${c} | xargs -n1 basename)"
				fi
			done
			;;
			# skip file, any other entry
			*)
			# Any other answer is now
			# No changes
			echo "No clients have been modified."
			echo
			;;
		esac
 
	fi
 
}
 
#version info in install script
f_Install() {
	if [ "$opsi" == "remote" ]; then inst_dir="/opt/pcbin/install/""$product"/; fi
	#local_test
	if [ "$opsi" == "local" ]; then inst_dir="/Users/islam/Documents/rechnerpool/opsi/updater/opsi-server/install/""$product"/; fi
	setup_file="setup.ins"
 
	setup_bak_dir="$inst_dir""archiv/"
	setup_bak_file="$setup_bak_dir""$setup_file""_$NOW.bak"
	#create backup folder if not exist
 
	if [ ! -d "$setup_bak_dir" ]; then mkdir -p "$setup_bak_dir"; fi
 
	#Set $ProductVersion$  = "17.0.7"
	if [ -f "$inst_dir""$setup_file" ]; then
		#echo "setup.ins found"
		#change version info in setup-script
		#echo "-----------" $old_version
		#cat "$inst_dir""$setup_file" | grep "Set \$ProductVersion\$  = \"$old_version"
		#echo "-----------"
		#backup
		cp -f "$inst_dir""$setup_file" "$setup_bak_file"
		cat "$inst_dir""$setup_file" | sed 's/Set \$ProductVersion\$  = "'$old_version'"/Set \$ProductVersion\$  = "'$new_version'"/g' >"$inst_dir""$setup_file".tmp
		mv -f "$inst_dir""$setup_file".tmp "$inst_dir""$setup_file"
		# set file rights
		chown opsiconfd:opsifileadmins "$inst_dir""$setup_file"
		chmod 660 "$inst_dir""$setup_file"
 
		#verify edit	
		if grep -q "Set \$ProductVersion\$  = \"$new_version\"" "$inst_dir""$setup_file"
		then
  			# code if found
  			echo "OK: ProductVersion replaced in $setup_file"
		else
  			# code if not found
  			error "ProductVersion NOT replaced in $setup_file"
		fi
 
 
	fi
 
 
}
 
# products info
f_Product() {
 
	if [ "$opsi" == "remote" ]; then product_dir="/var/lib/opsi/config/products/"; fi
	#local test
	if [ "$opsi" == "local" ]; then product_dir="/Users/islam/Documents/rechnerpool/opsi/updater/opsi-server/config/products/"; fi
 
	#echo "$new_version"
	#echo "$product"
	#read pkg_ver
	#set old packageversion if new is not defined
	if [ ! "$new_pkg_version" ]; then new_pkg_version="$old_pkg_version"; fi
	#set old product version if new is not defined
	if [ ! "$new_version" ]; then new_version="$old_version"; fi
 
	#prod_pkg_ver="$old_pkg_version"
	#identify type .localboot or .netboot #later feature
	product_file_old="$product"_"$old_version"-"$old_pkg_version".localboot
	product_file_new="$product"_"$new_version"-"$new_pkg_version".localboot
#	echo
#	echo old_version="$old_version"
#	echo new_version="$new_version"
#	echo old_pkg_version="$old_pkg_version"
#	echo new_pkg_version="$new_pkg_version"
 
	product_bak_dir="$product_dir""archiv/"
	product_bak_file="$product_bak_dir""$product_file_old""_$NOW.bak"
	#create backup folder if not exist
	if [ ! -d $product_bak_dir ]; then mkdir -p $product_bak_dir; fi
 
 
	#check if product file exists
	if [ -f "$product_dir""$product_file_old" ]; then
		#### rename product file
		#backup file? #later
		cp -f "$product_dir""$product_file_old" "$product_bak_file"
 
		mv -f "$product_dir""$product_file_old" "$product_dir""$product_file_new"
		#check if renamed file exists? #later_feature
 
		#### change file version in content
		case "$change" in
			1)	# change product version
				cat "$product_dir""$product_file_new" | sed 's/version: '$old_version'/version: '$new_version'/g' >"$product_dir""$product_file_new".tmp
				mv -f "$product_dir""$product_file_new".tmp "$product_dir""$product_file_new"
				# verify change, #later
				# cat "$product_dir""$product_file_new" | grep version: '$new_version'
				# set file rights
				chown opsiconfd:opsifileadmins "$product_dir""$product_file_new"
				chmod 660 "$product_dir""$product_file_new"
 
				#### change file version in setup script
				f_Install
				### update installed clients
				f_UpdateClients
			;;
			3)	# change package version / sed ====> first match for version: only / first occurence
				cat "$product_dir""$product_file_new" | awk '/version: '$old_pkg_version'/{if (M==""){sub("version: '$old_pkg_version'","version: '$new_pkg_version'");M=1}}{print}' >"$product_dir""$product_file_new".tmp		
				# all occurences
				#cat "$product_dir""$product_file_new" | sed 's/version: '$old_pkg_version'/version: '$new_pkg_version'/g' > "$product_dir""$product_file_new".tmp
				mv -f "$product_dir""$product_file_new".tmp "$product_dir""$product_file_new"
				# set file rights
				chown opsiconfd:opsifileadmins "$product_dir""$product_file_new"
				chmod 660 "$product_dir""$product_file_new"
			;;
			4) #change prod. version first, then pkg version
				cat "$product_dir""$product_file_new" | sed 's/version: '$old_version'/version: '$new_version'/g' >"$product_dir""$product_file_new".tmp
				cat "$product_dir""$product_file_new".tmp | awk '/version: '$old_pkg_version'/{if (M==""){sub("version: '$old_pkg_version'","version: '$new_pkg_version'");M=1}}{print}' >"$product_dir""$product_file_new"
				#mv -f "$product_dir""$product_file_new".tmp2 "$product_dir""$product_file_new"
				# set file rights
				chown opsiconfd:opsifileadmins "$product_dir""$product_file_new"
				chmod 660 "$product_dir""$product_file_new"
				#### change file version in setup script
				f_Install
				### update installed clients
				f_UpdateClients
			;;
		esac
 
		if [ -f "$product_dir""$product_file_new".tmp ]; then rm -f "$product_dir""$product_file_new".tmp; fi
 
	else
		error "Product file: [ $product_file_old ] not found in: [ $product_dir ]"
		#restore backed up file
		mv -f $depot_bak_file $depot
		# set file rights
		chown opsiconfd:opsifileadmins $depot
		chmod 660 $depot
	fi
}
 
 
######################
#script start
echo
echo "#################################"
echo "#				#"
echo "# opsi-info version: $ver	#"
echo "#				#"
echo "#	use -h for help		#"
echo "#				#"
echo "#################################"
echo
 
# read arguments
f_GetArgs $@
 
f_Depot
#display values
#echo "using depot file :"
#echo "	$depot"
#echo ver = $new_version
#echo product = $product
 
#read depot file
 
# sed '/^start_string/s/search_string/replace_string/'
# replace line starting with "[" by "@"
# replace new lines by ";"
# replace "@" by "new line"
# replace ";;" by ";"
# replace ";" by "newline"
#cat $depot | sed '/^\[/s/\[/@\[/' | tr '\n' ';' | tr '@' '\n' | sed 's/;;/;/g' | tr ';' '\n'
 
#create tmp file and change structure for search
cat $depot | sed '/^\[/s/\[/@\[/' | tr '\n' ';' | tr '@' '\n' > $depot_tmp1
 
# find line with product name and replace string (version value) till ";"
found=0
change=0
for v in $(cat $depot_tmp1 | grep "\[$product-state\]"); do
	found=$((found + 1))
	if [ "$found" == "1" ]; then
		# must find 1 instance only - replace only one product
		# read current version
		#last working: old_version=$(echo $v | sed 's/\[.*productversion.*= //g' | tr -d ";")
		old_version=$(echo "$v" | sed -e 's/^.*productversion = \([.[:digit:]]*\);.*$/\1/g')
		old_pkg_version=$(echo "$v" | sed -e 's/^.*packageversion = \([.[:digit:]]*\);.*$/\1/g')
 
#		echo old_version="$old_version"
#		echo new_version="$new_version"
#		echo old_pkg_version="$old_pkg_version"
#		echo new_pkg_version="$new_pkg_version"
#		echo v="$v"
 
		#edit only if new_version is defined
		if [ "$new_version" ]; then
			change=$((change + 1))
			# replace old version with new, retain whole string
			n=$(echo "$v" | sed -e 's/productversion = '$old_version';/\productversion = '$new_version';;/g')
			#echo n="$n"
			#exit
			echo "replacing product version for:	[ $product ], from: [ $old_version ] to: [ $new_version ]"
		else
			echo "current product version for:	[ $product ], is: [ $old_version ]"
		fi
 
		#edit only if new_pkg_version is defined
		if [ "$new_pkg_version" ]; then
			change=$((change + 3))
			# replace old version with new, retain whole string
			p=$(echo "$v" | sed -e 's/packageversion = '$old_pkg_version';/\packageversion = '$new_pkg_version';;/g')
			echo "replacing package version for:	[ $product ], from: [ $old_pkg_version ] to: [ $new_pkg_version ]"
		else
			echo "current package version for:	[ $product ], is: [ $old_pkg_version ]"
		fi
	else
		error "[ $found ] matches found for: $product "
	fi
done
 
#case for changes
case "$change" in
#	0)	echo "# nothing to change";;
	1)	#echo "# change version only"
		# backup original depot file
		cp -f $depot $depot_bak_file
		# replace version info and retain original file structure
		sed 's/\'$v'/\'$n'/g' $depot_tmp1 | sed 's/;;/;/g' | tr ';' '\n' >$depot
		# set file rights
		chown opsiconfd:opsifileadmins $depot
		chmod 660 $depot
		f_Product
	;;
	3)	#echo "# change pkg version only"
		# backup original depot file
		cp -f $depot $depot_bak_file
		sed 's/\'$v'/\'$p'/g' $depot_tmp1 | sed 's/;;/;/g' | tr ';' '\n' >$depot
		# set file rights
		chown opsiconfd:opsifileadmins $depot
		chmod 660 $depot
		# change further files
		f_Product
	;;
	4)	#echo "# change pver + ver"	
		p=$(echo "$n" | sed -e 's/packageversion = '$old_pkg_version';/\packageversion = '$new_pkg_version';;/g')
		# backup original depot file		
		cp -f $depot $depot_bak_file
		# replace version info and retain original file structure
		sed 's/\'$v'/\'$p'/g' $depot_tmp1 | sed 's/;;/;/g' | tr ';' '\n' >$depot
		# set file rights
		chown opsiconfd:opsifileadmins $depot
		chmod 660 $depot
		# change further files
		f_Product
	;;
esac
 
# errors only if product / arguments specified
#echo $i
if [ "$i" -gt "0" ]; then
	if [ "$found" == "0" ]; then error "no matching product found"; fi
else
	error "no arguments specified"
	echo "use -h argument for help"
fi
 
# file end
echo
echo "###############################"
echo
echo "process done."
# remove existing tmp file
if [ -f $depot_tmp1 ]; then rm -f $depot_tmp1; fi
if [ -f $depot_tmp2 ]; then rm -f $depot_tmp2; fi
echo
#read -p ""
#exit