Locking related fixes for networks
[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       "nodegroups": {},
97       }))
98
99     hostname = netutils.GetHostname().name
100     assert hostname != utils.ReadOneLineFile(self.ss_master_node_path)
101
102     self.assertRaises(Exception, _RunUpgrade, self.tmpdir, False, True,
103                       ignore_hostname=False)
104
105   def testCorrectHostname(self):
106     self._CreateValidConfigDir()
107
108     utils.WriteFile(self.config_path, data=serializer.DumpJson({
109       "version": constants.CONFIG_VERSION,
110       "cluster": {},
111       "instances": {},
112       "nodegroups": {},
113       }))
114
115     utils.WriteFile(self.ss_master_node_path,
116                     data="%s\n" % netutils.GetHostname().name)
117
118     _RunUpgrade(self.tmpdir, False, True, ignore_hostname=False)
119
120   def testInconsistentConfig(self):
121     self._CreateValidConfigDir()
122     # There should be no "config_version"
123     cfg = {
124       "version": 0,
125       "cluster": {
126         "config_version": 0,
127         },
128       "instances": {},
129       "nodegroups": {},
130       }
131     utils.WriteFile(self.config_path, data=serializer.DumpJson(cfg))
132     self.assertRaises(Exception, _RunUpgrade, self.tmpdir, False, True)
133
134   def testInvalidConfig(self):
135     self._CreateValidConfigDir()
136     # Missing version from config
137     utils.WriteFile(self.config_path, data=serializer.DumpJson({}))
138     self.assertRaises(Exception, _RunUpgrade, self.tmpdir, False, True)
139
140   def _TestSimpleUpgrade(self, from_version, dry_run,
141                          file_storage_dir=None,
142                          shared_file_storage_dir=None):
143     cluster = {}
144
145     if file_storage_dir:
146       cluster["file_storage_dir"] = file_storage_dir
147     if shared_file_storage_dir:
148       cluster["shared_file_storage_dir"] = shared_file_storage_dir
149
150     cfg = {
151       "version": from_version,
152       "cluster": cluster,
153       "instances": {},
154       "nodegroups": {},
155       }
156     self._CreateValidConfigDir()
157     utils.WriteFile(self.config_path, data=serializer.DumpJson(cfg))
158
159     self.assertFalse(os.path.isfile(self.rapi_cert_path))
160     self.assertFalse(os.path.isfile(self.confd_hmac_path))
161     self.assertFalse(os.path.isfile(self.cds_path))
162
163     _RunUpgrade(self.tmpdir, dry_run, True)
164
165     if dry_run:
166       expversion = from_version
167       checkfn = operator.not_
168     else:
169       expversion = constants.CONFIG_VERSION
170       checkfn = operator.truth
171
172     self.assert_(checkfn(os.path.isfile(self.rapi_cert_path)))
173     self.assert_(checkfn(os.path.isfile(self.confd_hmac_path)))
174     self.assert_(checkfn(os.path.isfile(self.cds_path)))
175
176     newcfg = self._LoadConfig()
177     self.assertEqual(newcfg["version"], expversion)
178
179   def testRapiUsers(self):
180     self.assertFalse(os.path.exists(self.rapi_users_path))
181     self.assertFalse(os.path.exists(self.rapi_users_path_pre24))
182     self.assertFalse(os.path.exists(os.path.dirname(self.rapi_users_path)))
183
184     utils.WriteFile(self.rapi_users_path_pre24, data="some user\n")
185     self._TestSimpleUpgrade(constants.BuildVersion(2, 3, 0), False)
186
187     self.assertTrue(os.path.isdir(os.path.dirname(self.rapi_users_path)))
188     self.assert_(os.path.islink(self.rapi_users_path_pre24))
189     self.assert_(os.path.isfile(self.rapi_users_path))
190     self.assertEqual(os.readlink(self.rapi_users_path_pre24),
191                      self.rapi_users_path)
192     for path in [self.rapi_users_path, self.rapi_users_path_pre24]:
193       self.assertEqual(utils.ReadFile(path), "some user\n")
194
195   def testRapiUsers24AndAbove(self):
196     self.assertFalse(os.path.exists(self.rapi_users_path))
197     self.assertFalse(os.path.exists(self.rapi_users_path_pre24))
198
199     os.mkdir(os.path.dirname(self.rapi_users_path))
200     utils.WriteFile(self.rapi_users_path, data="other user\n")
201     self._TestSimpleUpgrade(constants.BuildVersion(2, 3, 0), False)
202
203     self.assert_(os.path.islink(self.rapi_users_path_pre24))
204     self.assert_(os.path.isfile(self.rapi_users_path))
205     self.assertEqual(os.readlink(self.rapi_users_path_pre24),
206                      self.rapi_users_path)
207     for path in [self.rapi_users_path, self.rapi_users_path_pre24]:
208       self.assertEqual(utils.ReadFile(path), "other user\n")
209
210   def testRapiUsersExistingSymlink(self):
211     self.assertFalse(os.path.exists(self.rapi_users_path))
212     self.assertFalse(os.path.exists(self.rapi_users_path_pre24))
213
214     os.mkdir(os.path.dirname(self.rapi_users_path))
215     os.symlink(self.rapi_users_path, self.rapi_users_path_pre24)
216     utils.WriteFile(self.rapi_users_path, data="hello world\n")
217
218     self._TestSimpleUpgrade(constants.BuildVersion(2, 2, 0), False)
219
220     self.assert_(os.path.isfile(self.rapi_users_path) and
221                  not os.path.islink(self.rapi_users_path))
222     self.assert_(os.path.islink(self.rapi_users_path_pre24))
223     self.assertEqual(os.readlink(self.rapi_users_path_pre24),
224                      self.rapi_users_path)
225     for path in [self.rapi_users_path, self.rapi_users_path_pre24]:
226       self.assertEqual(utils.ReadFile(path), "hello world\n")
227
228   def testRapiUsersExistingTarget(self):
229     self.assertFalse(os.path.exists(self.rapi_users_path))
230     self.assertFalse(os.path.exists(self.rapi_users_path_pre24))
231
232     os.mkdir(os.path.dirname(self.rapi_users_path))
233     utils.WriteFile(self.rapi_users_path, data="other user\n")
234     utils.WriteFile(self.rapi_users_path_pre24, data="hello world\n")
235
236     self.assertRaises(Exception, self._TestSimpleUpgrade,
237                       constants.BuildVersion(2, 2, 0), False)
238
239     for path in [self.rapi_users_path, self.rapi_users_path_pre24]:
240       self.assert_(os.path.isfile(path) and not os.path.islink(path))
241     self.assertEqual(utils.ReadFile(self.rapi_users_path), "other user\n")
242     self.assertEqual(utils.ReadFile(self.rapi_users_path_pre24),
243                      "hello world\n")
244
245   def testRapiUsersDryRun(self):
246     self.assertFalse(os.path.exists(self.rapi_users_path))
247     self.assertFalse(os.path.exists(self.rapi_users_path_pre24))
248
249     utils.WriteFile(self.rapi_users_path_pre24, data="some user\n")
250     self._TestSimpleUpgrade(constants.BuildVersion(2, 3, 0), True)
251
252     self.assertFalse(os.path.isdir(os.path.dirname(self.rapi_users_path)))
253     self.assertTrue(os.path.isfile(self.rapi_users_path_pre24) and
254                     not os.path.islink(self.rapi_users_path_pre24))
255     self.assertFalse(os.path.exists(self.rapi_users_path))
256
257   def testRapiUsers24AndAboveDryRun(self):
258     self.assertFalse(os.path.exists(self.rapi_users_path))
259     self.assertFalse(os.path.exists(self.rapi_users_path_pre24))
260
261     os.mkdir(os.path.dirname(self.rapi_users_path))
262     utils.WriteFile(self.rapi_users_path, data="other user\n")
263     self._TestSimpleUpgrade(constants.BuildVersion(2, 3, 0), True)
264
265     self.assertTrue(os.path.isfile(self.rapi_users_path) and
266                     not os.path.islink(self.rapi_users_path))
267     self.assertFalse(os.path.exists(self.rapi_users_path_pre24))
268     self.assertEqual(utils.ReadFile(self.rapi_users_path), "other user\n")
269
270   def testRapiUsersExistingSymlinkDryRun(self):
271     self.assertFalse(os.path.exists(self.rapi_users_path))
272     self.assertFalse(os.path.exists(self.rapi_users_path_pre24))
273
274     os.mkdir(os.path.dirname(self.rapi_users_path))
275     os.symlink(self.rapi_users_path, self.rapi_users_path_pre24)
276     utils.WriteFile(self.rapi_users_path, data="hello world\n")
277
278     self._TestSimpleUpgrade(constants.BuildVersion(2, 2, 0), True)
279
280     self.assertTrue(os.path.islink(self.rapi_users_path_pre24))
281     self.assertTrue(os.path.isfile(self.rapi_users_path) and
282                     not os.path.islink(self.rapi_users_path))
283     self.assertEqual(os.readlink(self.rapi_users_path_pre24),
284                      self.rapi_users_path)
285     for path in [self.rapi_users_path, self.rapi_users_path_pre24]:
286       self.assertEqual(utils.ReadFile(path), "hello world\n")
287
288   def testFileStoragePathsDryRun(self):
289     self.assertFalse(os.path.exists(self.file_storage_paths))
290
291     self._TestSimpleUpgrade(constants.BuildVersion(2, 6, 0), True,
292                             file_storage_dir=self.tmpdir,
293                             shared_file_storage_dir="/tmp")
294
295     self.assertFalse(os.path.exists(self.file_storage_paths))
296
297   def testFileStoragePathsBoth(self):
298     self.assertFalse(os.path.exists(self.file_storage_paths))
299
300     self._TestSimpleUpgrade(constants.BuildVersion(2, 6, 0), False,
301                             file_storage_dir=self.tmpdir,
302                             shared_file_storage_dir="/tmp")
303
304     lines = utils.ReadFile(self.file_storage_paths).splitlines()
305     self.assertTrue(lines.pop(0).startswith("# "))
306     self.assertTrue(lines.pop(0).startswith("# cfgupgrade"))
307     self.assertEqual(lines.pop(0), self.tmpdir)
308     self.assertEqual(lines.pop(0), "/tmp")
309     self.assertFalse(lines)
310     self.assertEqual(os.stat(self.file_storage_paths).st_mode & 0777,
311                      0600, msg="Wrong permissions")
312
313   def testFileStoragePathsSharedOnly(self):
314     self.assertFalse(os.path.exists(self.file_storage_paths))
315
316     self._TestSimpleUpgrade(constants.BuildVersion(2, 5, 0), False,
317                             file_storage_dir=None,
318                             shared_file_storage_dir=self.tmpdir)
319
320     lines = utils.ReadFile(self.file_storage_paths).splitlines()
321     self.assertTrue(lines.pop(0).startswith("# "))
322     self.assertTrue(lines.pop(0).startswith("# cfgupgrade"))
323     self.assertEqual(lines.pop(0), self.tmpdir)
324     self.assertFalse(lines)
325
326   def testUpgradeFrom_2_0(self):
327     self._TestSimpleUpgrade(constants.BuildVersion(2, 0, 0), False)
328
329   def testUpgradeFrom_2_1(self):
330     self._TestSimpleUpgrade(constants.BuildVersion(2, 1, 0), False)
331
332   def testUpgradeFrom_2_2(self):
333     self._TestSimpleUpgrade(constants.BuildVersion(2, 2, 0), False)
334
335   def testUpgradeFrom_2_3(self):
336     self._TestSimpleUpgrade(constants.BuildVersion(2, 3, 0), False)
337
338   def testUpgradeFrom_2_4(self):
339     self._TestSimpleUpgrade(constants.BuildVersion(2, 4, 0), False)
340
341   def testUpgradeFrom_2_5(self):
342     self._TestSimpleUpgrade(constants.BuildVersion(2, 5, 0), False)
343
344   def testUpgradeFrom_2_6(self):
345     self._TestSimpleUpgrade(constants.BuildVersion(2, 6, 0), False)
346
347   def testUpgradeCurrent(self):
348     self._TestSimpleUpgrade(constants.CONFIG_VERSION, False)
349
350   def testUpgradeDryRunFrom_2_0(self):
351     self._TestSimpleUpgrade(constants.BuildVersion(2, 0, 0), True)
352
353   def testUpgradeDryRunFrom_2_1(self):
354     self._TestSimpleUpgrade(constants.BuildVersion(2, 1, 0), True)
355
356   def testUpgradeDryRunFrom_2_2(self):
357     self._TestSimpleUpgrade(constants.BuildVersion(2, 2, 0), True)
358
359   def testUpgradeDryRunFrom_2_3(self):
360     self._TestSimpleUpgrade(constants.BuildVersion(2, 3, 0), True)
361
362   def testUpgradeDryRunFrom_2_4(self):
363     self._TestSimpleUpgrade(constants.BuildVersion(2, 4, 0), True)
364
365   def testUpgradeDryRunFrom_2_5(self):
366     self._TestSimpleUpgrade(constants.BuildVersion(2, 5, 0), True)
367
368   def testUpgradeDryRunFrom_2_6(self):
369     self._TestSimpleUpgrade(constants.BuildVersion(2, 6, 0), True)
370
371   def testUpgradeCurrentDryRun(self):
372     self._TestSimpleUpgrade(constants.CONFIG_VERSION, True)
373
374
375 if __name__ == "__main__":
376   testutils.GanetiTestProgram()