| #!/bin/sh |
| # Copyright (C) 2000-2015, Parallels, Inc. All rights reserved. |
| # |
| # This program is free software; you can redistribute it and/or modify |
| # it under the terms of the GNU General Public License as published by |
| # the Free Software Foundation; either version 2 of the License, or |
| # (at your option) any later version. |
| # |
| # This program is distributed in the hope that it will be useful, |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| # GNU General Public License for more details. |
| # |
| # You should have received a copy of the GNU General Public License |
| # along with this program; if not, write to the Free Software |
| # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| # |
| # |
| |
| # Set the sane umask |
| umask 022 |
| CP='/bin/cp -fp' |
| # overwrite copy arguments as a workaround for FC5 bug #190601 (ovz bug #297) |
| [ -f /etc/fedora-release ] && CP='/bin/cp -f --preserve=mode,ownership' |
| |
| # Error codes |
| VZ_INVALID_PARAMETER_SYNTAX=20 |
| VZ_FS_NO_DISK_SPACE=46 |
| VZ_FS_BAD_TMPL=47 |
| VZ_FS_NEW_VE_PRVT=48 |
| VZ_CHANGEPASS=74 |
| VZ_CANT_ADDIP=34 |
| VZ_IP_INUSE=78 |
| |
| FAKEGATEWAY=192.0.2.1 |
| FAKEGATEWAYNET=192.0.2.0 |
| |
| # Prints error message and exits |
| # Parameters: |
| # $1 - error message |
| # $2 - exit code |
| # Example of usage: |
| # error "Fatal error" 1 |
| error() |
| { |
| # print errors to stdout too |
| ERR=$? |
| printf '%s ERROR: %s\n' "$SELFNAME" "$1" |
| exit $2 |
| } |
| |
| # Puts line |
| # NAME="value" |
| # to config file. If NAME is found, line gets replaced, |
| # otherwise it is added to the end of file. |
| # Parameters: |
| # $1 - config file |
| # $2 - NAME |
| # $3 - value |
| put_param() |
| { |
| local file="$1" |
| local name="$2" |
| local value="$3" |
| local path |
| |
| path=${file%/*} |
| if [ ! -d "${path}" ]; then |
| mkdir -p ${path} || error "Unable to create dir ${path}" $VZ_FS_NO_DISK_SPACE |
| fi |
| if grep -E "^$name=.*" $file>/dev/null 2>&1; then |
| ${CP} ${file} ${file}.$$ || error "Can't copy file $file" $VZ_FS_NO_DISK_SPACE |
| if ! sed "s|^$name=.*|$name=\"$value\"|" < ${file} > ${file}.$$; then |
| rm -f ${file}.$$ 2>/dev/null |
| error "Can't change file $file" $VZ_FS_NO_DISK_SPACE |
| fi |
| mv -f ${file}.$$ ${file} |
| elif ! printf '%s="%s"\n' "$name" "$value" >> $file; then |
| error "Can't change file $file" $VZ_FS_NO_DISK_SPACE |
| fi |
| } |
| |
| # Adds value to variable NAME |
| # in config file. If NAME is found, value gets added, |
| # otherwise it is added to the end of file. |
| # Parameters: |
| # $1 - config file |
| # $2 - NAME |
| # $3 - value |
| add_param() |
| { |
| local file="$1" |
| local name="$2" |
| local value="$3" |
| local path |
| |
| path=${file%/*} |
| if [ ! -d "${path}" ]; then |
| mkdir -p ${path} || error "Unable to create dir ${path}" $VZ_FS_NO_DISK_SPACE |
| fi |
| if grep -q "^$name=" $file > /dev/null 2>&1; then |
| ${CP} ${file} ${file}.$$ || |
| error "Can't copy file $file" $VZ_FS_NO_DISK_SPACE |
| if ! sed -E "s|^$name=\"(.*)\"|$name=\"\\1 $value \"|" < ${file} > ${file}.$$; then |
| rm -f ${file}.$$ 2>/dev/null |
| error "Can't change file $file" $VZ_FS_NO_DISK_SPACE |
| fi |
| mv -f ${file}.$$ ${file} |
| elif ! printf '%s="%s"\n' "$name" "$value" >> $file; then |
| error "Can't change file $file" $VZ_FS_NO_DISK_SPACE |
| fi |
| } |
| |
| del_param() |
| { |
| local file="$1" |
| local name="$2" |
| local value="$3" |
| local path |
| |
| path=${file%/*} |
| if [ ! -d "${path}" ]; then |
| mkdir -p ${path} || error "Unable to create dir ${path}" $VZ_FS_NO_DISK_SPACE |
| fi |
| if grep -q "^$name=" $file >/dev/null 2>&1; then |
| ${CP} ${file} ${file}.$$ || |
| error "Can't copy file $file" $VZ_FS_NO_DISK_SPACE |
| if |
| ! if [ -z "${value}" ]; then |
| sed "/^${name}=.*/d" |
| else |
| sed -E "s|^${name}=(.*)${value}(.*)|${name}=\\1\\2|" |
| fi < ${file} > ${file}.$$ |
| then |
| rm -f ${file}.$$ 2>/dev/null |
| error "Can't change file $file" $VZ_FS_NO_DISK_SPACE |
| fi |
| mv -f ${file}.$$ ${file} |
| fi |
| } |
| |
| # Puts line |
| # NAME value |
| # to config file. If NAME is found, line gets replaced, |
| # otherwise it is added to the end of file. |
| # Parameters: |
| # $1 - config file |
| # $2 - NAME |
| # $3 - value |
| put_param2() |
| { |
| local file="$1" |
| local name="$2" |
| local value="$3" |
| local path |
| |
| path=${file%/*} |
| if [ ! -d "${path}" ]; then |
| mkdir -p ${path} || error "Unable to create dir ${path}" $VZ_FS_NO_DISK_SPACE |
| fi |
| if grep -E "^<$name>" $file > /dev/null 2>&1; then |
| ${CP} ${file} ${file}.$$ || error "Can't copy file $file" $VZ_FS_NO_DISK_SPACE |
| if ! sed "s|^<$name>.*|$name $value|" < ${file} > ${file}.$$; then |
| rm -f ${file}.$$ 2>/dev/null |
| error "Can't change file $file" $VZ_FS_NO_DISK_SPACE |
| fi |
| mv -f ${file}.$$ ${file} |
| elif printf '%s %s\n' "$name" "$value" >> $file; then |
| error "Can't change file $file" $VZ_FS_NO_DISK_SPACE |
| fi |
| } |
| |
| # Puts line |
| # NAME=( value ) |
| # to config file. If NAME is found, line gets replaced, |
| # otherwise it is added to the end of file. |
| # Parameters: |
| # $1 - config file |
| # $2 - NAME |
| # $3 - value |
| put_param3() { |
| local file="$1" |
| local name="$2" |
| local value="$3" |
| local path |
| |
| path=${file%/*} |
| if [ ! -d "${path}" ]; then |
| mkdir -p ${path} || error "Unable to create dir ${path}" $VZ_FS_NO_DISK_SPACE |
| fi |
| if grep -E "^$name=\\(.*\\)" $file > /dev/null 2>&1; then |
| ${CP} ${file} ${file}.$$ || error "Can't copy file $file" $VZ_FS_NO_DISK_SPACE |
| if |
| ! if [ -z "${value}" ]; then |
| sed -E "s|^$name=\\(.*\\)|$name=\\( \\)|" |
| else |
| sed -E "s|^$name=\\(.*\\)|$name=\\( \"$value\" \\)|" |
| fi < ${file} > ${file}.$$ |
| then |
| rm -f ${file}.$$ 2>/dev/null |
| error "Can't change file $file" $VZ_FS_NO_DISK_SPACE |
| fi |
| mv -f ${file}.$$ ${file} |
| elif |
| ! if [ -z "${value}" ]; then |
| printf '%s=( )\n' "$name" |
| else |
| printf '%s=( "%s" )\n' "$name" "$value" |
| fi >> $file |
| then |
| error "Can't change file $file" $VZ_FS_NO_DISK_SPACE |
| fi |
| } |
| |
| # Adds value to array NAME |
| # in config file. If NAME is found, value gets added, |
| # otherwise it is added to the end of file. |
| # Parameters: |
| # $1 - config file |
| # $2 - NAME |
| # $3 - value |
| add_param3() { |
| local file="$1" |
| local name="$2" |
| local value="$3" |
| local path |
| |
| path=${file%/*} |
| if [ ! -d "${path}" ]; then |
| mkdir -p ${path} || error "Unable to create dir ${path}" $VZ_FS_NO_DISK_SPACE |
| fi |
| if grep -E "^$name=\\(.*\\)" $file > /dev/null 2>&1; then |
| ${CP} ${file} ${file}.$$ || error "Can't copy file $file" $VZ_FS_NO_DISK_SPACE |
| if ! sed -r "s|^$name=\\((.*)\\)|$name=\\( \\1 \"$value\" \\)|" < ${file} > ${file}.$$; then |
| rm -f ${file}.$$ 2>/dev/null |
| error "Can't change file $file" $VZ_FS_NO_DISK_SPACE |
| fi |
| mv -f ${file}.$$ ${file} |
| elif ! printf '%s=( "%s" )\n' "$name" "$value" >> $file; then |
| error "Can't change file $file" $VZ_FS_NO_DISK_SPACE |
| fi |
| } |
| |
| # Removes value from array NAME |
| # in config file. If NAME is found, value gets removed, |
| # otherwise this is a noop function. |
| # Parameters: |
| # $1 - config file |
| # $2 - NAME |
| # $3 - value |
| del_param3() { |
| local file="$1" |
| local name="$2" |
| local value="$3" |
| |
| [ ! -f $file ] && return 0 |
| |
| if grep -E "^$name=\\(.*\\)" $file > /dev/null 2>&1; then |
| ${CP} ${file} ${file}.$$ || error "Can't copy file $file" $VZ_FS_NO_DISK_SPACE |
| if ! sed -r "s|^($name=\\( .*)\"$value\"(.* \\))|\\1\\2|" < ${file} > ${file}.$$; then |
| rm -f ${file}.$$ 2>/dev/null |
| error "Can't change file $file" $VZ_FS_NO_DISK_SPACE |
| fi |
| mv -f ${file}.$$ ${file} |
| else |
| return 0 |
| fi |
| } |
| |
| remove_debian_interface() |
| { |
| local dev="$1" |
| local cfg="$2" |
| |
| ${CP} ${cfg} ${cfg}.$$ || |
| error "Can't copy file ${cfg}" $VZ_FS_NO_DISK_SPACE |
| |
| awk ' |
| NF == 0 {next} |
| $1 == "auto" && $2 ~/'${dev}'$/ {next} |
| $1 == "iface" && $2 ~/'${dev}'$/ {skip = 1; next} |
| /^\t/ && skip {next} |
| {skip = 0; print} |
| ' < ${cfg} > ${cfg}.$$ && mv -f ${cfg}.$$ ${cfg} |
| |
| rm -f ${cfg}.$$ 2>/dev/null |
| } |
| |
| change_hostname() |
| { |
| local cfg="$1" |
| local host="$2" |
| local address="$3" |
| local comm='# Auto-generated hostname. Please do not remove this comment.' |
| |
| [ -f "${cfg}" ] || touch ${cfg} |
| if [ "${host}" = "localhost" -o "${host}" = "localhost.localdomain" ]; |
| then |
| put_param2 ${cfg} "127.0.0.1" "localhost.localdomain localhost" |
| return 0 |
| fi |
| ${CP} ${cfg} ${cfg}.$$ || |
| error "Can't copy file ${cfg}" $VZ_FS_NO_DISK_SPACE |
| if ! awk -v address="${address}" -v host="${host}" -v comm="${comm}" ' |
| BEGIN { found = 0; extranames = ""; alias=""; } |
| $0 == comm {found = 1; next} |
| found || ($2 == host && (address == "" || address == $1)) { |
| if (address == "") {address = $1} |
| for (i=3; i <= NF; i++) { |
| if ((j=index($2, ".")) > 1) { |
| origalias= substr($2, 1, j - 1); |
| if (origalias != $i) { |
| EXTRANAMES[$i] = 1; |
| } |
| } else { |
| EXTRANAMES[$i] = 1; |
| } |
| } |
| found = 0; |
| next; |
| } |
| address != "" && $1 == address && $2 != host { |
| for (i=2; i <= NF; i++) { EXTRANAMES[$i] = 1 } |
| next; |
| } |
| $1 == "127.0.0.1" { |
| for (i=2; i <= NF; i++) { if ($i != "localhost" && $i != "localhost.localdomain") { LOCALHOST_ALIASES[$i] = 1 } } |
| for (localhost_alias in LOCALHOST_ALIASES) { localhost_aliases = localhost_aliases " " localhost_alias } |
| ate_localhost = 1; |
| next; |
| } |
| $1 == "::1" { |
| my_ipv6 = $0; |
| ate_ipv6 = 1; |
| next; |
| } |
| {print} |
| END { |
| if (address == "") { address ="127.0.0.1" } |
| if (ate_localhost && address != "127.0.0.1") { |
| print "127.0.0.1 localhost.localdomain localhost" localhost_aliases; |
| } |
| print comm; |
| if ((i=index(host, ".")) > 1) { |
| alias= " " substr(host, 1, i - 1); |
| if (! (alias in EXTRANAMES)) { |
| EXTRANAMES[alias] = 1; |
| } |
| } |
| if (address == "127.0.0.1") { |
| if (! ("localhost" in EXTRANAMES)) { |
| EXTRANAMES["localhost"] = 1; |
| } |
| if (! ("localhost.localdomain" in EXTRANAMES)) { |
| EXTRANAMES["localhost.localdomain"] = 1; |
| } |
| extranames = localhost_aliases; |
| } |
| for (extraname in EXTRANAMES) { extranames = extranames " " extraname } |
| print address " " host extranames; |
| if (ate_ipv6) { |
| print my_ipv6; |
| } else { |
| print "::1 localhost"; |
| } |
| } |
| ' < ${cfg} > ${cfg}.$$; then |
| rm -f ${cfg}.$$ 2>/dev/null |
| error "Can't change file ${cfg}" $VZ_FS_NO_DISK_SPACE |
| fi |
| mv -f ${cfg}.$$ ${cfg} |
| } |
| |
| cidr2mask() { |
| local i |
| local mask="" |
| local full_octets=$(($1/8)) |
| local partial_octet=$(($1%8)) |
| |
| for i in 0 1 2 3; do |
| if [ $i -lt $full_octets ]; then |
| mask="${mask}255" |
| elif [ $i -eq $full_octets ]; then |
| mask="${mask}$((256 - (1 << (8 - $partial_octet))))" |
| else |
| mask="${mask}0" |
| fi |
| test $i -lt 3 && mask="${mask}." |
| done |
| |
| echo $mask |
| } |
| |
| ip_conv() { |
| local ipm=$1 |
| _IP=${ipm%%/*} |
| _MASK='' |
| _NETMASK='' |
| _IPV6ADDR='' |
| if [ "${_IP#*:}" != "${_IP}" ]; then |
| _IPV6ADDR=yes |
| fi |
| if echo "${ipm}" | grep -q '/'; then |
| _MASK=${ipm##*/} |
| else |
| if [ -z "$_IPV6ADDR" ]; then |
| _MASK=32 |
| else |
| _MASK=128 |
| fi |
| fi |
| echo $ipm | grep -q ':' && return 0 |
| _NETMASK=$(cidr2mask $_MASK) |
| } |
| |
| quota_tools_support_ext4() { |
| # First a hack for RHEL5 which supports ext4 since quota-3.13-4.el5 |
| test -n "$(rpm -q --qf '%{version}.%{release}\n' quota 2>/dev/null | |
| awk -F . '$NF=="el5" && ($2>13 || ($2==13 && $3>3))')" && |
| return 0 |
| |
| # Now, check other systems, that should have quota > 3.16 |
| quotacheck -V | awk '/ version /{ |
| i=split($4, a, "."); |
| if (i < 2) { |
| print("Unable to detect quota version: " $0); |
| exit 1; |
| } |
| if (a[1] >= 4) { |
| exit 0; |
| } |
| if (a[1] < 3 || (a[1] == 3 && a[2] < 17)) { |
| print("Old quota utils version detected: " $0); |
| print("Quota utils version should be > 3.16"); |
| exit 1; |
| } |
| }' |
| } |
| |
| setup_quota_ploop() { |
| if [ -z "$UGIDLIMIT" ]; then |
| quotaoff -a |
| rm -f /aquota.user |
| rm -f /aquota.group |
| elif [ ! -f "/aquota.user" -o ! -f "/aquota.group" ]; then |
| quota_tools_support_ext4 || exit 1 |
| quotacheck -anugmM -F vfsv0 |
| fi |
| } |
| |
| setup_quota() { |
| if grep -q /dev/ploop /proc/mounts; then |
| setup_quota_ploop |
| else |
| setup_vzquota |
| fi |
| } |
| |
| have_ifconfig() |
| { |
| which ifconfig >/dev/null 2>&1 |
| } |
| |
| is_wicked() |
| { |
| readlink /etc/systemd/system/network.service 2>/dev/null | |
| grep -q wicked |
| } |