LUQueryNodes: Convert to new query model
[ganeti-local] / qa / qa_cluster.py
1 #
2 #
3
4 # Copyright (C) 2007, 2010 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
22 """Cluster related QA tests.
23
24 """
25
26 import tempfile
27 import os.path
28
29 from ganeti import constants
30 from ganeti import utils
31
32 import qa_config
33 import qa_utils
34 import qa_error
35
36 from qa_utils import AssertEqual, AssertCommand
37
38
39 def _RemoveFileFromAllNodes(filename):
40   """Removes a file from all nodes.
41
42   """
43   for node in qa_config.get("nodes"):
44     AssertCommand(["rm", "-f", filename], node=node)
45
46
47 def _CheckFileOnAllNodes(filename, content):
48   """Verifies the content of the given file on all nodes.
49
50   """
51   cmd = utils.ShellQuoteArgs(["cat", filename])
52   for node in qa_config.get("nodes"):
53     AssertEqual(qa_utils.GetCommandOutput(node["primary"], cmd), content)
54
55
56 def TestClusterInit(rapi_user, rapi_secret):
57   """gnt-cluster init"""
58   master = qa_config.GetMasterNode()
59
60   rapi_dir = os.path.dirname(constants.RAPI_USERS_FILE)
61
62   # First create the RAPI credentials
63   fh = tempfile.NamedTemporaryFile()
64   try:
65     fh.write("%s %s write\n" % (rapi_user, rapi_secret))
66     fh.flush()
67
68     tmpru = qa_utils.UploadFile(master["primary"], fh.name)
69     try:
70       AssertCommand(["mkdir", "-p", rapi_dir])
71       AssertCommand(["mv", tmpru, constants.RAPI_USERS_FILE])
72     finally:
73       AssertCommand(["rm", "-f", tmpru])
74   finally:
75     fh.close()
76
77   # Initialize cluster
78   cmd = ['gnt-cluster', 'init']
79
80   cmd.append("--primary-ip-version=%d" %
81              qa_config.get("primary_ip_version", 4))
82
83   if master.get('secondary', None):
84     cmd.append('--secondary-ip=%s' % master['secondary'])
85
86   bridge = qa_config.get('bridge', None)
87   if bridge:
88     cmd.append('--bridge=%s' % bridge)
89     cmd.append('--master-netdev=%s' % bridge)
90
91   htype = qa_config.get('enabled-hypervisors', None)
92   if htype:
93     cmd.append('--enabled-hypervisors=%s' % htype)
94
95   cmd.append(qa_config.get('name'))
96
97   AssertCommand(cmd)
98
99
100 def TestClusterRename():
101   """gnt-cluster rename"""
102   cmd = ['gnt-cluster', 'rename', '-f']
103
104   original_name = qa_config.get('name')
105   rename_target = qa_config.get('rename', None)
106   if rename_target is None:
107     print qa_utils.FormatError('"rename" entry is missing')
108     return
109
110   cmd_verify = ['gnt-cluster', 'verify']
111
112   for data in [
113     cmd + [rename_target],
114     cmd_verify,
115     cmd + [original_name],
116     cmd_verify,
117     ]:
118     AssertCommand(data)
119
120
121 def TestClusterVerify():
122   """gnt-cluster verify"""
123   AssertCommand(["gnt-cluster", "verify"])
124
125
126 def TestJobqueue():
127   """gnt-debug test-jobqueue"""
128   AssertCommand(["gnt-debug", "test-jobqueue"])
129
130
131 def TestClusterReservedLvs():
132   """gnt-cluster reserved lvs"""
133   CVERIFY = ["gnt-cluster", "verify"]
134   for fail, cmd in [
135     (False, CVERIFY),
136     (False, ["gnt-cluster", "modify", "--reserved-lvs", ""]),
137     (False, ["lvcreate", "-L1G", "-nqa-test", "xenvg"]),
138     (True,  CVERIFY),
139     (False, ["gnt-cluster", "modify", "--reserved-lvs", "qa-test,other-test"]),
140     (False, CVERIFY),
141     (False, ["gnt-cluster", "modify", "--reserved-lvs", "qa-.*"]),
142     (False, CVERIFY),
143     (False, ["gnt-cluster", "modify", "--reserved-lvs", ""]),
144     (True,  CVERIFY),
145     (False, ["lvremove", "-f", "xenvg/qa-test"]),
146     (False, CVERIFY),
147     ]:
148     AssertCommand(cmd, fail=fail)
149
150
151 def TestClusterModifyBe():
152   """gnt-cluster modify -B"""
153   for fail, cmd in [
154     # mem
155     (False, ["gnt-cluster", "modify", "-B", "memory=256"]),
156     (False, ["sh", "-c", "gnt-cluster info|grep '^ *memory: 256$'"]),
157     (True,  ["gnt-cluster", "modify", "-B", "memory=a"]),
158     (False, ["gnt-cluster", "modify", "-B", "memory=128"]),
159     (False, ["sh", "-c", "gnt-cluster info|grep '^ *memory: 128$'"]),
160     # vcpus
161     (False, ["gnt-cluster", "modify", "-B", "vcpus=4"]),
162     (False, ["sh", "-c", "gnt-cluster info|grep '^ *vcpus: 4$'"]),
163     (True,  ["gnt-cluster", "modify", "-B", "vcpus=a"]),
164     (False, ["gnt-cluster", "modify", "-B", "vcpus=1"]),
165     (False, ["sh", "-c", "gnt-cluster info|grep '^ *vcpus: 1$'"]),
166     # auto_balance
167     (False, ["gnt-cluster", "modify", "-B", "auto_balance=False"]),
168     (False, ["sh", "-c", "gnt-cluster info|grep '^ *auto_balance: False$'"]),
169     (True,  ["gnt-cluster", "modify", "-B", "auto_balance=1"]),
170     (False, ["gnt-cluster", "modify", "-B", "auto_balance=True"]),
171     (False, ["sh", "-c", "gnt-cluster info|grep '^ *auto_balance: True$'"]),
172     ]:
173     AssertCommand(cmd, fail=fail)
174
175
176 def TestClusterInfo():
177   """gnt-cluster info"""
178   AssertCommand(["gnt-cluster", "info"])
179
180
181 def TestClusterGetmaster():
182   """gnt-cluster getmaster"""
183   AssertCommand(["gnt-cluster", "getmaster"])
184
185
186 def TestClusterVersion():
187   """gnt-cluster version"""
188   AssertCommand(["gnt-cluster", "version"])
189
190
191 def TestClusterRenewCrypto():
192   """gnt-cluster renew-crypto"""
193   master = qa_config.GetMasterNode()
194
195   # Conflicting options
196   cmd = ["gnt-cluster", "renew-crypto", "--force",
197          "--new-cluster-certificate", "--new-confd-hmac-key"]
198   conflicting = [
199     ["--new-rapi-certificate", "--rapi-certificate=/dev/null"],
200     ["--new-cluster-domain-secret", "--cluster-domain-secret=/dev/null"],
201     ]
202   for i in conflicting:
203     AssertCommand(cmd+i, fail=True)
204
205   # Invalid RAPI certificate
206   cmd = ["gnt-cluster", "renew-crypto", "--force",
207          "--rapi-certificate=/dev/null"]
208   AssertCommand(cmd, fail=True)
209
210   rapi_cert_backup = qa_utils.BackupFile(master["primary"],
211                                          constants.RAPI_CERT_FILE)
212   try:
213     # Custom RAPI certificate
214     fh = tempfile.NamedTemporaryFile()
215
216     # Ensure certificate doesn't cause "gnt-cluster verify" to complain
217     validity = constants.SSL_CERT_EXPIRATION_WARN * 3
218
219     utils.GenerateSelfSignedSslCert(fh.name, validity=validity)
220
221     tmpcert = qa_utils.UploadFile(master["primary"], fh.name)
222     try:
223       AssertCommand(["gnt-cluster", "renew-crypto", "--force",
224                      "--rapi-certificate=%s" % tmpcert])
225     finally:
226       AssertCommand(["rm", "-f", tmpcert])
227
228     # Custom cluster domain secret
229     cds_fh = tempfile.NamedTemporaryFile()
230     cds_fh.write(utils.GenerateSecret())
231     cds_fh.write("\n")
232     cds_fh.flush()
233
234     tmpcds = qa_utils.UploadFile(master["primary"], cds_fh.name)
235     try:
236       AssertCommand(["gnt-cluster", "renew-crypto", "--force",
237                      "--cluster-domain-secret=%s" % tmpcds])
238     finally:
239       AssertCommand(["rm", "-f", tmpcds])
240
241     # Normal case
242     AssertCommand(["gnt-cluster", "renew-crypto", "--force",
243                    "--new-cluster-certificate", "--new-confd-hmac-key",
244                    "--new-rapi-certificate", "--new-cluster-domain-secret"])
245
246     # Restore RAPI certificate
247     AssertCommand(["gnt-cluster", "renew-crypto", "--force",
248                    "--rapi-certificate=%s" % rapi_cert_backup])
249   finally:
250     AssertCommand(["rm", "-f", rapi_cert_backup])
251
252
253 def TestClusterBurnin():
254   """Burnin"""
255   master = qa_config.GetMasterNode()
256
257   options = qa_config.get('options', {})
258   disk_template = options.get('burnin-disk-template', 'drbd')
259   parallel = options.get('burnin-in-parallel', False)
260   check_inst = options.get('burnin-check-instances', False)
261   do_rename = options.get('burnin-rename', '')
262   do_reboot = options.get('burnin-reboot', True)
263   reboot_types = options.get("reboot-types", constants.REBOOT_TYPES)
264
265   # Get as many instances as we need
266   instances = []
267   try:
268     try:
269       num = qa_config.get('options', {}).get('burnin-instances', 1)
270       for _ in range(0, num):
271         instances.append(qa_config.AcquireInstance())
272     except qa_error.OutOfInstancesError:
273       print "Not enough instances, continuing anyway."
274
275     if len(instances) < 1:
276       raise qa_error.Error("Burnin needs at least one instance")
277
278     script = qa_utils.UploadFile(master['primary'], '../tools/burnin')
279     try:
280       # Run burnin
281       cmd = [script,
282              '--os=%s' % qa_config.get('os'),
283              '--disk-size=%s' % ",".join(qa_config.get('disk')),
284              '--disk-growth=%s' % ",".join(qa_config.get('disk-growth')),
285              '--disk-template=%s' % disk_template]
286       if parallel:
287         cmd.append('--parallel')
288         cmd.append('--early-release')
289       if check_inst:
290         cmd.append('--http-check')
291       if do_rename:
292         cmd.append('--rename=%s' % do_rename)
293       if not do_reboot:
294         cmd.append('--no-reboot')
295       else:
296         cmd.append('--reboot-types=%s' % ",".join(reboot_types))
297       cmd += [inst['name'] for inst in instances]
298       AssertCommand(cmd)
299     finally:
300       AssertCommand(["rm", "-f", script])
301
302   finally:
303     for inst in instances:
304       qa_config.ReleaseInstance(inst)
305
306
307 def TestClusterMasterFailover():
308   """gnt-cluster master-failover"""
309   master = qa_config.GetMasterNode()
310   failovermaster = qa_config.AcquireNode(exclude=master)
311
312   cmd = ["gnt-cluster", "master-failover"]
313   try:
314     AssertCommand(cmd, node=failovermaster)
315     AssertCommand(cmd, node=master)
316   finally:
317     qa_config.ReleaseNode(failovermaster)
318
319
320 def TestClusterCopyfile():
321   """gnt-cluster copyfile"""
322   master = qa_config.GetMasterNode()
323
324   uniqueid = utils.NewUUID()
325
326   # Create temporary file
327   f = tempfile.NamedTemporaryFile()
328   f.write(uniqueid)
329   f.flush()
330   f.seek(0)
331
332   # Upload file to master node
333   testname = qa_utils.UploadFile(master['primary'], f.name)
334   try:
335     # Copy file to all nodes
336     AssertCommand(["gnt-cluster", "copyfile", testname])
337     _CheckFileOnAllNodes(testname, uniqueid)
338   finally:
339     _RemoveFileFromAllNodes(testname)
340
341
342 def TestClusterCommand():
343   """gnt-cluster command"""
344   uniqueid = utils.NewUUID()
345   rfile = "/tmp/gnt%s" % utils.NewUUID()
346   rcmd = utils.ShellQuoteArgs(['echo', '-n', uniqueid])
347   cmd = utils.ShellQuoteArgs(['gnt-cluster', 'command',
348                               "%s >%s" % (rcmd, rfile)])
349
350   try:
351     AssertCommand(cmd)
352     _CheckFileOnAllNodes(rfile, uniqueid)
353   finally:
354     _RemoveFileFromAllNodes(rfile)
355
356
357 def TestClusterDestroy():
358   """gnt-cluster destroy"""
359   AssertCommand(["gnt-cluster", "destroy", "--yes-do-it"])