Statistics
| Branch: | Tag: | Revision:

root / test / py / cfgupgrade_unittest.py @ fa166f67

History | View | Annotate | Download (15.2 kB)

1
#!/usr/bin/python
2
#
3

    
4
# Copyright (C) 2010, 2012, 2013 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
                downgrade=False):
42
  cmd = [sys.executable, "%s/tools/cfgupgrade" % testutils.GetSourceDir(),
43
         "--debug", "--force", "--path=%s" % path, "--confdir=%s" % path]
44

    
45
  if ignore_hostname:
46
    cmd.append("--ignore-hostname")
47
  if dry_run:
48
    cmd.append("--dry-run")
49
  if no_verify:
50
    cmd.append("--no-verify")
51
  if downgrade:
52
    cmd.append("--downgrade")
53

    
54
  result = utils.RunCmd(cmd, cwd=os.getcwd())
55
  if result.failed:
56
    raise Exception("cfgupgrade failed: %s, output %r" %
57
                    (result.fail_reason, result.output))
58

    
59

    
60
class TestCfgupgrade(unittest.TestCase):
61
  def setUp(self):
62
    self.tmpdir = tempfile.mkdtemp()
63

    
64
    self.config_path = utils.PathJoin(self.tmpdir, "config.data")
65
    self.noded_cert_path = utils.PathJoin(self.tmpdir, "server.pem")
66
    self.rapi_cert_path = utils.PathJoin(self.tmpdir, "rapi.pem")
67
    self.rapi_users_path = utils.PathJoin(self.tmpdir, "rapi", "users")
68
    self.rapi_users_path_pre24 = utils.PathJoin(self.tmpdir, "rapi_users")
69
    self.known_hosts_path = utils.PathJoin(self.tmpdir, "known_hosts")
70
    self.confd_hmac_path = utils.PathJoin(self.tmpdir, "hmac.key")
71
    self.cds_path = utils.PathJoin(self.tmpdir, "cluster-domain-secret")
72
    self.ss_master_node_path = utils.PathJoin(self.tmpdir, "ssconf_master_node")
73
    self.file_storage_paths = utils.PathJoin(self.tmpdir, "file-storage-paths")
74

    
75
  def tearDown(self):
76
    shutil.rmtree(self.tmpdir)
77

    
78
  def _LoadConfig(self):
79
    return serializer.LoadJson(utils.ReadFile(self.config_path))
80

    
81
  def _CreateValidConfigDir(self):
82
    utils.WriteFile(self.noded_cert_path, data="")
83
    utils.WriteFile(self.known_hosts_path, data="")
84
    utils.WriteFile(self.ss_master_node_path,
85
                    data="node.has.another.name.example.net")
86

    
87
  def testNoConfigDir(self):
88
    self.assertFalse(utils.ListVisibleFiles(self.tmpdir))
89
    self.assertRaises(Exception, _RunUpgrade, self.tmpdir, False, True)
90
    self.assertRaises(Exception, _RunUpgrade, self.tmpdir, True, True)
91

    
92
  def testWrongHostname(self):
93
    self._CreateValidConfigDir()
94

    
95
    utils.WriteFile(self.config_path, data=serializer.DumpJson({
96
      "version": constants.CONFIG_VERSION,
97
      "cluster": {},
98
      "instances": {},
99
      "nodegroups": {},
100
      }))
101

    
102
    hostname = netutils.GetHostname().name
103
    assert hostname != utils.ReadOneLineFile(self.ss_master_node_path)
104

    
105
    self.assertRaises(Exception, _RunUpgrade, self.tmpdir, False, True,
106
                      ignore_hostname=False)
107

    
108
  def testCorrectHostname(self):
109
    self._CreateValidConfigDir()
110

    
111
    utils.WriteFile(self.config_path, data=serializer.DumpJson({
112
      "version": constants.CONFIG_VERSION,
113
      "cluster": {},
114
      "instances": {},
115
      "nodegroups": {},
116
      }))
117

    
118
    utils.WriteFile(self.ss_master_node_path,
119
                    data="%s\n" % netutils.GetHostname().name)
120

    
121
    _RunUpgrade(self.tmpdir, False, True, ignore_hostname=False)
122

    
123
  def testInconsistentConfig(self):
124
    self._CreateValidConfigDir()
125
    # There should be no "config_version"
126
    cfg = {
127
      "version": 0,
128
      "cluster": {
129
        "config_version": 0,
130
        },
131
      "instances": {},
132
      "nodegroups": {},
133
      }
134
    utils.WriteFile(self.config_path, data=serializer.DumpJson(cfg))
135
    self.assertRaises(Exception, _RunUpgrade, self.tmpdir, False, True)
136

    
137
  def testInvalidConfig(self):
138
    self._CreateValidConfigDir()
139
    # Missing version from config
140
    utils.WriteFile(self.config_path, data=serializer.DumpJson({}))
141
    self.assertRaises(Exception, _RunUpgrade, self.tmpdir, False, True)
142

    
143
  def _TestSimpleUpgrade(self, from_version, dry_run,
144
                         file_storage_dir=None,
145
                         shared_file_storage_dir=None):
146
    cluster = {}
147

    
148
    if file_storage_dir:
149
      cluster["file_storage_dir"] = file_storage_dir
150
    if shared_file_storage_dir:
151
      cluster["shared_file_storage_dir"] = shared_file_storage_dir
152

    
153
    cfg = {
154
      "version": from_version,
155
      "cluster": cluster,
156
      "instances": {},
157
      "nodegroups": {},
158
      }
159
    self._TestUpgradeFromData(cfg, dry_run)
160

    
161
  def _TestUpgradeFromData(self, cfg, dry_run):
162
    assert "version" in cfg
163
    from_version = cfg["version"]
164
    self._CreateValidConfigDir()
165
    utils.WriteFile(self.config_path, data=serializer.DumpJson(cfg))
166

    
167
    self.assertFalse(os.path.isfile(self.rapi_cert_path))
168
    self.assertFalse(os.path.isfile(self.confd_hmac_path))
169
    self.assertFalse(os.path.isfile(self.cds_path))
170

    
171
    _RunUpgrade(self.tmpdir, dry_run, True)
172

    
173
    if dry_run:
174
      expversion = from_version
175
      checkfn = operator.not_
176
    else:
177
      expversion = constants.CONFIG_VERSION
178
      checkfn = operator.truth
179

    
180
    self.assert_(checkfn(os.path.isfile(self.rapi_cert_path)))
181
    self.assert_(checkfn(os.path.isfile(self.confd_hmac_path)))
182
    self.assert_(checkfn(os.path.isfile(self.cds_path)))
183

    
184
    newcfg = self._LoadConfig()
185
    self.assertEqual(newcfg["version"], expversion)
186

    
187
  def testRapiUsers(self):
188
    self.assertFalse(os.path.exists(self.rapi_users_path))
189
    self.assertFalse(os.path.exists(self.rapi_users_path_pre24))
190
    self.assertFalse(os.path.exists(os.path.dirname(self.rapi_users_path)))
191

    
192
    utils.WriteFile(self.rapi_users_path_pre24, data="some user\n")
193
    self._TestSimpleUpgrade(constants.BuildVersion(2, 3, 0), False)
194

    
195
    self.assertTrue(os.path.isdir(os.path.dirname(self.rapi_users_path)))
196
    self.assert_(os.path.islink(self.rapi_users_path_pre24))
197
    self.assert_(os.path.isfile(self.rapi_users_path))
198
    self.assertEqual(os.readlink(self.rapi_users_path_pre24),
199
                     self.rapi_users_path)
200
    for path in [self.rapi_users_path, self.rapi_users_path_pre24]:
201
      self.assertEqual(utils.ReadFile(path), "some user\n")
202

    
203
  def testRapiUsers24AndAbove(self):
204
    self.assertFalse(os.path.exists(self.rapi_users_path))
205
    self.assertFalse(os.path.exists(self.rapi_users_path_pre24))
206

    
207
    os.mkdir(os.path.dirname(self.rapi_users_path))
208
    utils.WriteFile(self.rapi_users_path, data="other user\n")
209
    self._TestSimpleUpgrade(constants.BuildVersion(2, 3, 0), False)
210

    
211
    self.assert_(os.path.islink(self.rapi_users_path_pre24))
212
    self.assert_(os.path.isfile(self.rapi_users_path))
213
    self.assertEqual(os.readlink(self.rapi_users_path_pre24),
214
                     self.rapi_users_path)
215
    for path in [self.rapi_users_path, self.rapi_users_path_pre24]:
216
      self.assertEqual(utils.ReadFile(path), "other user\n")
217

    
218
  def testRapiUsersExistingSymlink(self):
219
    self.assertFalse(os.path.exists(self.rapi_users_path))
220
    self.assertFalse(os.path.exists(self.rapi_users_path_pre24))
221

    
222
    os.mkdir(os.path.dirname(self.rapi_users_path))
223
    os.symlink(self.rapi_users_path, self.rapi_users_path_pre24)
224
    utils.WriteFile(self.rapi_users_path, data="hello world\n")
225

    
226
    self._TestSimpleUpgrade(constants.BuildVersion(2, 2, 0), False)
227

    
228
    self.assert_(os.path.isfile(self.rapi_users_path) and
229
                 not os.path.islink(self.rapi_users_path))
230
    self.assert_(os.path.islink(self.rapi_users_path_pre24))
231
    self.assertEqual(os.readlink(self.rapi_users_path_pre24),
232
                     self.rapi_users_path)
233
    for path in [self.rapi_users_path, self.rapi_users_path_pre24]:
234
      self.assertEqual(utils.ReadFile(path), "hello world\n")
235

    
236
  def testRapiUsersExistingTarget(self):
237
    self.assertFalse(os.path.exists(self.rapi_users_path))
238
    self.assertFalse(os.path.exists(self.rapi_users_path_pre24))
239

    
240
    os.mkdir(os.path.dirname(self.rapi_users_path))
241
    utils.WriteFile(self.rapi_users_path, data="other user\n")
242
    utils.WriteFile(self.rapi_users_path_pre24, data="hello world\n")
243

    
244
    self.assertRaises(Exception, self._TestSimpleUpgrade,
245
                      constants.BuildVersion(2, 2, 0), False)
246

    
247
    for path in [self.rapi_users_path, self.rapi_users_path_pre24]:
248
      self.assert_(os.path.isfile(path) and not os.path.islink(path))
249
    self.assertEqual(utils.ReadFile(self.rapi_users_path), "other user\n")
250
    self.assertEqual(utils.ReadFile(self.rapi_users_path_pre24),
251
                     "hello world\n")
252

    
253
  def testRapiUsersDryRun(self):
254
    self.assertFalse(os.path.exists(self.rapi_users_path))
255
    self.assertFalse(os.path.exists(self.rapi_users_path_pre24))
256

    
257
    utils.WriteFile(self.rapi_users_path_pre24, data="some user\n")
258
    self._TestSimpleUpgrade(constants.BuildVersion(2, 3, 0), True)
259

    
260
    self.assertFalse(os.path.isdir(os.path.dirname(self.rapi_users_path)))
261
    self.assertTrue(os.path.isfile(self.rapi_users_path_pre24) and
262
                    not os.path.islink(self.rapi_users_path_pre24))
263
    self.assertFalse(os.path.exists(self.rapi_users_path))
264

    
265
  def testRapiUsers24AndAboveDryRun(self):
266
    self.assertFalse(os.path.exists(self.rapi_users_path))
267
    self.assertFalse(os.path.exists(self.rapi_users_path_pre24))
268

    
269
    os.mkdir(os.path.dirname(self.rapi_users_path))
270
    utils.WriteFile(self.rapi_users_path, data="other user\n")
271
    self._TestSimpleUpgrade(constants.BuildVersion(2, 3, 0), True)
272

    
273
    self.assertTrue(os.path.isfile(self.rapi_users_path) and
274
                    not os.path.islink(self.rapi_users_path))
275
    self.assertFalse(os.path.exists(self.rapi_users_path_pre24))
276
    self.assertEqual(utils.ReadFile(self.rapi_users_path), "other user\n")
277

    
278
  def testRapiUsersExistingSymlinkDryRun(self):
279
    self.assertFalse(os.path.exists(self.rapi_users_path))
280
    self.assertFalse(os.path.exists(self.rapi_users_path_pre24))
281

    
282
    os.mkdir(os.path.dirname(self.rapi_users_path))
283
    os.symlink(self.rapi_users_path, self.rapi_users_path_pre24)
284
    utils.WriteFile(self.rapi_users_path, data="hello world\n")
285

    
286
    self._TestSimpleUpgrade(constants.BuildVersion(2, 2, 0), True)
287

    
288
    self.assertTrue(os.path.islink(self.rapi_users_path_pre24))
289
    self.assertTrue(os.path.isfile(self.rapi_users_path) and
290
                    not os.path.islink(self.rapi_users_path))
291
    self.assertEqual(os.readlink(self.rapi_users_path_pre24),
292
                     self.rapi_users_path)
293
    for path in [self.rapi_users_path, self.rapi_users_path_pre24]:
294
      self.assertEqual(utils.ReadFile(path), "hello world\n")
295

    
296
  def testFileStoragePathsDryRun(self):
297
    self.assertFalse(os.path.exists(self.file_storage_paths))
298

    
299
    self._TestSimpleUpgrade(constants.BuildVersion(2, 6, 0), True,
300
                            file_storage_dir=self.tmpdir,
301
                            shared_file_storage_dir="/tmp")
302

    
303
    self.assertFalse(os.path.exists(self.file_storage_paths))
304

    
305
  def testFileStoragePathsBoth(self):
306
    self.assertFalse(os.path.exists(self.file_storage_paths))
307

    
308
    self._TestSimpleUpgrade(constants.BuildVersion(2, 6, 0), False,
309
                            file_storage_dir=self.tmpdir,
310
                            shared_file_storage_dir="/tmp")
311

    
312
    lines = utils.ReadFile(self.file_storage_paths).splitlines()
313
    self.assertTrue(lines.pop(0).startswith("# "))
314
    self.assertTrue(lines.pop(0).startswith("# cfgupgrade"))
315
    self.assertEqual(lines.pop(0), self.tmpdir)
316
    self.assertEqual(lines.pop(0), "/tmp")
317
    self.assertFalse(lines)
318
    self.assertEqual(os.stat(self.file_storage_paths).st_mode & 0777,
319
                     0600, msg="Wrong permissions")
320

    
321
  def testFileStoragePathsSharedOnly(self):
322
    self.assertFalse(os.path.exists(self.file_storage_paths))
323

    
324
    self._TestSimpleUpgrade(constants.BuildVersion(2, 5, 0), False,
325
                            file_storage_dir=None,
326
                            shared_file_storage_dir=self.tmpdir)
327

    
328
    lines = utils.ReadFile(self.file_storage_paths).splitlines()
329
    self.assertTrue(lines.pop(0).startswith("# "))
330
    self.assertTrue(lines.pop(0).startswith("# cfgupgrade"))
331
    self.assertEqual(lines.pop(0), self.tmpdir)
332
    self.assertFalse(lines)
333

    
334
  def testUpgradeFrom_2_0(self):
335
    self._TestSimpleUpgrade(constants.BuildVersion(2, 0, 0), False)
336

    
337
  def testUpgradeFrom_2_1(self):
338
    self._TestSimpleUpgrade(constants.BuildVersion(2, 1, 0), False)
339

    
340
  def testUpgradeFrom_2_2(self):
341
    self._TestSimpleUpgrade(constants.BuildVersion(2, 2, 0), False)
342

    
343
  def testUpgradeFrom_2_3(self):
344
    self._TestSimpleUpgrade(constants.BuildVersion(2, 3, 0), False)
345

    
346
  def testUpgradeFrom_2_4(self):
347
    self._TestSimpleUpgrade(constants.BuildVersion(2, 4, 0), False)
348

    
349
  def testUpgradeFrom_2_5(self):
350
    self._TestSimpleUpgrade(constants.BuildVersion(2, 5, 0), False)
351

    
352
  def testUpgradeFrom_2_6(self):
353
    self._TestSimpleUpgrade(constants.BuildVersion(2, 6, 0), False)
354

    
355
  def testUpgradeCurrent(self):
356
    self._TestSimpleUpgrade(constants.CONFIG_VERSION, False)
357

    
358
  def _RunDowngradeUpgrade(self):
359
    oldconf = self._LoadConfig()
360
    _RunUpgrade(self.tmpdir, False, True, downgrade=True)
361
    _RunUpgrade(self.tmpdir, False, True)
362
    newconf = self._LoadConfig()
363
    self.assertEqual(oldconf, newconf)
364

    
365
  def testDowngrade(self):
366
    self._TestSimpleUpgrade(constants.CONFIG_VERSION, False)
367
    self._RunDowngradeUpgrade()
368

    
369
  def _RunDowngradeTwice(self):
370
    """Make sure that downgrade is idempotent."""
371
    _RunUpgrade(self.tmpdir, False, True, downgrade=True)
372
    oldconf = self._LoadConfig()
373
    _RunUpgrade(self.tmpdir, False, True, downgrade=True)
374
    newconf = self._LoadConfig()
375
    self.assertEqual(oldconf, newconf)
376

    
377
  def testDowngradeTwice(self):
378
    self._TestSimpleUpgrade(constants.CONFIG_VERSION, False)
379
    self._RunDowngradeTwice()
380

    
381
  def testUpgradeDryRunFrom_2_0(self):
382
    self._TestSimpleUpgrade(constants.BuildVersion(2, 0, 0), True)
383

    
384
  def testUpgradeDryRunFrom_2_1(self):
385
    self._TestSimpleUpgrade(constants.BuildVersion(2, 1, 0), True)
386

    
387
  def testUpgradeDryRunFrom_2_2(self):
388
    self._TestSimpleUpgrade(constants.BuildVersion(2, 2, 0), True)
389

    
390
  def testUpgradeDryRunFrom_2_3(self):
391
    self._TestSimpleUpgrade(constants.BuildVersion(2, 3, 0), True)
392

    
393
  def testUpgradeDryRunFrom_2_4(self):
394
    self._TestSimpleUpgrade(constants.BuildVersion(2, 4, 0), True)
395

    
396
  def testUpgradeDryRunFrom_2_5(self):
397
    self._TestSimpleUpgrade(constants.BuildVersion(2, 5, 0), True)
398

    
399
  def testUpgradeDryRunFrom_2_6(self):
400
    self._TestSimpleUpgrade(constants.BuildVersion(2, 6, 0), True)
401

    
402
  def testUpgradeCurrentDryRun(self):
403
    self._TestSimpleUpgrade(constants.CONFIG_VERSION, True)
404

    
405
  def testDowngradeDryRun(self):
406
    self._TestSimpleUpgrade(constants.CONFIG_VERSION, False)
407
    oldconf = self._LoadConfig()
408
    _RunUpgrade(self.tmpdir, True, True, downgrade=True)
409
    newconf = self._LoadConfig()
410
    self.assertEqual(oldconf["version"], newconf["version"])
411

    
412
if __name__ == "__main__":
413
  testutils.GanetiTestProgram()