/usr/lib/python3/dist-packages/provisioningserver/utils/version.py is in python3-maas-provisioningserver 2.4.0~beta2-6865-gec43e47e6-0ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 | # Copyright 2015-2017 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Version utilities."""
__all__ = [
"get_maas_doc_version",
"get_maas_version_subversion",
"get_maas_version_ui",
"MAASVersion",
]
from collections import namedtuple
from functools import lru_cache
import re
from provisioningserver.logger import get_maas_logger
from provisioningserver.utils import (
shell,
snappy,
)
maaslog = get_maas_logger('version')
DEFAULT_VERSION = "2.3.0"
# Only import apt_pkg and initialize when not running in a snap.
if not snappy.running_in_snap():
import apt_pkg
apt_pkg.init()
# Name of maas package to get version from.
REGION_PACKAGE_NAME = "maas-region-api"
RACK_PACKAGE_NAME = "maas-rack-controller"
def get_version_from_apt(*packages):
"""Return the version output from `apt_pkg.Cache` for the given package(s),
or log an error message if the package data is not valid."""
try:
cache = apt_pkg.Cache(None)
except SystemError:
maaslog.error(
'Installed version could not be determined. Ensure '
'/var/lib/dpkg/status is valid.')
return ""
version = None
for package in packages:
if package in cache:
apt_package = cache[package]
version = apt_package.current_ver
# If the version is None or an empty string, try the next package.
if not version:
continue
break
return version.ver_str if version is not None else ""
def extract_version_subversion(version):
"""Return a tuple (version, subversion) from the given apt version."""
main_version, subversion = re.split('[+|-]', version, 1)
return main_version, subversion
def get_maas_repo_hash():
"""Return the Git hash for this running MAAS.
:return: A string if MAAS is running from a git working tree, else `None`.
"""
try:
return shell.call_and_check(['git', 'rev-parse', 'HEAD']).decode(
'ascii').strip()
except shell.ExternalProcessError:
# We may not be in a git repository, or any manner of other errors. For
# the purposes of this function we don't care; simply say we don't
# know.
return None
except FileNotFoundError:
# Git is not installed. We don't care and simply say we don't know.
return None
def get_maas_version_track_channel():
"""Returns the track/channel where a snap of this version can be found"""
version = get_maas_version()
if version:
# If running from the snap or the package.
series, _ = extract_version_subversion(version)
else:
# If running from source, we simply get the default version.
series = DEFAULT_VERSION
# If the version is a devel version, then we always assume we can
# get the snap from the latest edge channel; else, we return
# the stable channel for such series.
if 'alpha' in series or 'beta' in series or 'rc' in series:
return "latest/edge"
else:
# XXX - The snap store doesn't make it easy to create tracks
# for projects. As such, MAAS will continue to use the latest
# stable channel for the snap publishing regardless of the
# version. As such, use the stable channel instead. This needs
# to be reverted once tracks are easily supported by the store.
# return "%s/stable" % '.'.join(series.split('.')[0:2])
return "latest/stable"
MAASVersion = namedtuple('MAASVersion', (
'major',
'minor',
'point',
'qualifier_type_version',
'qualifier_version',
'revno',
'git_rev',
'short_version',
'extended_info',
'qualifier_type',
'is_snap',
))
def _coerce_to_int(string: str) -> int:
"""Strips all non-numeric characters out of the string and returns an int.
Returns 0 for an empty string.
"""
numbers = re.sub(r'[^\d]+', '', string)
if len(numbers) > 0:
return int(numbers)
else:
return 0
def get_version_tuple(maas_version: str) -> MAASVersion:
version_parts = maas_version.split('-', 1)
short_version = version_parts[0]
major_minor_point = re.sub(r'~.*', '', short_version).split('.')
for i in range(3):
try:
major_minor_point[i] = _coerce_to_int(major_minor_point[i])
except ValueError:
major_minor_point[i] = 0
except IndexError:
major_minor_point.append(0)
major, minor, point = major_minor_point
extended_info = ''
if len(version_parts) > 1:
extended_info = version_parts[1]
qualifier_type = None
qualifier_type_version = 0
qualifier_version = 0
if '~' in short_version:
# Parse the alpha/beta/rc version.
base_version, qualifier = short_version.split('~', 2)
qualifier_types = {
"rc": -1,
"beta": -2,
"alpha": -3
}
# A release build won't have a qualifier, so its version should be
# greater than releases qualified with alpha/beta/rc revisions.
qualifier_type = re.sub(r'[\d]+', '', qualifier)
qualifier_version = _coerce_to_int(qualifier)
qualifier_type_version = qualifier_types.get(qualifier_type, 0)
revno = 0
git_rev = ''
# If we find a '-g', that means the extended info indicates a git revision.
if '-g' in extended_info:
revno, git_rev = extended_info.split('-')[0:2]
# Strip any non-numeric characters from the revno, just in case.
revno = _coerce_to_int(revno)
# Remove anything that doesn't look like a hexadecimal character.
git_rev = re.sub(r'[^0-9a-f]+', '', git_rev)
is_snap = maas_version.endswith('-snap')
extended_info = re.sub(r'-*snap$', '', extended_info)
# Remove unnecessary garbage from the extended info string.
if '-' in extended_info:
extended_info = '-'.join(extended_info.split('-')[0:2])
return MAASVersion(
major, minor, point, qualifier_type_version, qualifier_version,
revno, git_rev, short_version, extended_info, qualifier_type, is_snap)
@lru_cache(maxsize=1)
def get_maas_version():
"""Return the apt or snap version for the main MAAS package."""
if snappy.running_in_snap():
return snappy.get_snap_version()
else:
return get_version_from_apt(RACK_PACKAGE_NAME, REGION_PACKAGE_NAME)
@lru_cache(maxsize=1)
def get_maas_version_subversion():
"""Return a tuple with the MAAS version and the MAAS subversion."""
version = get_maas_version()
if version:
return extract_version_subversion(version)
else:
# Get the branch information
commit_hash = get_maas_repo_hash()
if commit_hash is None:
# Not installed or not in repo, then no way to identify. This
# should not happen, but just in case.
return DEFAULT_VERSION, "unknown"
else:
return "%s from source" % DEFAULT_VERSION, "git+%s" % commit_hash
@lru_cache(maxsize=1)
def get_maas_version_ui():
"""Return the version string for the running MAAS region.
The returned string is suitable to display in the UI.
"""
version, subversion = get_maas_version_subversion()
return "%s (%s)" % (version, subversion) if subversion else version
@lru_cache(maxsize=1)
def get_maas_version_user_agent():
"""Return the version string for the running MAAS region.
The returned string is suitable to set the user agent.
"""
version, subversion = get_maas_version_subversion()
return "maas/%s/%s" % (version, subversion)
@lru_cache(maxsize=1)
def get_maas_doc_version():
"""Return the doc version for the running MAAS region."""
apt_version = get_maas_version()
if apt_version:
version, _ = extract_version_subversion(apt_version)
return '.'.join(version.split('~')[0].split('.')[:2])
else:
return ''
def get_maas_version_tuple():
"""Returns a tuple of the MAAS version without the svn rev."""
return tuple(int(x) for x in DEFAULT_VERSION.split('.'))
|