File: rpc.py

package info (click to toggle)
python-ncclient 0.6.17-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,448 kB
  • sloc: python: 9,548; xml: 476; makefile: 77; sh: 5
file content (127 lines) | stat: -rw-r--r-- 5,713 bytes parent folder | download | duplicates (2)
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
from ncclient.xml_ import *

from ncclient.operations.rpc import RPC
from ncclient.operations.rpc import RPCReply
from ncclient.operations.rpc import RPCError
from ncclient import NCClientError
import math


class GetConfiguration(RPC):
    def request(self, format='xml', filter=None):
        node = new_ele('get-configuration', {'format':format})
        if filter is not None:
            node.append(filter)
        if format !='xml':
            # The entire config comes as a single text element and this requires huge_tree support for large configs
            self._huge_tree = True
        return self._request(node)

class LoadConfiguration(RPC):
    def request(self, format='xml', action='merge',
            target='candidate', config=None):
        if config is not None:
            if type(config) == list:
                config = '\n'.join(config)
            if action == 'set':
                format = 'text'
            node = new_ele('load-configuration', {'action':action, 'format':format})
            if format == 'xml':
                config_node = sub_ele(node, 'configuration')
                config_node.append(config)
            if format == 'json':
                config_node = sub_ele(node, 'configuration-json').text = config
            if format == 'text' and not action == 'set':
                config_node = sub_ele(node, 'configuration-text').text = config
            if action == 'set' and format == 'text':
                config_node = sub_ele(node, 'configuration-set').text = config
            return self._request(node)


class CompareConfiguration(RPC):
    def request(self, rollback=0, format='text'):
        node = new_ele('get-configuration', {'compare':'rollback', 'format':format, 'rollback':str(rollback)})
        return self._request(node)


class ExecuteRpc(RPC):
    def request(self, rpc, filter_xml=None):
        if isinstance(rpc, str):
            rpc = to_ele(rpc)
        self._filter_xml = filter_xml
        return self._request(rpc)


class Command(RPC):
    def request(self, command=None, format='xml'):
        node = new_ele('command', {'format':format})
        node.text = command
        return self._request(node)


class Reboot(RPC):
    def request(self):
        node = new_ele('request-reboot')
        return self._request(node)


class Halt(RPC):
    def request(self):
        node = new_ele('request-halt')
        return self._request(node)


class Commit(RPC):
    "`commit` RPC. Depends on the `:candidate` capability, and the `:confirmed-commit`."

    DEPENDS = [':candidate']

    def request(self, confirmed=False, timeout=None, comment=None, synchronize=False, at_time=None, check=False):
        """Commit the candidate configuration as the device's new current configuration. Depends on the `:candidate` capability.

        A confirmed commit (i.e. if *confirmed* is `True`) is reverted if there is no followup commit within the *timeout* interval. If no timeout is specified the confirm timeout defaults to 600 seconds (10 minutes). A confirming commit may have the *confirmed* parameter but this is not required. Depends on the `:confirmed-commit` capability.

        *confirmed* whether this is a confirmed commit. Mutually exclusive with at_time.

        *timeout* specifies the confirm timeout in seconds

        *comment* a string to comment the commit with. Review on the device using 'show system commit'

        *synchronize* Whether we should synch this commit across both Routing Engines

        *at_time* Mutually exclusive with confirmed. The time at which the commit should happen. Junos expects either of these two formats:
            A time value of the form hh:mm[:ss] (hours, minutes, and, optionally, seconds)
            A date and time value of the form yyyy-mm-dd hh:mm[:ss] (year, month, date, hours, minutes, and, optionally, seconds)

        *check* Verify the syntactic correctness of the candidate configuration"""
        # NOTE: non netconf standard, Junos specific commit-configuration element, see
        # https://www.juniper.net/documentation/en_US/junos/topics/reference/tag-summary/junos-xml-protocol-commit-configuration.html
        node = new_ele_ns("commit-configuration", "")
        if confirmed and at_time is not None:
            raise NCClientError("'Commit confirmed' and 'commit at' are mutually exclusive.")
        if confirmed:
            self._assert(":confirmed-commit")
            sub_ele(node, "confirmed")
            if timeout is not None:
                # NOTE: For Junos, confirm-timeout has to be given in minutes:
                # https://www.juniper.net/documentation/en_US/junos/topics/reference/tag-summary/junos-xml-protocol-commit-configuration.html
                # but the netconf standard and ncclient library uses seconds:
                # https://tools.ietf.org/html/rfc6241#section-8.4.5
                # http://ncclient.readthedocs.io/en/latest/manager.html#ncclient.manager.Manager.commit
                # so need to convert the value in seconds to minutes.
                timeout_int = int(timeout) if isinstance(timeout, str) else timeout
                sub_ele(node, "confirm-timeout").text = str(int(math.ceil(timeout_int/60.0)))
        elif at_time is not None:
            sub_ele(node, "at-time").text = at_time
        if comment is not None:
            sub_ele(node, "log").text = comment
        if synchronize:
            sub_ele(node, "synchronize")
        if check:
            sub_ele(node, "check")
        return self._request(node)

class Rollback(RPC):
    def request(self, rollback=0):
        node = new_ele('load-configuration', {'rollback':str(rollback)})
        return self._request(node)