blob: 358354cd521f6181b6e7d039595dbd129cd240c5 [file] [log] [blame] [raw]
#!/bin/sh
# Copyright (C) 2000-2011, 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=$?
echo "$SELFNAME ERROR: $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
/bin/sed -e "s|^$name=.*|$name=\"$value\"|" < ${file} > ${file}.$$
if [ $? -ne 0 ]; then
rm -f ${file}.$$ 2>/dev/null
error "Can't change file $file" $VZ_FS_NO_DISK_SPACE
fi
mv -f ${file}.$$ ${file}
else
echo "$name=\"$value\"" >> $file || 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 -qe "^$name=" $file >/dev/null 2>&1; then
${CP} ${file} ${file}.$$ ||
error "Can't copy file $file" $VZ_FS_NO_DISK_SPACE
/bin/sed -e "s|^$name=\"\(.*\)\"|$name=\"\1 $value \"|" < ${file} > ${file}.$$
if [ $? -ne 0 ]; then
rm -f ${file}.$$ 2>/dev/null
error "Can't change file $file" $VZ_FS_NO_DISK_SPACE
fi
mv -f ${file}.$$ ${file}
else
echo "$name=\"$value\"" >> $file || 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 -qe "^$name=" $file >/dev/null 2>&1; then
${CP} ${file} ${file}.$$ ||
error "Can't copy file $file" $VZ_FS_NO_DISK_SPACE
if [ -z "${value}" ]; then
/bin/sed -e "/^${name}=.*/d" < ${file} > ${file}.$$
else
sed -e "s|^${name}=\(.*\)${value}\(.*\)|${name}=\1\2|" <${file} > ${file}.$$
fi
if [ $? -ne 0 ]; 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
/bin/sed -e "s|^\<$name\>.*|$name $value|" < ${file} > ${file}.$$
if [ $? -ne 0 ]; then
rm -f ${file}.$$ 2>/dev/null
error "Can't change file $file" $VZ_FS_NO_DISK_SPACE
fi
mv -f ${file}.$$ ${file}
else
echo "$name $value" >> $file || 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 [ -z "${value}" ]; then
/bin/sed -e "s|^$name=\(.*\)|$name=\( \)|" < ${file} > ${file}.$$
else
/bin/sed -e "s|^$name=\(.*\)|$name=\( \"$value\" \)|" < ${file} > ${file}.$$
fi
if [ $? -ne 0 ]; then
rm -f ${file}.$$ 2>/dev/null
error "Can't change file $file" $VZ_FS_NO_DISK_SPACE
fi
mv -f ${file}.$$ ${file}
else
if [ -z "${value}" ]; then
echo "$name=( )" >> $file || error "Can't change file $file" $VZ_FS_NO_DISK_SPACE
else
echo "$name=( \"$value\" )" >> $file || error "Can't change file $file" $VZ_FS_NO_DISK_SPACE
fi
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
/bin/sed -r "s|^$name=\((.*)\)|$name=\( \1 \"$value\" \)|" < ${file} > ${file}.$$
if [ $? -ne 0 ]; then
rm -f ${file}.$$ 2>/dev/null
error "Can't change file $file" $VZ_FS_NO_DISK_SPACE
fi
mv -f ${file}.$$ ${file}
else
echo "$name=( \"$value\" )" >> $file || 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
if grep -E "^$name=\(.*\)" $file>/dev/null 2>&1; then
${CP} ${file} ${file}.$$ || error "Can't copy file $file" $VZ_FS_NO_DISK_SPACE
/bin/sed -r "s|^($name=\( .*)\"$value\"(.* \))|\1\2|" < ${file} > ${file}.$$
if [ $? -ne 0 ]; 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
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 ip="$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
fi
${CP} ${cfg} ${cfg}.$$ ||
error "Can't copy file ${cfg}" $VZ_FS_NO_DISK_SPACE
awk -v ip="${ip}" -v host="${host}" -v comm="${comm}" '
BEGIN { found = 0; extranames = ""; alias=""; }
$0 == comm {found = 1; next}
found || ($2 == host && (ip == "" || ip == $1)) {
if (ip == "") {ip = $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;
}
ip != "" && $1 == ip && $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 (ip == "") { ip ="127.0.0.1" }
if (ate_localhost && ip != "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 (ip == "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 ip " " host extranames;
if (ate_ipv6) {
print my_ipv6;
} else {
print "::1 localhost";
}
}
' < ${cfg} > ${cfg}.$$
if [ $? -ne 0 ]; 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
_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
}