aboutsummaryrefslogtreecommitdiffstats
path: root/resources/tools/testbed-setup/ansible/roles/kernel/filter_plugins/main.py
blob: 7d909b90e8511154eabf8915d0c9f9cc8d538221 (plain)
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
"""Extra Ansible filters"""

def deb_kernel(packages, kernel_version, current_version):
    """
    Return best matching kernel version.
    Args:
        packages (dict): apt-cache showpkg output.
        kernel_version (str): Kernel version to install.
        current_version (str): Current kernel version.
    Returns:
       str: kernel version.
    """
    kernels = set()

    # List all available kernel version and associated repository
    for line in packages['stdout'].splitlines():
        line = line.strip()
        if line.startswith('Package: ') and (
                line.endswith('-common') or  # Debian
                line.endswith('-generic')):  # Ubuntu
            kernel = line.split()[1]

            for string in ('linux-headers-', 'common', 'generic'):
                kernel = kernel.replace(string, '')
            kernel = kernel.strip('-')

            if kernel:
                kernels.add(kernel)

    # Sort Kernel versions
    versions = {}
    for kernel in kernels:
        try:
            version, build = kernel.split('-', 1)
        except ValueError:
            version = kernel
            build = ''
        versions[kernel] = list(
            int(ver) for ver in version.split('.')) + [build]
    kernels = sorted(versions.keys(), key=versions.get, reverse=True)

    # Return more recent kernel package that match version requirement
    for kernel in kernels:
        if kernel.startswith(kernel_version):
            return kernel

    raise RuntimeError(
        'No kernel matching to "%s". Available kernel versions: %s' % (
            kernel_version, ', '.join(reversed(kernels))))


def _deb_kernel_package(kernel, dist, arch, name):
    """
    Return kernel package name.
    Args:
        kernel (str): Kernel version.
        dist (str): Distribution.
        arch (str): Architecture.
        name (str): Package name.
    Returns:
       str: kernel package.
    """
    # Define package suffix
    if dist == 'Ubuntu':
        suffix = 'generic'
    elif name == 'linux-image':
        suffix = arch.replace('x86_64', 'amd64')
    else:
        suffix = 'common'

    return '-'.join((name, kernel, suffix))


def deb_kernel_pkg(packages, kernel_version, current_version, dist, arch, name):
    """
    Return kernel package to install.
    Args:
        packages (dict): apt-cache showpkg output.
        kernel_version (str): Kernel version to install.
        current_version (str): Current kernel version.
        dist (str): Distribution.
        arch (str): Architecture.
        name (str): Package name.
    Returns:
       str: kernel package to install.
    """
    return _deb_kernel_package(
        deb_kernel(packages, kernel_version, current_version), dist, arch, name)


def deb_installed_kernel(installed, packages, kernel_version, current_version):
    """
    Return old kernel packages to remove.
    Args:
        installed (dict): dpkg -l output.
        packages (dict): apt-cache showpkg output.
        kernel_version (str): Kernel version to install.
        current_version (str): Current kernel version.
    Returns:
       list of str: Kernel packages to remove.
    """
    # Filter installed package to keep
    to_keep = deb_kernel(packages, kernel_version, current_version)

    # Return installed package to remove
    to_remove = []
    for line in installed['stdout'].splitlines():
        if ' linux-' not in line:
            continue

        package = line.split()[1]
        if ((package.startswith('linux-image-') or
             package.startswith('linux-headers-')) and not (
             package.startswith('linux-image-' + to_keep) or
             package.startswith('linux-headers-' + to_keep))):
            to_remove.append(package)

    return to_remove


def kernel_match(kernel, kernel_spec):
    """
    Check if kernel version match.
    Args:
        kernel (str): Kernel
        kernel_spec (str): Kernel to match.
    Returns:
        bool: True if Kernel match.
    """
    return kernel.startswith(kernel_spec)


class FilterModule(object):
    """Return filter plugin"""

    @staticmethod
    def filters():
        """Return filter"""
        return {'deb_kernel': deb_kernel,
                'deb_kernel_pkg': deb_kernel_pkg,
                'deb_installed_kernel': deb_installed_kernel,
                'kernel_match': kernel_match}