Revision effc1b86

b/Makefile.am
483 483
	lib/utils/retry.py \
484 484
	lib/utils/storage.py \
485 485
	lib/utils/text.py \
486
	lib/utils/version.py \
486 487
	lib/utils/wrapper.py \
487 488
	lib/utils/x509.py
488 489

  
b/lib/constants.py
44 44
EXPORT_VERSION = 0
45 45
RAPI_VERSION = 2
46 46

  
47

  
48
# Format for CONFIG_VERSION:
49
#   01 03 0123 = 01030123
50
#   ^^ ^^ ^^^^
51
#   |  |  + Configuration version/revision
52
#   |  + Minor version
53
#   + Major version
54
#
55
# It is stored as an integer. Make sure not to write an octal number.
56

  
57
# BuildVersion and SplitVersion must be in here because we can't import other
58
# modules. The cfgupgrade tool must be able to read and write version numbers
59
# and thus requires these functions. To avoid code duplication, they're kept in
60
# here.
61

  
62
def BuildVersion(major, minor, revision):
63
  """Calculates int version number from major, minor and revision numbers.
64

  
65
  Returns: int representing version number
66

  
67
  """
68
  assert isinstance(major, int)
69
  assert isinstance(minor, int)
70
  assert isinstance(revision, int)
71
  return (1000000 * major +
72
            10000 * minor +
73
                1 * revision)
74

  
75

  
76
def SplitVersion(version):
77
  """Splits version number stored in an int.
78

  
79
  Returns: tuple; (major, minor, revision)
80

  
81
  """
82
  assert isinstance(version, int)
83

  
84
  (major, remainder) = divmod(version, 1000000)
85
  (minor, revision) = divmod(remainder, 10000)
86

  
87
  return (major, minor, revision)
88

  
89

  
90 47
CONFIG_MAJOR = _constants.CONFIG_MAJOR
91 48
CONFIG_MINOR = _constants.CONFIG_MINOR
92 49
CONFIG_REVISION = _constants.CONFIG_REVISION
b/lib/server/masterd.py
61 61
from ganeti import pathutils
62 62
from ganeti import ht
63 63

  
64
from ganeti.utils import version
65

  
64 66

  
65 67
CLIENT_REQUEST_WORKERS = 16
66 68

  
......
90 92
    client_ops = ClientOps(server)
91 93

  
92 94
    try:
93
      (method, args, version) = luxi.ParseRequest(message)
95
      (method, args, ver) = luxi.ParseRequest(message)
94 96
    except luxi.ProtocolError, err:
95 97
      logging.error("Protocol Error: %s", err)
96 98
      client.close_log()
......
99 101
    success = False
100 102
    try:
101 103
      # Verify client's version if there was one in the request
102
      if version is not None and version != constants.LUXI_VERSION:
104
      if ver is not None and ver != constants.LUXI_VERSION:
103 105
        raise errors.LuxiError("LUXI version mismatch, server %s, request %s" %
104
                               (constants.LUXI_VERSION, version))
106
                               (constants.LUXI_VERSION, ver))
105 107

  
106 108
      result = client_ops.handle_request(method, args)
107 109
      success = True
......
685 687
  try:
686 688
    config.ConfigWriter()
687 689
  except errors.ConfigVersionMismatch, err:
688
    v1 = "%s.%s.%s" % constants.SplitVersion(err.args[0])
689
    v2 = "%s.%s.%s" % constants.SplitVersion(err.args[1])
690
    v1 = "%s.%s.%s" % version.SplitVersion(err.args[0])
691
    v2 = "%s.%s.%s" % version.SplitVersion(err.args[1])
690 692
    print >> sys.stderr,  \
691 693
        ("Configuration version mismatch. The current Ganeti software"
692 694
         " expects version %s, but the on-disk configuration file has"
b/lib/utils/version.py
1
#!/usr/bin/python
2
#
3

  
4
# Copyright (C) 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
"""Version utilities."""
23

  
24

  
25
# Format for CONFIG_VERSION:
26
#   01 03 0123 = 01030123
27
#   ^^ ^^ ^^^^
28
#   |  |  + Configuration version/revision
29
#   |  + Minor version
30
#   + Major version
31
#
32
# It is stored as an integer. Make sure not to write an octal number.
33

  
34
# BuildVersion and SplitVersion must be in here because we can't import other
35
# modules. The cfgupgrade tool must be able to read and write version numbers
36
# and thus requires these functions. To avoid code duplication, they're kept in
37
# here.
38

  
39
def BuildVersion(major, minor, revision):
40
  """Calculates int version number from major, minor and revision numbers.
41

  
42
  Returns: int representing version number
43

  
44
  """
45
  assert isinstance(major, int)
46
  assert isinstance(minor, int)
47
  assert isinstance(revision, int)
48
  return (1000000 * major +
49
            10000 * minor +
50
                1 * revision)
51

  
52

  
53
def SplitVersion(version):
54
  """Splits version number stored in an int.
55

  
56
  Returns: tuple; (major, minor, revision)
57

  
58
  """
59
  assert isinstance(version, int)
60

  
61
  (major, remainder) = divmod(version, 1000000)
62
  (minor, revision) = divmod(remainder, 10000)
63

  
64
  return (major, minor, revision)
b/test/py/cfgupgrade_unittest.py
34 34
from ganeti import serializer
35 35
from ganeti import netutils
36 36

  
37
from ganeti.utils import version
38

  
37 39
import testutils
38 40

  
39 41

  
......
199 201
    self.assertFalse(os.path.exists(os.path.dirname(self.rapi_users_path)))
200 202

  
201 203
    utils.WriteFile(self.rapi_users_path_pre24, data="some user\n")
202
    self._TestSimpleUpgrade(constants.BuildVersion(2, 3, 0), False)
204
    self._TestSimpleUpgrade(version.BuildVersion(2, 3, 0), False)
203 205

  
204 206
    self.assertTrue(os.path.isdir(os.path.dirname(self.rapi_users_path)))
205 207
    self.assert_(os.path.islink(self.rapi_users_path_pre24))
......
215 217

  
216 218
    os.mkdir(os.path.dirname(self.rapi_users_path))
217 219
    utils.WriteFile(self.rapi_users_path, data="other user\n")
218
    self._TestSimpleUpgrade(constants.BuildVersion(2, 3, 0), False)
220
    self._TestSimpleUpgrade(version.BuildVersion(2, 3, 0), False)
219 221

  
220 222
    self.assert_(os.path.islink(self.rapi_users_path_pre24))
221 223
    self.assert_(os.path.isfile(self.rapi_users_path))
......
232 234
    os.symlink(self.rapi_users_path, self.rapi_users_path_pre24)
233 235
    utils.WriteFile(self.rapi_users_path, data="hello world\n")
234 236

  
235
    self._TestSimpleUpgrade(constants.BuildVersion(2, 2, 0), False)
237
    self._TestSimpleUpgrade(version.BuildVersion(2, 2, 0), False)
236 238

  
237 239
    self.assert_(os.path.isfile(self.rapi_users_path) and
238 240
                 not os.path.islink(self.rapi_users_path))
......
251 253
    utils.WriteFile(self.rapi_users_path_pre24, data="hello world\n")
252 254

  
253 255
    self.assertRaises(Exception, self._TestSimpleUpgrade,
254
                      constants.BuildVersion(2, 2, 0), False)
256
                      version.BuildVersion(2, 2, 0), False)
255 257

  
256 258
    for path in [self.rapi_users_path, self.rapi_users_path_pre24]:
257 259
      self.assert_(os.path.isfile(path) and not os.path.islink(path))
......
264 266
    self.assertFalse(os.path.exists(self.rapi_users_path_pre24))
265 267

  
266 268
    utils.WriteFile(self.rapi_users_path_pre24, data="some user\n")
267
    self._TestSimpleUpgrade(constants.BuildVersion(2, 3, 0), True)
269
    self._TestSimpleUpgrade(version.BuildVersion(2, 3, 0), True)
268 270

  
269 271
    self.assertFalse(os.path.isdir(os.path.dirname(self.rapi_users_path)))
270 272
    self.assertTrue(os.path.isfile(self.rapi_users_path_pre24) and
......
277 279

  
278 280
    os.mkdir(os.path.dirname(self.rapi_users_path))
279 281
    utils.WriteFile(self.rapi_users_path, data="other user\n")
280
    self._TestSimpleUpgrade(constants.BuildVersion(2, 3, 0), True)
282
    self._TestSimpleUpgrade(version.BuildVersion(2, 3, 0), True)
281 283

  
282 284
    self.assertTrue(os.path.isfile(self.rapi_users_path) and
283 285
                    not os.path.islink(self.rapi_users_path))
......
292 294
    os.symlink(self.rapi_users_path, self.rapi_users_path_pre24)
293 295
    utils.WriteFile(self.rapi_users_path, data="hello world\n")
294 296

  
295
    self._TestSimpleUpgrade(constants.BuildVersion(2, 2, 0), True)
297
    self._TestSimpleUpgrade(version.BuildVersion(2, 2, 0), True)
296 298

  
297 299
    self.assertTrue(os.path.islink(self.rapi_users_path_pre24))
298 300
    self.assertTrue(os.path.isfile(self.rapi_users_path) and
......
305 307
  def testFileStoragePathsDryRun(self):
306 308
    self.assertFalse(os.path.exists(self.file_storage_paths))
307 309

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

  
......
314 316
  def testFileStoragePathsBoth(self):
315 317
    self.assertFalse(os.path.exists(self.file_storage_paths))
316 318

  
317
    self._TestSimpleUpgrade(constants.BuildVersion(2, 6, 0), False,
319
    self._TestSimpleUpgrade(version.BuildVersion(2, 6, 0), False,
318 320
                            file_storage_dir=self.tmpdir,
319 321
                            shared_file_storage_dir="/tmp")
320 322

  
......
330 332
  def testFileStoragePathsSharedOnly(self):
331 333
    self.assertFalse(os.path.exists(self.file_storage_paths))
332 334

  
333
    self._TestSimpleUpgrade(constants.BuildVersion(2, 5, 0), False,
335
    self._TestSimpleUpgrade(version.BuildVersion(2, 5, 0), False,
334 336
                            file_storage_dir=None,
335 337
                            shared_file_storage_dir=self.tmpdir)
336 338

  
......
341 343
    self.assertFalse(lines)
342 344

  
343 345
  def testUpgradeFrom_2_0(self):
344
    self._TestSimpleUpgrade(constants.BuildVersion(2, 0, 0), False)
346
    self._TestSimpleUpgrade(version.BuildVersion(2, 0, 0), False)
345 347

  
346 348
  def testUpgradeFrom_2_1(self):
347
    self._TestSimpleUpgrade(constants.BuildVersion(2, 1, 0), False)
349
    self._TestSimpleUpgrade(version.BuildVersion(2, 1, 0), False)
348 350

  
349 351
  def testUpgradeFrom_2_2(self):
350
    self._TestSimpleUpgrade(constants.BuildVersion(2, 2, 0), False)
352
    self._TestSimpleUpgrade(version.BuildVersion(2, 2, 0), False)
351 353

  
352 354
  def testUpgradeFrom_2_3(self):
353
    self._TestSimpleUpgrade(constants.BuildVersion(2, 3, 0), False)
355
    self._TestSimpleUpgrade(version.BuildVersion(2, 3, 0), False)
354 356

  
355 357
  def testUpgradeFrom_2_4(self):
356
    self._TestSimpleUpgrade(constants.BuildVersion(2, 4, 0), False)
358
    self._TestSimpleUpgrade(version.BuildVersion(2, 4, 0), False)
357 359

  
358 360
  def testUpgradeFrom_2_5(self):
359
    self._TestSimpleUpgrade(constants.BuildVersion(2, 5, 0), False)
361
    self._TestSimpleUpgrade(version.BuildVersion(2, 5, 0), False)
360 362

  
361 363
  def testUpgradeFrom_2_6(self):
362
    self._TestSimpleUpgrade(constants.BuildVersion(2, 6, 0), False)
364
    self._TestSimpleUpgrade(version.BuildVersion(2, 6, 0), False)
363 365

  
364 366
  def testUpgradeFrom_2_7(self):
365
    self._TestSimpleUpgrade(constants.BuildVersion(2, 7, 0), False)
367
    self._TestSimpleUpgrade(version.BuildVersion(2, 7, 0), False)
366 368

  
367 369
  def testUpgradeFullConfigFrom_2_7(self):
368 370
    self._TestUpgradeFromFile("cluster_config_2.7.json", False)
......
431 433
    self._RunDowngradeTwice()
432 434

  
433 435
  def testUpgradeDryRunFrom_2_0(self):
434
    self._TestSimpleUpgrade(constants.BuildVersion(2, 0, 0), True)
436
    self._TestSimpleUpgrade(version.BuildVersion(2, 0, 0), True)
435 437

  
436 438
  def testUpgradeDryRunFrom_2_1(self):
437
    self._TestSimpleUpgrade(constants.BuildVersion(2, 1, 0), True)
439
    self._TestSimpleUpgrade(version.BuildVersion(2, 1, 0), True)
438 440

  
439 441
  def testUpgradeDryRunFrom_2_2(self):
440
    self._TestSimpleUpgrade(constants.BuildVersion(2, 2, 0), True)
442
    self._TestSimpleUpgrade(version.BuildVersion(2, 2, 0), True)
441 443

  
442 444
  def testUpgradeDryRunFrom_2_3(self):
443
    self._TestSimpleUpgrade(constants.BuildVersion(2, 3, 0), True)
445
    self._TestSimpleUpgrade(version.BuildVersion(2, 3, 0), True)
444 446

  
445 447
  def testUpgradeDryRunFrom_2_4(self):
446
    self._TestSimpleUpgrade(constants.BuildVersion(2, 4, 0), True)
448
    self._TestSimpleUpgrade(version.BuildVersion(2, 4, 0), True)
447 449

  
448 450
  def testUpgradeDryRunFrom_2_5(self):
449
    self._TestSimpleUpgrade(constants.BuildVersion(2, 5, 0), True)
451
    self._TestSimpleUpgrade(version.BuildVersion(2, 5, 0), True)
450 452

  
451 453
  def testUpgradeDryRunFrom_2_6(self):
452
    self._TestSimpleUpgrade(constants.BuildVersion(2, 6, 0), True)
454
    self._TestSimpleUpgrade(version.BuildVersion(2, 6, 0), True)
453 455

  
454 456
  def testUpgradeCurrentDryRun(self):
455 457
    self._TestSimpleUpgrade(constants.CONFIG_VERSION, True)
b/test/py/ganeti.constants_unittest.py
30 30
from ganeti import locking
31 31
from ganeti import utils
32 32

  
33
from ganeti.utils import version
34

  
33 35
import testutils
34 36

  
35 37

  
......
46 48
    self.failUnless(constants.CONFIG_VERSION >= 0 and
47 49
                    constants.CONFIG_VERSION <= 99999999)
48 50

  
49
    self.failUnless(constants.BuildVersion(0, 0, 0) == 0)
50
    self.failUnless(constants.BuildVersion(10, 10, 1010) == 10101010)
51
    self.failUnless(constants.BuildVersion(12, 34, 5678) == 12345678)
52
    self.failUnless(constants.BuildVersion(99, 99, 9999) == 99999999)
51
    self.failUnless(version.BuildVersion(0, 0, 0) == 0)
52
    self.failUnless(version.BuildVersion(10, 10, 1010) == 10101010)
53
    self.failUnless(version.BuildVersion(12, 34, 5678) == 12345678)
54
    self.failUnless(version.BuildVersion(99, 99, 9999) == 99999999)
53 55

  
54
    self.failUnless(constants.SplitVersion(00000000) == (0, 0, 0))
55
    self.failUnless(constants.SplitVersion(10101010) == (10, 10, 1010))
56
    self.failUnless(constants.SplitVersion(12345678) == (12, 34, 5678))
57
    self.failUnless(constants.SplitVersion(99999999) == (99, 99, 9999))
58
    self.failUnless(constants.SplitVersion(constants.CONFIG_VERSION) ==
56
    self.failUnless(version.SplitVersion(00000000) == (0, 0, 0))
57
    self.failUnless(version.SplitVersion(10101010) == (10, 10, 1010))
58
    self.failUnless(version.SplitVersion(12345678) == (12, 34, 5678))
59
    self.failUnless(version.SplitVersion(99999999) == (99, 99, 9999))
60
    self.failUnless(version.SplitVersion(constants.CONFIG_VERSION) ==
59 61
                    (constants.CONFIG_MAJOR, constants.CONFIG_MINOR,
60 62
                     constants.CONFIG_REVISION))
61 63

  
b/tools/cfgupgrade
44 44
from ganeti import netutils
45 45
from ganeti import pathutils
46 46

  
47
from ganeti.utils import version
48

  
47 49

  
48 50
options = None
49 51
args = None
......
347 349

  
348 350

  
349 351
def UpgradeAll(config_data):
350
  config_data["version"] = constants.BuildVersion(TARGET_MAJOR,
351
                                                  TARGET_MINOR, 0)
352
  config_data["version"] = version.BuildVersion(TARGET_MAJOR, TARGET_MINOR, 0)
352 353
  UpgradeRapiUsers()
353 354
  UpgradeWatcher()
354 355
  UpgradeFileStoragePaths(config_data)
......
379 380
def DowngradeAll(config_data):
380 381
  # Any code specific to a particular version should be labeled that way, so
381 382
  # it can be removed when updating to the next version.
382
  config_data["version"] = constants.BuildVersion(DOWNGRADE_MAJOR,
383
                                                  DOWNGRADE_MINOR, 0)
383
  config_data["version"] = version.BuildVersion(DOWNGRADE_MAJOR,
384
                                                DOWNGRADE_MINOR, 0)
384 385
  DowngradeInstances(config_data)
385 386

  
386 387

  
......
482 483
    raise Error("Unable to determine configuration version")
483 484

  
484 485
  (config_major, config_minor, config_revision) = \
485
    constants.SplitVersion(config_version)
486
    version.SplitVersion(config_version)
486 487

  
487 488
  logging.info("Found configuration version %s (%d.%d.%d)",
488 489
               config_version, config_major, config_minor, config_revision)
b/tools/cfgupgrade12
49 49
from ganeti import cli
50 50
from ganeti import pathutils
51 51

  
52
from ganeti.utils import version
53

  
52 54

  
53 55
options = None
54 56
args = None
......
345 347
      raise Error("Unsupported configuration version: %s" %
346 348
                  old_config_version)
347 349
    if "version" not in config_data:
348
      config_data["version"] = constants.BuildVersion(2, 0, 0)
350
      config_data["version"] = version.BuildVersion(2, 0, 0)
349 351
    if F_SERIAL not in config_data:
350 352
      config_data[F_SERIAL] = 1
351 353

  

Also available in: Unified diff