rename content to xml_
[ncclient] / ncclient / operations / edit.py
1 # Copyright 2009 Shikhar Bhushan
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #    http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 from copy import deepcopy
16
17 from ncclient import xml_
18
19 from rpc import RPC
20
21 import util
22
23 import logging
24 logger = logging.getLogger('ncclient.operations.edit')
25
26 "Operations related to changing device configuration"
27
28 class EditConfig(RPC):
29
30     # TESTED
31
32     "*<edit-config>* RPC"
33
34     SPEC = {'tag': 'edit-config', 'subtree': []}
35
36     def request(self, target, config, default_operation=None, test_option=None,
37                 error_option=None):
38         """
39         :arg target: see :ref:`source_target`
40         :type target: string
41
42         :arg config: a config element in :ref:`dtree`
43         :type config: `string` or `dict` or :class:`~xml.etree.ElementTree.Element`
44
45         :arg default_operation: optional; one of {'merge', 'replace', 'none'}
46         :type default_operation: `string`
47
48         :arg error_option: optional; one of {'stop-on-error', 'continue-on-error', 'rollback-on-error'}. Last option depends on the *:rollback-on-error* capability
49         :type error_option: string
50
51         :arg test_option: optional; one of {'test-then-set', 'set'}. Depends on *:validate* capability.
52         :type test_option: string
53
54         :seealso: :ref:`return`
55         """
56         spec = deepcopy(EditConfig.SPEC)
57         subtree = spec['subtree']
58         subtree.append(util.store_or_url('target', target, self._assert))
59         if error_option is not None:
60             if error_option == 'rollback-on-error':
61                 self._assert(':rollback-on-error')
62             subtree.append({
63                 'tag': 'error-option',
64                 'text': error_option
65                 })
66         if test_option is not None:
67             self._assert(':validate')
68             subtree.append({
69                 'tag': 'test-option',
70                 'text': test_option
71                 })
72         if default_operation is not None:
73             subtree.append({
74                 'tag': 'default-operation',
75                 'text': default_operation
76                 })
77         subtree.append(xml_.validated_element(config, ('config', xml_.qualify('config'))))
78         return self._request(spec)
79
80 class DeleteConfig(RPC):
81
82     # TESTED
83
84     "*<delete-config>* RPC"
85
86     SPEC = {'tag': 'delete-config', 'subtree': []}
87
88     def request(self, target):
89         """
90         :arg target: See :ref:`source_target`
91         :type target: `string` or `dict` or :class:`~xml.etree.ElementTree.Element`
92
93         :seealso: :ref:`return`
94         """
95         spec = deepcopy(DeleteConfig.SPEC)
96         spec['subtree'].append(util.store_or_url('target', target, self._assert))
97         return self._request(spec)
98
99
100 class CopyConfig(RPC):
101
102     # TESTED
103
104     "*<copy-config>* RPC"
105
106     SPEC = {'tag': 'copy-config', 'subtree': []}
107
108     def request(self, source, target):
109         """
110         :arg source: See :ref:`source_target`
111         :type source: `string` or `dict` or :class:`~xml.etree.ElementTree.Element`
112
113         :arg target: See :ref:`source_target`
114         :type target: `string` or `dict` or :class:`~xml.etree.ElementTree.Element`
115
116         :seealso: :ref:`return`
117         """
118         spec = deepcopy(CopyConfig.SPEC)
119         spec['subtree'].append(util.store_or_url('target', target, self._assert))
120         spec['subtree'].append(util.store_or_url('source', source, self._assert))
121         return self._request(spec)
122
123
124 class Validate(RPC):
125
126     # TESTED
127
128     "*<validate>* RPC. Depends on the *:validate* capability."
129
130     DEPENDS = [':validate']
131
132     SPEC = {'tag': 'validate', 'subtree': []}
133
134     def request(self, source):
135         """
136         :arg source: See :ref:`source_target`
137         :type source: `string` or `dict` or :class:`~xml.etree.ElementTree.Element`
138
139         :seealso: :ref:`return`
140         """
141         spec = deepcopy(Validate.SPEC)
142         try:
143             src = markup.validated_element(source, ('config', markup.qualify('config')))
144         except Exception as e:
145             logger.debug(e)
146             src = util.store_or_url('source', source, self._assert)
147         spec['subtree'].append({
148             'tag': 'source',
149             'subtree': src
150             })
151         return self._request(spec)
152
153
154 class Commit(RPC):
155
156     # TESTED
157
158     "*<commit>* RPC. Depends on the *:candidate* capability."
159
160     DEPENDS = [':candidate']
161
162     SPEC = {'tag': 'commit', 'subtree': []}
163
164     def _parse_hook(self):
165         pass
166
167     def request(self, confirmed=False, timeout=None):
168         """
169         Requires *:confirmed-commit* capability if *confirmed* argument is
170         :const:`True`.
171
172         :arg confirmed: optional; request a confirmed commit
173         :type confirmed: `bool`
174
175         :arg timeout: specify timeout for confirmed commit
176         :type timeout: `int`
177
178         :seealso: :ref:`return`
179         """
180         spec = deepcopy(Commit.SPEC)
181         if confirmed:
182             self._assert(':confirmed-commit')
183             spec['subtree'].append({'tag': 'confirmed'})
184             if timeout is not None:
185                 spec['subtree'].append({
186                     'tag': 'confirm-timeout',
187                     'text': timeout
188                 })
189         return self._request(Commit.SPEC)
190
191
192 class DiscardChanges(RPC):
193
194     # TESTED
195
196     "*<discard-changes>* RPC. Depends on the *:candidate* capability."
197
198     DEPENDS = [':candidate']
199
200     SPEC = {'tag': 'discard-changes'}
201
202     def request(self):
203         ":seealso: :ref:`return`"
204         return self._request(DiscardChanges.SPEC)