Statistics
| Branch: | Tag: | Revision:

root / lib / utils / version.py @ 9b85ede9

History | View | Annotate | Download (5 kB)

1
#
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
import re
25

    
26
from ganeti import constants
27

    
28
_FULL_VERSION_RE = re.compile(r"(\d+)\.(\d+)\.(\d+)")
29
_SHORT_VERSION_RE = re.compile(r"(\d+)\.(\d+)")
30

    
31
# The first Ganeti version that supports automatic upgrades
32
FIRST_UPGRADE_VERSION = (2, 10, 0)
33

    
34
CURRENT_VERSION = (constants.VERSION_MAJOR, constants.VERSION_MINOR,
35
                   constants.VERSION_REVISION)
36

    
37
# Format for CONFIG_VERSION:
38
#   01 03 0123 = 01030123
39
#   ^^ ^^ ^^^^
40
#   |  |  + Configuration version/revision
41
#   |  + Minor version
42
#   + Major version
43
#
44
# It is stored as an integer. Make sure not to write an octal number.
45

    
46
# BuildVersion and SplitVersion must be in here because we can't import other
47
# modules. The cfgupgrade tool must be able to read and write version numbers
48
# and thus requires these functions. To avoid code duplication, they're kept in
49
# here.
50

    
51

    
52
def BuildVersion(major, minor, revision):
53
  """Calculates int version number from major, minor and revision numbers.
54

55
  Returns: int representing version number
56

57
  """
58
  assert isinstance(major, int)
59
  assert isinstance(minor, int)
60
  assert isinstance(revision, int)
61
  return (1000000 * major +
62
            10000 * minor +
63
                1 * revision)
64

    
65

    
66
def SplitVersion(version):
67
  """Splits version number stored in an int.
68

69
  Returns: tuple; (major, minor, revision)
70

71
  """
72
  assert isinstance(version, int)
73

    
74
  (major, remainder) = divmod(version, 1000000)
75
  (minor, revision) = divmod(remainder, 10000)
76

    
77
  return (major, minor, revision)
78

    
79

    
80
def ParseVersion(versionstring):
81
  """Parses a version string.
82

83
  @param versionstring: the version string to parse
84
  @type versionstring: string
85
  @rtype: tuple or None
86
  @return: (major, minor, revision) if parsable, None otherwise.
87

88
  """
89
  m = _FULL_VERSION_RE.match(versionstring)
90
  if m is not None:
91
    return (int(m.group(1)), int(m.group(2)), int(m.group(3)))
92

    
93
  m = _SHORT_VERSION_RE.match(versionstring)
94
  if m is not None:
95
    return (int(m.group(1)), int(m.group(2)), 0)
96

    
97
  return None
98

    
99

    
100
def UpgradeRange(target, current=CURRENT_VERSION):
101
  """Verify whether a version is within the range of automatic upgrades.
102

103
  @param target: The version to upgrade to as (major, minor, revision)
104
  @type target: tuple
105
  @param current: The version to upgrade from as (major, minor, revision)
106
  @type current: tuple
107
  @rtype: string or None
108
  @return: None, if within the range, and a human-readable error message
109
      otherwise
110

111
  """
112
  if target < FIRST_UPGRADE_VERSION or current < FIRST_UPGRADE_VERSION:
113
    return "automatic upgrades only supported from 2.10 onwards"
114

    
115
  if target[0] != current[0]:
116
    return "different major versions"
117

    
118
  if target[1] < current[1] - 1:
119
    return "can only downgrade one minor version at a time"
120

    
121
  return None
122

    
123

    
124
def ShouldCfgdowngrade(version, current=CURRENT_VERSION):
125
  """Decide whether cfgupgrade --downgrade should be called.
126

127
  Given the current version and the version to change to, decide
128
  if in the transition process cfgupgrade --downgrade should
129
  be called
130

131
  @param version: The version to upgrade to as (major, minor, revision)
132
  @type version: tuple
133
  @param current: The version to upgrade from as (major, minor, revision)
134
  @type current: tuple
135
  @rtype: bool
136
  @return: True, if cfgupgrade --downgrade should be called.
137

138
  """
139
  return version[0] == current[0] and version[1] == current[1] - 1
140

    
141

    
142
def IsCorrectConfigVersion(targetversion, configversion):
143
  """Decide whether configuration version is compatible with the target.
144

145
  @param targetversion: The version to upgrade to as (major, minor, revision)
146
  @type targetversion: tuple
147
  @param configversion: The version of the current configuration
148
  @type configversion: tuple
149
  @rtype: bool
150
  @return: True, if the configversion fits with the target version.
151

152
  """
153
  return (configversion[0] == targetversion[0] and
154
          configversion[1] == targetversion[1])
155

    
156

    
157
def IsBefore(version, major, minor, revision):
158
  """Decide if a given version is strictly before a given version.
159

160
  @param version: (major, minor, revision) or None, with None being
161
      before all versions
162
  @type version: (int, int, int) or None
163
  @param major: major version
164
  @type major: int
165
  @param minor: minor version
166
  @type minor: int
167
  @param revision: revision
168
  @type revision: int
169

170
  """
171
  if version is None:
172
    return True
173

    
174
  return version < (major, minor, revision)