workerpool: Preserve task number when deferring
[ganeti-local] / test / cfgupgrade_unittest.py
1 #!/usr/bin/python
2 #
3
4 # Copyright (C) 2010, 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
22 """Script for testing tools/cfgupgrade"""
23
24 import os
25 import sys
26 import unittest
27 import shutil
28 import tempfile
29 import operator
30
31 from ganeti import constants
32 from ganeti import utils
33 from ganeti import errors
34 from ganeti import serializer
35 from ganeti import netutils
36
37 import testutils
38
39
40 def _RunUpgrade(path, dry_run, no_verify, ignore_hostname=True):
41   cmd = [sys.executable, "%s/tools/cfgupgrade" % testutils.GetSourceDir(),
42          "--debug", "--force", "--path=%s" % path, "--confdir=%s" % path]
43
44   if ignore_hostname:
45     cmd.append("--ignore-hostname")
46   if dry_run:
47     cmd.append("--dry-run")
48   if no_verify:
49     cmd.append("--no-verify")
50
51   result = utils.RunCmd(cmd, cwd=os.getcwd())
52   if result.failed:
53     raise Exception("cfgupgrade failed: %s, output %r" %
54                     (result.fail_reason, result.output))
55
56
57 class TestCfgupgrade(unittest.TestCase):
58   def setUp(self):
59     self.tmpdir = tempfile.mkdtemp()
60
61     self.config_path = utils.PathJoin(self.tmpdir, "config.data")
62     self.noded_cert_path = utils.PathJoin(self.tmpdir, "server.pem")
63     self.rapi_cert_path = utils.PathJoin(self.tmpdir, "rapi.pem")
64     self.rapi_users_path = utils.PathJoin(self.tmpdir, "rapi", "users")
65     self.rapi_users_path_pre24 = utils.PathJoin(self.tmpdir, "rapi_users")
66     self.known_hosts_path = utils.PathJoin(self.tmpdir, "known_hosts")
67     self.confd_hmac_path = utils.PathJoin(self.tmpdir, "hmac.key")
68     self.cds_path = utils.PathJoin(self.tmpdir, "cluster-domain-secret")
69     self.ss_master_node_path = utils.PathJoin(self.tmpdir, "ssconf_master_node")
70     self.file_storage_paths = utils.PathJoin(self.tmpdir, "file-storage-paths")
71
72   def tearDown(self):
73     shutil.rmtree(self.tmpdir)
74
75   def _LoadConfig(self):
76     return serializer.LoadJson(utils.ReadFile(self.config_path))
77
78   def _CreateValidConfigDir(self):
79     utils.WriteFile(self.noded_cert_path, data="")
80     utils.WriteFile(self.known_hosts_path, data="")
81     utils.WriteFile(self.ss_master_node_path,
82                     data="node.has.another.name.example.net")
83
84   def testNoConfigDir(self):
85     self.assertFalse(utils.ListVisibleFiles(self.tmpdir))
86     self.assertRaises(Exception, _RunUpgrade, self.tmpdir, False, True)
87     self.assertRaises(Exception, _RunUpgrade, self.tmpdir, True, True)
88
89   def testWrongHostname(self):
90     self._CreateValidConfigDir()
91
92     utils.WriteFile(self.config_path, data=serializer.DumpJson({
93       "version": constants.CONFIG_VERSION,
94       "cluster": {},
95       "instances": {},
96       }))
97
98     hostname = netutils.GetHostname().name
99     assert hostname != utils.ReadOneLineFile(self.ss_master_node_path)
100
101     self.assertRaises(Exception, _RunUpgrade, self.tmpdir, False, True,
102                       ignore_hostname=False)
103
104   def testCorrectHostname(self):
105     self._CreateValidConfigDir()
106
107     utils.WriteFile(self.config_path, data=serializer.DumpJson({
108       "version": constants.CONFIG_VERSION,
109       "cluster": {},
110       "instances": {},
111       }))
112
113     utils.WriteFile(self.ss_master_node_path,
114                     data="%s\n" % netutils.GetHostname().name)
115
116     _RunUpgrade(self.tmpdir, False, True, ignore_hostname=False)
117
118   def testInconsistentConfig(self):
119     self._CreateValidConfigDir()
120     # There should be no "config_version"
121     cfg = {
122       "version": 0,
123       "cluster": {
124         "config_version": 0,
125         },
126       "instances": {},
127       }
128     utils.WriteFile(self.config_path, data=serializer.DumpJson(cfg))
129     self.assertRaises(Exception, _RunUpgrade, self.tmpdir, False, True)
130
131   def testInvalidConfig(self):
132     self._CreateValidConfigDir()
133     # Missing version from config
134     utils.WriteFile(self.config_path, data=serializer.DumpJson({}))
135     self.assertRaises(Exception, _RunUpgrade, self.tmpdir, False, True)
136
137   def _TestSimpleUpgrade(self, from_version, dry_run,
138                          file_storage_dir=None,
139                          shared_file_storage_dir=None):
140     cluster = {}
141
142     if file_storage_dir:
143       cluster["file_storage_dir"] = file_storage_dir
144     if shared_file_storage_dir:
145       cluster["shared_file_storage_dir"] = shared_file_storage_dir
146
147     cfg = {
148       "version": from_version,
149       "cluster": cluster,
150       "instances": {},
151       }
152     self._CreateValidConfigDir()
153     utils.WriteFile(self.config_path, data=serializer.DumpJson(cfg))
154
155     self.assertFalse(os.path.isfile(self.rapi_cert_path))
156     self.assertFalse(os.path.isfile(self.confd_hmac_path))
157     self.assertFalse(os.path.isfile(self.cds_path))
158
159     _RunUpgrade(self.tmpdir, dry_run, True)
160
161     if dry_run:
162       expversion = from_version
163       checkfn = operator.not_
164     else:
165       expversion = constants.CONFIG_VERSION
166       checkfn = operator.truth
167
168     self.assert_(checkfn(os.path.isfile(self.rapi_cert_path)))
169     self.assert_(checkfn(os.path.isfile(self.confd_hmac_path)))
170     self.assert_(checkfn(os.path.isfile(self.cds_path)))
171
172     newcfg = self._LoadConfig()
173     self.assertEqual(newcfg["version"], expversion)
174
175   def testRapiUsers(self):
176     self.assertFalse(os.path.exists(self.rapi_users_path))
177     self.assertFalse(os.path.exists(self.rapi_users_path_pre24))
178     self.assertFalse(os.path.exists(os.path.dirname(self.rapi_users_path)))
179
180     utils.WriteFile(self.rapi_users_path_pre24, data="some user\n")
181     self._TestSimpleUpgrade(constants.BuildVersion(2, 3, 0), False)
182
183     self.assertTrue(os.path.isdir(os.path.dirname(self.rapi_users_path)))
184     self.assert_(os.path.islink(self.rapi_users_path_pre24))
185     self.assert_(os.path.isfile(self.rapi_users_path))
186     self.assertEqual(os.readlink(self.rapi_users_path_pre24),
187                      self.rapi_users_path)
188     for path in [self.rapi_users_path, self.rapi_users_path_pre24]:
189       self.assertEqual(utils.ReadFile(path), "some user\n")
190
191   def testRapiUsers24AndAbove(self):
192     self.assertFalse(os.path.exists(self.rapi_users_path))
193     self.assertFalse(os.path.exists(self.rapi_users_path_pre24))
194
195     os.mkdir(os.path.dirname(self.rapi_users_path))
196     utils.WriteFile(self.rapi_users_path, data="other user\n")
197     self._TestSimpleUpgrade(constants.BuildVersion(2, 3, 0), False)
198
199     self.assert_(os.path.islink(self.rapi_users_path_pre24))
200     self.assert_(os.path.isfile(self.rapi_users_path))
201     self.assertEqual(os.readlink(self.rapi_users_path_pre24),
202                      self.rapi_users_path)
203     for path in [self.rapi_users_path, self.rapi_users_path_pre24]:
204       self.assertEqual(utils.ReadFile(path), "other user\n")
205
206   def testRapiUsersExistingSymlink(self):
207     self.assertFalse(os.path.exists(self.rapi_users_path))
208     self.assertFalse(os.path.exists(self.rapi_users_path_pre24))
209
210     os.mkdir(os.path.dirname(self.rapi_users_path))
211     os.symlink(self.rapi_users_path, self.rapi_users_path_pre24)
212     utils.WriteFile(self.rapi_users_path, data="hello world\n")
213
214     self._TestSimpleUpgrade(constants.BuildVersion(2, 2, 0), False)
215
216     self.assert_(os.path.isfile(self.rapi_users_path) and
217                  not os.path.islink(self.rapi_users_path))
218     self.assert_(os.path.islink(self.rapi_users_path_pre24))
219     self.assertEqual(os.readlink(self.rapi_users_path_pre24),
220                      self.rapi_users_path)
221     for path in [self.rapi_users_path, self.rapi_users_path_pre24]:
222       self.assertEqual(utils.ReadFile(path), "hello world\n")
223
224   def testRapiUsersExistingTarget(self):
225     self.assertFalse(os.path.exists(self.rapi_users_path))
226     self.assertFalse(os.path.exists(self.rapi_users_path_pre24))
227
228     os.mkdir(os.path.dirname(self.rapi_users_path))
229     utils.WriteFile(self.rapi_users_path, data="other user\n")
230     utils.WriteFile(self.rapi_users_path_pre24, data="hello world\n")
231
232     self.assertRaises(Exception, self._TestSimpleUpgrade,
233                       constants.BuildVersion(2, 2, 0), False)
234
235     for path in [self.rapi_users_path, self.rapi_users_path_pre24]:
236       self.assert_(os.path.isfile(path) and not os.path.islink(path))
237     self.assertEqual(utils.ReadFile(self.rapi_users_path), "other user\n")
238     self.assertEqual(utils.ReadFile(self.rapi_users_path_pre24),
239                      "hello world\n")
240
241   def testRapiUsersDryRun(self):
242     self.assertFalse(os.path.exists(self.rapi_users_path))
243     self.assertFalse(os.path.exists(self.rapi_users_path_pre24))
244
245     utils.WriteFile(self.rapi_users_path_pre24, data="some user\n")
246     self._TestSimpleUpgrade(constants.BuildVersion(2, 3, 0), True)
247
248     self.assertFalse(os.path.isdir(os.path.dirname(self.rapi_users_path)))
249     self.assertTrue(os.path.isfile(self.rapi_users_path_pre24) and
250                     not os.path.islink(self.rapi_users_path_pre24))
251     self.assertFalse(os.path.exists(self.rapi_users_path))
252
253   def testRapiUsers24AndAboveDryRun(self):
254     self.assertFalse(os.path.exists(self.rapi_users_path))
255     self.assertFalse(os.path.exists(self.rapi_users_path_pre24))
256
257     os.mkdir(os.path.dirname(self.rapi_users_path))
258     utils.WriteFile(self.rapi_users_path, data="other user\n")
259     self._TestSimpleUpgrade(constants.BuildVersion(2, 3, 0), True)
260
261     self.assertTrue(os.path.isfile(self.rapi_users_path) and
262                     not os.path.islink(self.rapi_users_path))
263     self.assertFalse(os.path.exists(self.rapi_users_path_pre24))
264     self.assertEqual(utils.ReadFile(self.rapi_users_path), "other user\n")
265
266   def testRapiUsersExistingSymlinkDryRun(self):
267     self.assertFalse(os.path.exists(self.rapi_users_path))
268     self.assertFalse(os.path.exists(self.rapi_users_path_pre24))
269
270     os.mkdir(os.path.dirname(self.rapi_users_path))
271     os.symlink(self.rapi_users_path, self.rapi_users_path_pre24)
272     utils.WriteFile(self.rapi_users_path, data="hello world\n")
273
274     self._TestSimpleUpgrade(constants.BuildVersion(2, 2, 0), True)
275
276     self.assertTrue(os.path.islink(self.rapi_users_path_pre24))
277     self.assertTrue(os.path.isfile(self.rapi_users_path) and
278                     not os.path.islink(self.rapi_users_path))
279     self.assertEqual(os.readlink(self.rapi_users_path_pre24),
280                      self.rapi_users_path)
281     for path in [self.rapi_users_path, self.rapi_users_path_pre24]:
282       self.assertEqual(utils.ReadFile(path), "hello world\n")
283
284   def testFileStoragePathsDryRun(self):
285     self.assertFalse(os.path.exists(self.file_storage_paths))
286
287     self._TestSimpleUpgrade(constants.BuildVersion(2, 6, 0), True,
288                             file_storage_dir=self.tmpdir,
289                             shared_file_storage_dir="/tmp")
290
291     self.assertFalse(os.path.exists(self.file_storage_paths))
292
293   def testFileStoragePathsBoth(self):
294     self.assertFalse(os.path.exists(self.file_storage_paths))
295
296     self._TestSimpleUpgrade(constants.BuildVersion(2, 6, 0), False,
297                             file_storage_dir=self.tmpdir,
298                             shared_file_storage_dir="/tmp")
299
300     lines = utils.ReadFile(self.file_storage_paths).splitlines()
301     self.assertTrue(lines.pop(0).startswith("# "))
302     self.assertTrue(lines.pop(0).startswith("# cfgupgrade"))
303     self.assertEqual(lines.pop(0), self.tmpdir)
304     self.assertEqual(lines.pop(0), "/tmp")
305     self.assertFalse(lines)
306     self.assertEqual(os.stat(self.file_storage_paths).st_mode & 0777,
307                      0600, msg="Wrong permissions")
308
309   def testFileStoragePathsSharedOnly(self):
310     self.assertFalse(os.path.exists(self.file_storage_paths))
311
312     self._TestSimpleUpgrade(constants.BuildVersion(2, 5, 0), False,
313                             file_storage_dir=None,
314                             shared_file_storage_dir=self.tmpdir)
315
316     lines = utils.ReadFile(self.file_storage_paths).splitlines()
317     self.assertTrue(lines.pop(0).startswith("# "))
318     self.assertTrue(lines.pop(0).startswith("# cfgupgrade"))
319     self.assertEqual(lines.pop(0), self.tmpdir)
320     self.assertFalse(lines)
321
322   def testUpgradeFrom_2_0(self):
323     self._TestSimpleUpgrade(constants.BuildVersion(2, 0, 0), False)
324
325   def testUpgradeFrom_2_1(self):
326     self._TestSimpleUpgrade(constants.BuildVersion(2, 1, 0), False)
327
328   def testUpgradeFrom_2_2(self):
329     self._TestSimpleUpgrade(constants.BuildVersion(2, 2, 0), False)
330
331   def testUpgradeFrom_2_3(self):
332     self._TestSimpleUpgrade(constants.BuildVersion(2, 3, 0), False)
333
334   def testUpgradeFrom_2_4(self):
335     self._TestSimpleUpgrade(constants.BuildVersion(2, 4, 0), False)
336
337   def testUpgradeFrom_2_5(self):
338     self._TestSimpleUpgrade(constants.BuildVersion(2, 5, 0), False)
339
340   def testUpgradeFrom_2_6(self):
341     self._TestSimpleUpgrade(constants.BuildVersion(2, 6, 0), False)
342
343   def testUpgradeCurrent(self):
344     self._TestSimpleUpgrade(constants.CONFIG_VERSION, False)
345
346   def testUpgradeDryRunFrom_2_0(self):
347     self._TestSimpleUpgrade(constants.BuildVersion(2, 0, 0), True)
348
349   def testUpgradeDryRunFrom_2_1(self):
350     self._TestSimpleUpgrade(constants.BuildVersion(2, 1, 0), True)
351
352   def testUpgradeDryRunFrom_2_2(self):
353     self._TestSimpleUpgrade(constants.BuildVersion(2, 2, 0), True)
354
355   def testUpgradeDryRunFrom_2_3(self):
356     self._TestSimpleUpgrade(constants.BuildVersion(2, 3, 0), True)
357
358   def testUpgradeDryRunFrom_2_4(self):
359     self._TestSimpleUpgrade(constants.BuildVersion(2, 4, 0), True)
360
361   def testUpgradeDryRunFrom_2_5(self):
362     self._TestSimpleUpgrade(constants.BuildVersion(2, 5, 0), True)
363
364   def testUpgradeDryRunFrom_2_6(self):
365     self._TestSimpleUpgrade(constants.BuildVersion(2, 6, 0), True)
366
367   def testUpgradeCurrentDryRun(self):
368     self._TestSimpleUpgrade(constants.CONFIG_VERSION, True)
369
370
371 if __name__ == "__main__":
372   testutils.GanetiTestProgram()