version.py 4.5 KB
Newer Older
Dmitry Volodin's avatar
Dmitry Volodin committed
1
2
3
4
5
6
7
8
9
10
11
12
13
# -*- coding: utf-8 -*-
# ---------------------------------------------------------------------
# NOC components versions
# ---------------------------------------------------------------------
# Copyright (C) 2007-2017 The NOC Project
# See LICENSE for details
# ---------------------------------------------------------------------

# Python modules
import os
import sys
import subprocess
import platform
Dmitry Volodin's avatar
Dmitry Volodin committed
14

Dmitry Volodin's avatar
Dmitry Volodin committed
15
16
17
18
# NOC modules
from noc.config import config

CHANGESET_LEN = 8
19
BRAND_PATH = config.get_customized_paths("BRAND", prefer_custom=True)
Dmitry Volodin's avatar
Dmitry Volodin committed
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


class cachedproperty(object):
    def __init__(self, f):
        self.f = f
        self.n = "_%s" % f.__name__
        self.__doc__ = f.__doc__

    def __get__(self, instance, owner):
        if instance is None:
            return self
        v = getattr(instance, self.n, None)
        if v is None:
            v = self.f(instance)
            setattr(instance, self.n, v)
        return v


class Version(object):
    @cachedproperty
    def has_git(self):
        """
        Check .git directory is exists and git executable is in $PATH
        :return:
        """
        if os.path.exists(".git"):
            with open(os.devnull, "w") as null:
                return subprocess.call(["which", "git"], stdout=null) == 0
        return False

    @cachedproperty
    def branch(self):
        """
        Returns current branch
        :return:
        """
        if self.has_git:
Dmitry Volodin's avatar
Dmitry Volodin committed
57
            return subprocess.check_output(["git", "rev-parse", "--abbrev-ref", "HEAD"]).strip()
Dmitry Volodin's avatar
Dmitry Volodin committed
58
59
60
61
62
63
64
65
66
67
        else:
            return ""

    @cachedproperty
    def changeset(self):
        """
        Returns current changeset
        :return:
        """
        if self.has_git:
Dmitry Volodin's avatar
Dmitry Volodin committed
68
            return subprocess.check_output(["git", "rev-parse", "HEAD"])[:CHANGESET_LEN]
Dmitry Volodin's avatar
Dmitry Volodin committed
69
70
71
72
73
74
        else:
            return ""

    @cachedproperty
    def version(self):
        if self.has_git:
Dmitry Volodin's avatar
Dmitry Volodin committed
75
76
77
            v = subprocess.check_output(
                ["git", "describe", "--tags", "--abbrev=%d" % CHANGESET_LEN]
            )
Dmitry Volodin's avatar
Dmitry Volodin committed
78
            if "-" not in v:
79
                return v.strip()
Dmitry Volodin's avatar
Dmitry Volodin committed
80
81
            r = v.rsplit("-", 2)
            if len(r) < 3:
82
                return v.strip()
Dmitry Volodin's avatar
Dmitry Volodin committed
83
            v, n, cs = r
Dmitry Volodin's avatar
Dmitry Volodin committed
84
            return "%s+%s.%s.%s" % (v, self.branch, n, cs[1 : CHANGESET_LEN + 1])
Dmitry Volodin's avatar
Dmitry Volodin committed
85
86
87
88
89
90
91
        else:
            # Productive, get version from VERSION file
            with open("VERSION") as f:
                return f.read().strip()

    @cachedproperty
    def brand(self):
92
93
94
95
96
97
        for p in BRAND_PATH:
            if os.path.exists(p):
                with open(p) as f:
                    return f.read().strip()
            else:
                return config.brand
Dmitry Volodin's avatar
Dmitry Volodin committed
98
99
100
101
102
103
104
105
106
107
108
109
110

    @cachedproperty
    def os_version(self):
        return " ".join(os.uname())

    @cachedproperty
    def os_brand(self):
        o = os.uname()[0].lower()
        if o == "linux":
            # os-release
            if os.path.exists("/etc/os-release"):
                vdata = {}
                with open("/etc/os-release") as f:
Dmitry Volodin's avatar
Dmitry Volodin committed
111
112
                    for line in f:
                        if "=" not in line:
Dmitry Volodin's avatar
Dmitry Volodin committed
113
                            continue
Dmitry Volodin's avatar
Dmitry Volodin committed
114
115
                        line = line.strip()
                        k, v = line.split("=", 1)
Dmitry Volodin's avatar
Dmitry Volodin committed
116
                        if v.startswith('"') and v.endswith('"'):
Dmitry Volodin's avatar
Dmitry Volodin committed
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
                            v = v[1:-1]
                        vdata[k] = v
                return "%s %s" % (vdata["NAME"], vdata["VERSION_ID"])
            # Old SuSE?
            if os.path.exists("/etc/SuSE-release"):
                # SuSE
                with open("/etc/SuSE-release") as f:
                    return f.readline().strip()
            # try lsb_release -d
            try:
                b = subprocess.check_output(["lsb_release", "-d"])
                return b.split(":", 1)[1].strip()
            except OSError:
                pass
            return "Unknown Linux"
        elif o == "freebsd":
            u = os.uname()
            return "%s %s" % (u[0], u[2])
        elif o == "darwin":
            # OS X
            return "Mac OS X %s" % platform.mac_ver()[0]
        return None

    @cachedproperty
    def python_version(self):
        return sys.version.split()[0]

    @cachedproperty
    def process(self):
        argv = [v for v in sys.argv if v]
        if not argv:
            return sys.executable
        if argv[0].endswith("python") and len(argv) > 1:
            return argv[1]
        return argv[0]

    @cachedproperty
    def package_versions(self):
Dmitry Volodin's avatar
Dmitry Volodin committed
155
        return {"Python": self.python_version}
Dmitry Volodin's avatar
Dmitry Volodin committed
156

Dmitry Volodin's avatar
Dmitry Volodin committed
157

Dmitry Volodin's avatar
Dmitry Volodin committed
158
159
# Singleton instance
version = Version()