blob: b1ca91e8868c1421e0d3da8ce659d3b9799c9d60 [file] [log] [blame] [raw]
#!/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
}