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