Revision 29386d3e

b/.gitignore
93 93
# tools
94 94
/tools/kvm-ifup
95 95
/tools/ensure-dirs
96
/tools/vcluster-setup
96 97

  
97 98
# scripts
98 99
/scripts/gnt-backup
b/Makefile.am
160 160
	$(man_MANS) \
161 161
	$(manhtml) \
162 162
	tools/kvm-ifup \
163
	tools/vcluster-setup
163 164
	stamp-directories \
164 165
	stamp-srclinks \
165 166
	$(nodist_pkgpython_PYTHON) \
......
675 676
	tools/xm-console-wrapper \
676 677
	tools/master-ip-setup
677 678

  
679
nodist_tools_SCRIPTS = \
680
	tools/vcluster-setup
681

  
678 682
pkglib_python_scripts = \
679 683
	daemons/import-export \
680 684
	tools/check-cert-expired
......
716 720
	$(pkglib_python_scripts) \
717 721
	devel/upload.in \
718 722
	tools/kvm-ifup.in \
723
	tools/vcluster-setup.in \
719 724
	$(docdot) \
720 725
	$(docpng) \
721 726
	$(docrst) \
......
1052 1057
	sed -f $(REPLACE_VARS_SED) < $< > $@
1053 1058
	chmod u+x $@
1054 1059

  
1060
tools/vcluster-setup: tools/vcluster-setup.in $(REPLACE_VARS_SED)
1061
	sed -f $(REPLACE_VARS_SED) < $< > $@
1062
	chmod +x $@
1063

  
1055 1064
daemons/%:: daemons/%.in $(REPLACE_VARS_SED)
1056 1065
	sed -f $(REPLACE_VARS_SED) < $< > $@
1057 1066
	chmod +x $@
b/tools/vcluster-setup.in
1
#!/bin/bash
2
#
3

  
4
# Copyright (C) 2012 Google Inc.
5
#
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 2 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
# General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
# 02110-1301, USA.
20

  
21
set -e -u -o pipefail
22
shopt -s extglob
23

  
24
readonly self=$(readlink -f $0)
25
readonly ensure_dirs=@PKGLIBDIR@/ensure-dirs
26
readonly action_shortcuts=( start stop restart status )
27
readonly default_nodecount=5
28
readonly default_instcount=10
29
readonly default_netprefix=192.0.2
30
readonly default_netdev=eth0
31
readonly cluster_name=cluster
32

  
33
# IP address space:
34
# Cluster: .1
35
# Nodes: .10-.99
36
# Instances: .100-.254
37
readonly first_node_ipaddr_octet=10
38
readonly first_inst_ipaddr_octet=100
39

  
40
readonly max_node_count=$((first_inst_ipaddr_octet - first_node_ipaddr_octet))
41
readonly max_instance_count=$((255 - first_inst_ipaddr_octet))
42

  
43
usage() {
44
  echo "Usage: $0 [-c <number>] [-i <number>] [-p <prefix>] [-n <netdev>]"\
45
       '<directory>'
46
  echo
47
  echo 'Options:'
48
  echo "  -c  Number of virtual nodes (defaults to $default_nodecount)"
49
  echo "  -i  Number of instances (defaults to $default_instcount)"
50
  echo "  -p  IPv4 network prefix (defaults to $default_netprefix)"
51
  echo '  -n  Network device for virtual IP addresses (defaults to'\
52
       "$default_netdev)"
53
}
54

  
55
# Variables for options
56
nodecount=$default_nodecount
57
instcount=$default_instcount
58
netprefix=$default_netprefix
59
netdev=$default_netdev
60

  
61
# Parse options
62
while getopts :hc:p:n:i: opt; do
63
  case "$opt" in
64
    h)
65
      usage
66
      exit 0
67
    ;;
68
    c)
69
      nodecount="$OPTARG"
70
      if [[ "$nodecount" != +([0-9]) ]]; then
71
        echo "Invalid node count number: $nodecount" >&2
72
        exit 1
73
      elif (( nodecount > max_node_count )); then
74
        echo "Node count must be $max_node_count or lower" >&2
75
        exit 1
76
      fi
77
    ;;
78
    i)
79
      instcount="$OPTARG"
80
      if [[ "$instcount" != +([0-9]) ]]; then
81
        echo "Invalid instance count number: $instcount" >&2
82
        exit 1
83
      elif (( instcount > max_instance_count )); then
84
        echo "Instance count must be $max_instance_count or lower" >&2
85
        exit 1
86
      fi
87
    ;;
88
    p)
89
      netprefix="$OPTARG"
90
      if [[ "$netprefix" != +([0-9]).+([0-9]).+([0-9]) ]]; then
91
        echo "Invalid network prefix: $netprefix" >&2
92
        exit 1
93
      fi
94
    ;;
95
    n)
96
      netdev="$OPTARG"
97
      if ! ip link show $netdev >/dev/null; then
98
        echo "Invalid network device: $netdev" >&2
99
        exit 1
100
      fi
101
    ;;
102
    \?)
103
      echo "Invalid option: -$OPTARG" >&2
104
      usage >&2
105
      exit 1
106
      ;;
107
    :)
108
      echo "Option -$OPTARG requires an argument" >&2
109
      usage >&2
110
      exit 1
111
      ;;
112
  esac
113
done
114

  
115
shift $((OPTIND - 1))
116

  
117
if [[ "$#" != 1 ]]; then
118
  usage
119
  exit 1
120
fi
121

  
122
readonly rootdir=$1; shift
123

  
124
if [[ ! -d "$rootdir" ]]; then
125
  echo "Directory '$rootdir' does not exist!" >&2
126
  exit 1
127
fi
128

  
129
if (( $nodecount < 1 )); then
130
  echo "Must create at least one node, currently requested $nodecount" >&2
131
  exit 1
132
fi
133

  
134
node_hostname() {
135
  local -r number="$1"
136

  
137
  echo "node$((number + 1))"
138
}
139

  
140
instance_hostname() {
141
  local -r number="$1"
142

  
143
  echo "instance$((number + 1))"
144
}
145

  
146
node_ipaddr() {
147
  local -r number="$1"
148

  
149
  echo "$netprefix.$((first_node_ipaddr_octet + number))"
150
}
151

  
152
instance_ipaddr() {
153
  local -r number="$1"
154

  
155
  echo "$netprefix.$((first_inst_ipaddr_octet + number))"
156
}
157

  
158
setup_node() {
159
  local -r number="$1"
160
  local -r nodedir=$rootdir/$(node_hostname $number)
161

  
162
  echo "Setting up node '$(node_hostname $number)' ..." >&2
163

  
164
  if [[ ! -d $nodedir ]]; then
165
    mkdir $nodedir
166
  fi
167

  
168
  mkdir -p \
169
    $nodedir/etc/default \
170
    $nodedir/var/lock\
171
    $nodedir/var/{lib,log,run}/ganeti
172

  
173
  GANETI_HOSTNAME=$(node_hostname $number) \
174
  GANETI_ROOTDIR=$nodedir \
175
  $ensure_dirs
176

  
177
  local -r daemon_args="-b $(node_ipaddr $number)"
178

  
179
  cat > $nodedir/etc/default/ganeti <<EOF
180
# Default settings for virtual node $i
181
NODED_ARGS='--no-mlock $daemon_args'
182
MASTERD_ARGS=''
183
RAPI_ARGS='$daemon_args'
184
CONFD_ARGS='$daemon_args'
185

  
186
export GANETI_ROOTDIR='$nodedir'
187
export GANETI_HOSTNAME='$(node_hostname $number)'
188
EOF
189

  
190
  cat > $nodedir/cmd <<EOF
191
#!/bin/bash
192

  
193
export GANETI_ROOTDIR='$nodedir'
194
export GANETI_HOSTNAME='$(node_hostname $number)'
195

  
196
bash -c "\$*"
197
EOF
198
  chmod +x $nodedir/cmd
199
}
200

  
201
setup_all_nodes() {
202
  for ((i=0; i < nodecount; ++i)); do
203
    setup_node $i
204
  done
205
}
206

  
207
setup_etc_hosts() {
208
  echo 'Configuring /etc/hosts ...' >&2
209
  (
210
    set -e -u
211
    local -r tmpfile=$(mktemp /etc/hosts.vcluster.XXXXX)
212
    trap "rm -f $tmpfile" EXIT
213
    {
214
      egrep -v "^$netprefix.[[:digit:]]+[[:space:]]" /etc/hosts
215
      echo "$netprefix.1 $cluster_name"
216
      for ((i=0; i < nodecount; ++i)); do
217
        echo "$(node_ipaddr $i) $(node_hostname $i)"
218
      done
219
      for ((i=0; i < instcount; ++i)); do
220
        echo "$(instance_ipaddr $i) $(instance_hostname $i)"
221
      done
222
    } > $tmpfile && \
223
    chmod 0644 $tmpfile && \
224
    mv $tmpfile /etc/hosts && \
225
    trap - EXIT
226
  )
227
}
228

  
229
setup_network_interfaces() {
230
  echo 'Configuring network ...' >&2
231
  for ((i=0; i < nodecount; ++i)); do
232
    local ipaddr="$(node_ipaddr $i)/32"
233
    ip addr del "$ipaddr" dev "$netdev" || :
234
    ip addr add "$ipaddr" dev "$netdev"
235
  done
236
}
237

  
238
setup_scripts() {
239
  echo 'Configuring helper scripts ...' >&2
240
  for action in "${action_shortcuts[@]}"; do
241
    {
242
      echo '#!/bin/bash'
243
      for ((i=0; i < nodecount; ++i)); do
244
        local name=$(node_hostname $i)
245
        echo "echo 'Action \"$action\" for virtual node \"$name\" ...'"
246
        echo "$name/cmd /etc/init.d/ganeti $action"
247
      done
248
    } > $rootdir/$action-all
249
    chmod +x $rootdir/$action-all
250
  done
251
}
252

  
253
show_info() {
254
  cat <<EOF
255
Virtual cluster setup is complete.
256

  
257
Root directory: $rootdir
258
Cluster name: $cluster_name
259
EOF
260

  
261
  echo 'Nodes:' $(for ((i=0; i < nodecount; ++i)); do node_hostname $i; done)
262

  
263
  cat <<EOF
264

  
265
Initialize cluster:
266
  cd $rootdir && node1/cmd gnt-cluster init --no-etc-hosts $cluster_name
267

  
268
Change cluster settings:
269
  cd $rootdir && node1/cmd gnt-cluster modify \\
270
    --enabled-hypervisors=fake \\
271
    --specs-disk-size=min=0 --specs-disk-count=min=0
272

  
273
Add node:
274
  cd $rootdir && node1/cmd gnt-node add --no-ssh-key-check node2
275
EOF
276
}
277

  
278
setup_all_nodes
279
setup_etc_hosts
280
setup_network_interfaces
281
setup_scripts
282
show_info
283

  
284
exit 0
285

  
286
# vim: set sw=2 sts=2 et :

Also available in: Unified diff