Add tests for custom text files
[ganeti-local] / htools / offline-test.sh
1 #!/bin/bash
2
3 # Copyright (C) 2012 Google Inc.
4
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 # General Public License for more details.
14
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 # 02110-1301, USA.
19
20 # This is an offline testing script for most/all of the htools
21 # programs, checking basic command line functionality.
22
23 set -e
24 set -o pipefail
25
26 . $(dirname $0)/cli-tests-defs.sh
27
28 T=`mktemp -d`
29 trap 'rm -rf $T' EXIT
30 trap 'echo FAIL' ERR
31 echo Using $T as temporary dir
32
33 echo Checking command line basic options
34 for prog in $ALL_ROLES; do
35   $prog --version >/dev/null
36   $prog --help >/dev/null
37   ! $prog --no-such-option 2>/dev/null
38 done
39 echo OK
40
41 echo Checking missing backend failure
42 for prog in hspace hinfo hbal; do
43   ! $prog 2>/dev/null
44 done
45 echo OK
46
47 echo Checking hail missing input file
48 ! hail 2>/dev/null
49 echo OK
50
51 echo Checking extra arguments
52 for prog in hspace hbal hinfo; do
53   (! $prog unexpected-argument 2>&1 ) | \
54     grep -q "Error: this program doesn't take any arguments"
55 done
56 echo OK
57
58 echo Checking failure on multiple backends
59 (! hbal -t /dev/null -m localhost 2>&1 ) | \
60   grep -q "Error: Only one of the rapi, luxi, and data files options should be given."
61 echo OK
62
63 echo Checking text file loading
64 hbal -t $TESTDATA_DIR/missing-resources.data 2>&1 | \
65   grep "node node2 is missing .* ram and .* disk" >/dev/null
66 hbal -t $TESTDATA_DIR/common-suffix.data -v 2>&1 | \
67   grep "Stripping common suffix of '.example.com' from names" >/dev/null
68 (! hbal -t $TESTDATA_DIR/invalid-node.data 2>&1 ) | \
69   grep "Unknown node '.*' for instance new-0" >/dev/null
70 echo OK
71
72 echo Checking hspace machine-readable mode
73 hspace --simu p,4,8T,64g,16 --machine-readable \
74   --disk-template drbd -l 8 >$T/capacity
75 ( . $T/capacity && test "$HTS_OK" = "1" )
76 echo OK
77
78 echo Checking hspace simulation to hinfo to hbal
79 # this cluster spec should be fine
80 hspace --simu p,4,8T,64g,16 -S $T/simu-onegroup \
81   --disk-template drbd -l 8 -v -v -v >/dev/null 2>&1
82 # results in .tiered and .standard
83 for suffix in standard tiered; do
84   BACKEND="-t$T/simu-onegroup.$suffix"
85   hinfo -v -v -p --print-instances $BACKEND >/dev/null 2>&1
86   hbal  -v -v -p --print-instances $BACKEND >/dev/null 2>&1
87   # hbal should not be able to balance
88   hbal $BACKEND | grep -qE "(Nothing to do, exiting|No solution found)"
89 done
90 echo OK
91
92 echo Checking hinfo and hbal on multi-nodegroup
93 hspace --simu p,4,8T,64g,16 --simu p,4,8T,64g,16 \
94   -S $T/simu-twogroups --disk-template drbd -l 8 >/dev/null 2>&1
95 # results in .tiered and .standard
96 for suffix in standard tiered; do
97   BACKEND="-t$T/simu-twogroups.$suffix"
98   hinfo -v -v -p --print-instances $BACKEND >/dev/null 2>&1
99   ! hbal $BACKEND >/dev/null 2>&1
100   # hbal should not be able to balance
101   ! hbal $BACKEND 2>&1 | grep -q "Found multiple node groups"
102   # but hbal should be able to balance one node group
103   hbal $BACKEND -G group-01 >/dev/null
104   # and it should not find an invalid group
105   ! hbal $BACKEND -G no-such-group >/dev/null 2>&1
106 done
107 echo OK
108
109 echo Checking rebalancing
110 # we generate a cluster with two node groups, one with unallocable
111 # policy, then we change all nodes from this group to the allocable
112 # one, and we check for rebalancing
113 FROOT="$T/simu-rebal-orig"
114 hspace --simu u,4,8T,64g,16 --simu p,4,8T,64g,16 \
115   -S $FROOT --disk-template drbd -l 8 >/dev/null 2>&1
116 for suffix in standard tiered; do
117   RELOC="$T/simu-rebal-merged.$suffix"
118   # this relocates the nodes
119   sed -re 's/^(node-.*|fake-uuid-)-02(|.*)/\1-01\2/' \
120     < $FROOT.$suffix > $RELOC
121   BACKEND="-t$RELOC"
122   hinfo -v -v -p --print-instances $BACKEND >/dev/null 2>&1
123   hbal -v -v -v -p --print-instances $BACKEND -G group-01 2>/dev/null | \
124     grep -qE -v "(Nothing to do, exiting|No solution found)"
125   hbal $BACKEND -G group-01 -C$T/rebal-cmds.$suffix \
126     -S $T/simu-rebal.$suffix >/dev/null 2>&1
127   grep -qE "gnt-instance (failover|migrate|replace-disks)" \
128     $T/rebal-cmds.$suffix
129   hbal $BACKEND -G group-01 -C \
130     -S $T/simu-rebal.$suffix 2>/dev/null | \
131     grep -qE "gnt-instance (failover|migrate|replace-disks)"
132   # state saved by hbal should be original
133   cmp $RELOC $T/simu-rebal.$suffix.original
134   # and we can't double rebalance
135   hbal -t $T/simu-rebal.$suffix.balanced \
136     -G group-01 | \
137     grep -qE "(Nothing to do, exiting|No solution found)"
138
139 done
140 echo OK
141
142 echo Checking utilisation-based code
143 BACKEND="-t $T/simu-onegroup.standard"
144 echo a > $T/dynu
145 (! hbal -U <(echo a) $BACKEND  2>&1 ) | grep -q "Cannot parse line"
146 (! hbal -U <(echo a b c d e f g h) $BACKEND 2>&1 ) | \
147   grep -q "Cannot parse line"
148 (! hbal -U <(echo inst cpu mem dsk net) $BACKEND 2>&1 ) | \
149   grep -Eq "cannot parse string '(cpu|mem|dsk|net)'"
150 # unknown instances are currently just ignored
151 hbal -U <(echo no-such-inst 2 2 2 2) $BACKEND >/dev/null 2>&1
152 # new-0 is the name of the first instance allocated by hspace
153 hbal -U <(echo new-0 2 2 2 2) $BACKEND >/dev/null 2>&1
154 echo OK
155
156 echo Checking selected/excluded instances
157 (! hbal $BACKEND --exclude-instances no-such-instance 2>&1 ) | \
158   grep -q "Unknown instance"
159 (! hbal $BACKEND --select-instances no-such-instances 2>&1 ) | \
160   grep -q "Unknown instance"
161 hbal $BACKEND --exclude-instances new-0 --select-instances new-1 >/dev/null
162 echo OK
163
164 echo IAllocator checks
165 # test that on invalid files it can't parse the request
166 (! hail /dev/null 2>&1 ) | grep -q "Invalid JSON"
167 ! hail <(echo '[]') >/dev/null 2>&1
168 (! hail <(echo '{}') 2>&1 ) | grep -q "key 'request' not found"
169 (! hail <(echo '{"request": 0}') 2>&1 ) | grep -q "key 'request'"
170 ! hail $TESTDATA_DIR/hail-invalid-reloc.json >/dev/null 2>&1
171
172 # just test that it can read the file, print the cluster and generate
173 # pre and post allocation files
174 hail -v -v -v -p $TESTDATA_DIR/hail-alloc-drbd.json \
175   -S $T/hail-alloc >/dev/null 2>&1
176 ! cmp -s $T/hail-alloc.pre-ialloc $T/hail-alloc.post-ialloc
177 hail -v -v -v -p $TESTDATA_DIR/hail-reloc-drbd.json \
178   -S $T/hail-reloc >/dev/null 2>&1
179 ! cmp -s $T/hail-reloc.pre-ialloc $T/hail-reloc.post-ialloc
180
181 # and now start the real tests
182 hail $TESTDATA_DIR/hail-alloc-drbd.json | \
183   grep -q '"success":true,.*,"result":\["node2","node1"\]'
184 hail $TESTDATA_DIR/hail-reloc-drbd.json | \
185   grep -q '"success":true,.*,"result":\["node1"\]'
186
187 hail $TESTDATA_DIR/hail-node-evac.json | \
188   grep -Fq '"success":true,"info":"Request successful: 0 instances failed to move and 1 were moved successfully"'
189
190 hail $TESTDATA_DIR/hail-change-group.json | \
191   grep -Fq '"success":true,"info":"Request successful: 0 instances failed to move and 1 were moved successfully"'
192
193 for evac_mode in primary-only secondary-only all; do
194   sed -e 's/"evac_mode": "all"/"evac_mode": "'${evac_mode}'"/' \
195     < $TESTDATA_DIR/hail-node-evac.json \
196     > $T/hail-node-evac.json.$evac_mode
197   hail $T/hail-node-evac.json.$evac_mode | \
198     grep -q '"success":true,"info":"Request successful: 0 instances failed to move and 1 were moved successfully"'
199 done
200
201 # check that hail can use the simu and text backends
202 hail --simu p,8,8T,16g,16 $TESTDATA_DIR/hail-alloc-drbd.json | \
203   grep -q '"success":true,'
204 hail -t $T/simu-rebal-merged.standard $TESTDATA_DIR/hail-alloc-drbd.json | \
205   grep -q '"success":true,'
206 echo OK
207
208 echo Checking file-based RAPI
209 mkdir -p $T/hscan
210 URL="file://$TESTDATA_DIR/rapi"
211 hinfo -v -v -p --print-instances -m $URL >/dev/null 2>&1
212 hbal -v -v -p --print-instances -m $URL >/dev/null 2>&1
213 hscan -d $T/hscan/ -p -v -v $URL >/dev/null 2>&1
214 # check that we file parsing is correct, i.e. hscan saves correct text
215 # files, and is idempotent (rapi+text == rapi)
216 HS="$(ls $T/hscan/*.data|head -n1)"
217 hinfo -p --print-instances -m $URL > $T/hscan/direct.hinfo 2>&1
218 hinfo -p --print-instances -t $HS  > $T/hscan/fromtext.hinfo 2>&1
219 cmp -s $T/hscan/direct.hinfo $T/hscan/fromtext.hinfo
220 echo OK
221
222 echo All OK