source: ror-farm/ror-farm-add @ 338

Last change on this file since 338 was 338, checked in by lucas, 11 years ago

ror-farm-add: remove debug

  • Property svn:executable set to *
File size: 9.1 KB
Line 
1#!/bin/sh
2
3# ror-farm-add (c) 2008 Bearstech - http://bearstech.com
4#
5# Depends: util-vserver vserver-debiantools lvm2 passwd pwgen
6# Recommends: mysql-client
7
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation, either version 3 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
21THIS_NAME=ror-farm-add
22THIS_VERSION=3
23
24# Distro-specific paths
25#
26VSERVER_CONF=/etc/vservers
27VSERVER_HOME=/var/lib/vservers
28
29# Default options
30#
31domain=ror.bearstech.com
32vgname=`vgdisplay -Ac 2>/dev/null | head -n1 | sed 's/^ *\([^:]*\).*/\1/'`
33slices=1
34template=template
35ssh_keys=""
36
37help() {
38  cat << EOF
39Usage: $THIS_NAME [options] vserver-name vserver-id
40
41Creates a new RoR-ready vserver instance.
42
43Options:
44  --domain       vserver template (default: '$domain')
45  --vgname       LVM volume group for vserver home (default: '$vgname')
46  --slices       Number of slices to allocate for this rorette (CPU/RAM/Disk)
47                 can be 1, 2 or 4 (default: $slices)
48  --template     vserver filesystem template (default: '$template')
49  --ssh-key      install a SSH public key file in the ror account (no default value)
50                 (can be specified several times)
51  --help, -h     this help
52  --version, -v  this script version
53EOF
54}
55
56version() {
57  echo "$THIS_NAME $THIS_VERSION"
58}
59
60error() {
61  echo "$THIS_NAME: error: $*"
62  exit 1
63}
64
65lv_from_slices() {
66  if [ $slices -eq 1 ]; then
67    lvsize=1G
68  elif [ $slices -eq 2 ]; then
69    lvsize=2G
70  elif [ $slices -eq 4 ]; then
71    lvsize=4G
72  else
73    echo "$THIS_NAME: error, slice must be a valid number (was: '$slices')"
74    exit 1
75  fi
76}
77
78ram_from_slices() {
79  if [ $slices -eq 1 ]; then
80    ram='512 384'
81  elif [ $slices -eq 2 ]; then
82    ram='1024 768'
83  elif [ $slices -eq 4 ]; then
84    ram='2048 1536'
85  else
86    echo "$THIS_NAME: error, slice must be a valid number (was: '$slices')"
87    exit 1
88  fi
89}
90
91# non-linear progression
92cpu_from_slices() {
93  if [ $slices -eq 1 ]; then
94    cpu='32 1024'
95  elif [ $slices -eq 2 ]; then
96    cpu='64 1536'
97  elif [ $slices -eq 4 ]; then
98    cpu='96 2048'
99  else
100    echo "$THIS_NAME: error, slice must be a valid number (was: '$slices')"
101    exit 1
102  fi
103}
104
105# Parse args
106#
107parse_opt=run
108while [ $parse_opt != "done"  ] ; do
109  case "$1" in
110
111    --domain)      shift; domain="$1"; shift;;
112    --vgname)      shift; vgname="$1"; shift;;
113    --slices)      shift; slices="$1"; shift;;
114    --template)    shift; template="$1"; shift;;
115    --ssh-key)     shift; ssh_keys="$ssh_keys
116$1"; shift;;
117
118    --help|-h)     shift; help; exit 0;;
119    --version|-v)  shift; version; exit 0;;
120
121    --)            shift; parse_opt=done;;
122    -*)            echo "$THIS_NAME: unknown option '$1'"; exit 1;;
123    *)             parse_opt=done;;
124  esac
125done
126name="$1"; shift
127id="$1"; shift
128
129
130# Sanity checks (lots of them)
131#
132
133set -e
134
135if [ -z "$name" ]; then
136  error "missing vserver-name"
137fi
138if [ x"$name" != x`echo "$name" | sed -ne '/^[a-z][a-z0-9]\{2,9\}$/p'` ]; then
139  error "unsupported vserver-name '$name' (0-9, a-z, 10 chars max, begins with a letter)"
140fi
141if [ -d "$VSERVER_CONF/$name" ]; then
142  error "vserver '$name' already exists"
143fi
144
145if [ -z "$id" ]; then
146  error "missing vserver-id"
147fi
148if [ $id -lt 2 -o $id -gt 49151 ]; then
149  error "vserver-id must be in 2..49151 range"
150fi
151cd $VSERVER_CONF
152for c in */context; do
153  if [ "$id" = `cat $c` ]; then
154    error "vserver-id already used by '${c/\/context/}'"
155  fi
156done
157
158if [ -z "$domain" ]; then
159  error "empty domain unsupported, use a dummy"
160fi
161
162if [ -z "$vgname" ]; then
163  error "missing --vgname"
164fi
165vgs "$vgname" >/dev/null 2>/dev/null || \
166  error "volume group '$vgname' not found"
167
168if [ -z "$slices" ]; then
169  error "missing --slices"
170fi
171if [ x"$slices" != x`echo "$slices" | sed -ne '/^[124]$/p'` ]; then
172  error "unsupported slices amount '$slices' (use 1, 2 or 4)"
173fi
174
175if [ -z "$template" ]; then
176  error "missing --template"
177fi
178if [ x`echo "$template" | sed -ne '/\//p'` != x ]; then
179  error "unsane template name ('$template')"
180fi
181if [ ! -d "$VSERVER_HOME/$template" ]; then
182  error "filesystem template '$template' not found (in $VSERVER_HOME)"
183fi
184
185# From slices to sizes
186lv_from_slices
187
188ram_from_slices
189ram_rss=$(echo $ram | cut -d' ' -f 1)
190ram_anon=$(echo $ram | cut -d' ' -f 2)
191
192cpu_from_slices
193cpu_nproc=$(echo $cpu | cut -d' ' -f 1)
194cpu_openfd=$(echo $cpu | cut -d' ' -f 2)
195
196
197# Setup vserver config
198#
199mkdir $VSERVER_CONF/$name
200cd    $VSERVER_CONF/$name
201
202mkdir -p apps/init
203mkdir -p apps/pkgmgmt
204mkdir -p cpuset
205mkdir -p interfaces/0
206mkdir -p rlimits
207mkdir -p uts
208
209ln -s $VSERVER_CONF/.defaults/run/$name      run
210ln -s $VSERVER_CONF/.defaults/vdirbase/$name vdir
211
212echo default > apps/init/mark
213echo $id     > context
214echo $name   > name
215echo $name   > uts/nodename
216cat <<EOF    > fstab
217none    /proc           proc    defaults                0 0
218none    /tmp            tmpfs   size=16m,mode=1777      0 0
219none    /dev/pts        devpts  gid=5,mode=620          0 0
220EOF
221
222# Rationale for the id -> ip mapping:
223# - id starts with 2, IP starts with 10.0.0.2 (.1 is gateway)
224# - map 250 ids per /24, we thus have 4 free IPs per /24 if needed
225# - id 2..251 map directly to 10.0.0.id
226#
227ip=10.0.$((($id-2) / 250)).$((2 + ($id-2) % 250))
228echo dummy0       > interfaces/0/dev
229echo $ip          > interfaces/0/ip
230echo 16           > interfaces/0/prefix
231
232mb=$((1024*1024 / `getconf PAGE_SIZE`))
233echo $(($ram_rss*$mb))  > rlimits/rss
234echo $(($ram_anon*$mb)) > rlimits/anon
235echo $cpu_nproc         > rlimits/nproc
236echo $cpu_openfd        > rlimits/nofile
237echo $cpu_openfd        > rlimits/openfd
238echo $cpu_nproc         > rlimits/nsock
239# upgrade /tmp size in > fstab ? (default: 16MB)
240# Display memory limits within a vserver (see http://linux-vserver.org/Memory_Limits)
241echo "VIRT_MEM"   >> flags
242
243
244# Setup vserver's filesystem root
245#
246cd $VSERVER_HOME
247mkdir $name
248
249# Create this vserver's home
250#
251lvcreate --quiet -L $lvsize -n $name $vgname >/dev/null
252mke2fs -q -i 4069 -j -m 0 /dev/$vgname/$name
253
254# Setup permnanent mountpoints, and mount them
255#
256cat <<EOF >>/etc/fstab
257$VSERVER_HOME/$template  $VSERVER_HOME/$name  bind  ro,bind  0  0
258/dev/$vgname/$name  $VSERVER_HOME/$name/home  ext3  defaults,noatime  0  0
259EOF
260mount $name
261mount $name/home
262
263
264# Populate home with a template copy
265#
266cp -a $template/home/* $name/home
267
268
269# Fixup various files to customize the template filesystem
270# (the following files are symlinked from /etc/ to /home/etc)
271#
272cd $VSERVER_HOME/$name
273
274cat  <<EOF         > etc/hosts
275127.0.0.1       localhost.localdomain localhost
276$ip     $name.$domain $name
277EOF
278echo $name          > etc/hostname
279echo $name.$domain  > etc/mailname
280rm -f etc/motd
281cat <<EOF           > etc/motd
282
283Welcome to $name.$domain, your own RoR server.
284
285See http://my.$domain/projects/show/$id for your account
286settings and monitoring. Have fun ! The Bearstech RoR team.
287
288EOF
289
290# Adjust cronjob times (mitigate 'cron storm' across many vservers)
291#
292delta=$(($id % 20))
293cron_tmp=`mktemp -t crontab.XXXXXXXX`
294cron_daily=$((10 + $delta - 1))
295cron_weekly=$((30 + $delta - 1))
296cron_monthly=$((40 + $delta - 1))
297sed \
298  -e 's/^[0-9]\+ \(.*cron\.daily.*\)/'$cron_daily' \1/' \
299  -e 's/^[0-9]\+ \(.*cron\.weekly.*\)/'$cron_weekly' \1/' \
300  -e 's/^[0-9]\+ \(.*cron\.monthly.*\)/'$cron_monthly' \1/' \
301  < etc/crontab \
302  > $cron_tmp
303mv $cron_tmp etc/crontab
304
305# Cleanup /var (yes, we remove *all* files)
306#
307find $VSERVER_HOME/$name/var/ -type f -exec rm {} \;
308
309# Cleanup user account
310#
311cd $VSERVER_HOME/$name/home/ror
312
313rm -rf .aptitude
314rm -f .bash_history .lesshst .viminfo
315rm -f .ssh/known_hosts .ssh/id_*
316rm -f gem/source_cache
317rm -f gem/cache/*
318rm -rf rubygems-*
319rm -f http/tmp/*
320rm -f http/log/*
321
322
323# Shell account (created on root-server, redirects to ror@$name)
324#
325useradd \
326  --uid 0 --gid 0 --non-unique \
327  --password '*' \
328  --comment "by=ror-farm-add,name=$name,id=$id" \
329  --home  $VSERVER_HOME/$name/home/ror \
330  --shell /usr/local/bin/ror-farm-shell \
331  $name
332
333
334# Databases (a common password for all of them)
335#
336db_pass=`pwgen 8 1`
337
338# Setup MySQL accounts and databases
339#
340if mysql --version >/dev/null 2>/dev/null; then
341  cat <<EOF | mysql
342CREATE DATABASE \`${name}_dev\` CHARSET utf8;
343CREATE DATABASE \`${name}_prod\` CHARSET utf8;
344GRANT ALL PRIVILEGES ON \`${name}\_dev\`.* TO '$name'@'%';
345GRANT ALL PRIVILEGES ON \`${name}\_prod\`.* TO '$name'@'%';
346SET PASSWORD FOR '$name'@'%'=PASSWORD('$db_pass');
347FLUSH PRIVILEGES;
348EOF
349
350  cat <<EOF > .my.cnf
351[client]
352host = 10.0.0.1
353user = $name
354pass = $db_pass
355default-character-set = utf8
356EOF
357fi
358
359# Setup SSH access if asked for
360if [ ! -z "$ssh_keys" ]; then
361  for k in $ssh_keys; do
362    cat $k >> .ssh/authorized_keys
363  done
364  # be sure to chown the file, SSH is picky
365  chown ror:ror .ssh/authorized_keys
366fi
367
368# Setup PostgreSQL accounts and databases
369#
370#if psql --version >/dev/null 2>/dev/null; then
371#fi
372
373
374# All done, start new vserver
375#
376vserver "$name" start
Note: See TracBrowser for help on using the repository browser.