Passed
Pull Request — master (#438)
by Björn
01:30
created

gvm.protocols.gmp.Gmp.determine_supported_gmp()   A

Complexity

Conditions 3

Size

Total Lines 17
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 11
nop 1
dl 0
loc 17
rs 9.85
c 0
b 0
f 0
1
# -*- coding: utf-8 -*-
2
# Copyright (C) 2019-2021 Greenbone Networks GmbH
3
#
4
# SPDX-License-Identifier: GPL-3.0-or-later
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 3 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,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
# GNU 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, see <http://www.gnu.org/licenses/>.
18
19
"""
20
Module for communication with gvmd
21
"""
22
from typing import Any, Optional, Callable, Union
23
24
from gvm.errors import GvmError
25
26
from gvm.protocols.base import GvmProtocol, GvmConnection
27
28
from gvm.protocols.gmpv208 import Gmp as Gmpv208
29
from gvm.protocols.gmpv214 import Gmp as Gmpv214
30
31
from gvm.transforms import EtreeCheckCommandTransform
32
33
from gvm.xml import XmlCommand
34
35
SUPPORTED_GMP_VERSIONS = Union[Gmpv208, Gmpv214]  # pylint: disable=invalid-name
36
37
38
class Gmp(GvmProtocol):
39
    """Dynamically select supported GMP protocol of the remote manager daemon.
40
41
    Must be used as a `Context Manager
42
    <https://docs.python.org/3/reference/datamodel.html#context-managers>`_
43
44
    Example:
45
46
        .. code-block:: python
47
48
            from gvm.protocols.gmp import Gmp
49
50
            with Gmp(connection) as gmp:
51
                # gmp can be an instance of gvm.protocols.gmpv208.Gmp,
52
                # gvm.protocols.gmpv214.Gmp depending
53
                # on the supported GMP version of the remote manager daemon
54
                resp = gmp.get_tasks()
55
56
    Attributes:
57
        connection: Connection to use to talk with the remote daemon. See
58
            :mod:`gvm.connections` for possible connection types.
59
        transform: Optional transform `callable`_ to convert response data.
60
            After each request the callable gets passed the plain response data
61
            which can be used to check the data and/or conversion into different
62
            representations like a xml dom.
63
64
            See :mod:`gvm.transforms` for existing transforms.
65
66
    .. _callable:
67
        https://docs.python.org/3/library/functions.html#callable
68
    """
69
70
    def __init__(
71
        self,
72
        connection: GvmConnection,
73
        *,
74
        transform: Optional[Callable[[str], Any]] = None,
75
    ):
76
        super().__init__(connection, transform=EtreeCheckCommandTransform())
77
        self._gmp_transform = transform
78
79
    def determine_remote_gmp_version(self) -> str:
80
        """Determine the supported GMP version of the remote daemon"""
81
        self.connect()
82
        resp = self._send_xml_command(XmlCommand("get_version"))
83
        self.disconnect()
84
85
        version_el = resp.find('version')
86
        if version_el is None:
87
            raise GvmError(
88
                'Invalid response from manager daemon while requesting the '
89
                'version information.'
90
            )
91
92
        return version_el.text
93
94
    def determine_supported_gmp(self) -> SUPPORTED_GMP_VERSIONS:
95
        """Determine supported GMP version of the remote daemon and return a
96
        corresponding Gmp class instance
97
        """
98
        version = self.determine_remote_gmp_version()
99
        major_version = int(version.split('.')[0])
100
        if major_version == 20:
101
            gmp_class = Gmpv208
102
        elif major_version == 21:
103
            gmp_class = Gmpv214
104
        else:
105
            raise GvmError(
106
                'Remote manager daemon uses an unsupported version of GMP. '
107
                'The GMP version was {}.'.format(version)
108
            )
109
110
        return gmp_class(self._connection, transform=self._gmp_transform)
111
112
    def __enter__(self):
113
        gmp = self.determine_supported_gmp()
114
115
        gmp.connect()
116
117
        return gmp
118