1 # Copyright 2009 Shikhar Bhushan
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
15 from copy import deepcopy
17 from ncclient import xml_
24 logger = logging.getLogger('ncclient.operations.edit')
26 "Operations related to changing device configuration"
28 class EditConfig(RPC):
34 SPEC = {'tag': 'edit-config', 'subtree': []}
36 def request(self, target, config, default_operation=None, test_option=None,
39 :arg target: see :ref:`source_target`
42 :arg config: a config element in :ref:`dtree`
43 :type config: `string` or `dict` or :class:`~xml.etree.ElementTree.Element`
45 :arg default_operation: optional; one of {'merge', 'replace', 'none'}
46 :type default_operation: `string`
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
51 :arg test_option: optional; one of {'test-then-set', 'set'}. Depends on *:validate* capability.
52 :type test_option: string
54 :seealso: :ref:`return`
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')
63 'tag': 'error-option',
66 if test_option is not None:
67 self._assert(':validate')
72 if default_operation is not None:
74 'tag': 'default-operation',
75 'text': default_operation
77 subtree.append(xml_.validated_element(config, ('config', xml_.qualify('config'))))
78 return self._request(spec)
80 class DeleteConfig(RPC):
84 "*<delete-config>* RPC"
86 SPEC = {'tag': 'delete-config', 'subtree': []}
88 def request(self, target):
90 :arg target: See :ref:`source_target`
91 :type target: `string` or `dict` or :class:`~xml.etree.ElementTree.Element`
93 :seealso: :ref:`return`
95 spec = deepcopy(DeleteConfig.SPEC)
96 spec['subtree'].append(util.store_or_url('target', target, self._assert))
97 return self._request(spec)
100 class CopyConfig(RPC):
104 "*<copy-config>* RPC"
106 SPEC = {'tag': 'copy-config', 'subtree': []}
108 def request(self, source, target):
110 :arg source: See :ref:`source_target`
111 :type source: `string` or `dict` or :class:`~xml.etree.ElementTree.Element`
113 :arg target: See :ref:`source_target`
114 :type target: `string` or `dict` or :class:`~xml.etree.ElementTree.Element`
116 :seealso: :ref:`return`
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)
128 "*<validate>* RPC. Depends on the *:validate* capability."
130 DEPENDS = [':validate']
132 SPEC = {'tag': 'validate', 'subtree': []}
134 def request(self, source):
136 :arg source: See :ref:`source_target`
137 :type source: `string` or `dict` or :class:`~xml.etree.ElementTree.Element`
139 :seealso: :ref:`return`
141 spec = deepcopy(Validate.SPEC)
143 src = markup.validated_element(source, ('config', markup.qualify('config')))
144 except Exception as e:
146 src = util.store_or_url('source', source, self._assert)
147 spec['subtree'].append({
151 return self._request(spec)
158 "*<commit>* RPC. Depends on the *:candidate* capability."
160 DEPENDS = [':candidate']
162 SPEC = {'tag': 'commit', 'subtree': []}
164 def _parse_hook(self):
167 def request(self, confirmed=False, timeout=None):
169 Requires *:confirmed-commit* capability if *confirmed* argument is
172 :arg confirmed: optional; request a confirmed commit
173 :type confirmed: `bool`
175 :arg timeout: specify timeout for confirmed commit
178 :seealso: :ref:`return`
180 spec = deepcopy(Commit.SPEC)
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',
189 return self._request(Commit.SPEC)
192 class DiscardChanges(RPC):
196 "*<discard-changes>* RPC. Depends on the *:candidate* capability."
198 DEPENDS = [':candidate']
200 SPEC = {'tag': 'discard-changes'}
203 ":seealso: :ref:`return`"
204 return self._request(DiscardChanges.SPEC)