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 content
24 logger = logging.getLogger('ncclient.operations.edit')
28 "Operations related to changing device configuration"
30 class EditConfig(RPC):
36 SPEC = {'tag': 'edit-config', 'subtree': []}
38 def request(self, target, config, default_operation=None, test_option=None,
41 :arg target: see :ref:`source_target`
44 :arg config: a config element in :ref:`dtree`
45 :type config: `string` or `dict` or :class:`~xml.etree.ElementTree.Element`
47 :arg default_operation: optional; one of {'merge', 'replace', 'none'}
48 :type default_operation: `string`
50 :arg test_option: optional; one of {'stop-on-error', 'continue-on-error', 'rollback-on-error'}. Last option depends on the *:rollback-on-error* capability
51 :type test_option: string
53 :seealso: :ref:`return`
55 spec = deepcopy(EditConfig.SPEC)
56 subtree = spec['subtree']
57 subtree.append(util.store_or_url('target', target, self._assert))
58 subtree.append(content.validated_element(config, ('config', content.qualify('config'))))
59 if default_operation is not None:
61 'tag': 'default-operation',
62 'text': default_operation
64 if test_option is not None:
65 self._assert(':validate')
70 if error_option is not None:
71 if error_option == 'rollback-on-error':
72 self._assert(':rollback-on-error')
74 'tag': 'error-option',
77 return self._request(spec)
79 class DeleteConfig(RPC):
83 "*<delete-config>* RPC"
85 SPEC = {'tag': 'delete-config', 'subtree': []}
87 def request(self, target):
89 :arg target: See :ref:`source_target`
90 :type target: `string` or `dict` or :class:`~xml.etree.ElementTree.Element`
92 :seealso: :ref:`return`
94 spec = deepcopy(DeleteConfig.SPEC)
95 spec['subtree'].append(util.store_or_url('target', target, self._assert))
96 return self._request(spec)
99 class CopyConfig(RPC):
103 "*<copy-config>* RPC"
105 SPEC = {'tag': 'copy-config', 'subtree': []}
107 def request(self, source, target):
109 :arg source: See :ref:`source_target`
110 :type source: `string` or `dict` or :class:`~xml.etree.ElementTree.Element`
112 :arg target: See :ref:`source_target`
113 :type target: `string` or `dict` or :class:`~xml.etree.ElementTree.Element`
115 :seealso: :ref:`return`
117 spec = deepcopy(CopyConfig.SPEC)
118 spec['subtree'].append(util.store_or_url('target', target, self._assert))
119 spec['subtree'].append(util.store_or_url('source', source, self._assert))
120 return self._request(spec)
127 "*<validate>* RPC. Depends on the *:validate* capability."
129 DEPENDS = [':validate']
131 SPEC = {'tag': 'validate', 'subtree': []}
133 def request(self, source):
135 :arg source: See :ref:`source_target`
136 :type source: `string` or `dict` or :class:`~xml.etree.ElementTree.Element`
138 :seealso: :ref:`return`
140 spec = deepcopy(Validate.SPEC)
142 src = content.validated_element(source, ('config', content.qualify('config')))
143 except Exception as e:
145 src = util.store_or_url('source', source, self._assert)
146 spec['subtree'].append({
150 return self._request(spec)
157 "*<commit>* RPC. Depends on the *:candidate* capability."
159 DEPENDS = [':candidate']
161 SPEC = {'tag': 'commit', 'subtree': []}
163 def _parse_hook(self):
166 def request(self, confirmed=False, timeout=None):
168 Requires *:confirmed-commit* capability if *confirmed* argument is
171 :arg confirmed: optional; request a confirmed commit
172 :type confirmed: `bool`
174 :arg timeout: specify timeout for confirmed commit
177 :seealso: :ref:`return`
179 spec = deepcopy(Commit.SPEC)
181 self._assert(':confirmed-commit')
182 spec['subtree'].append({'tag': 'confirmed'})
183 if timeout is not None:
184 spec['subtree'].append({
185 'tag': 'confirm-timeout',
188 return self._request(Commit.SPEC)
191 class DiscardChanges(RPC):
195 "*<discard-changes>* RPC. Depends on the *:candidate* capability."
197 DEPENDS = [':candidate']
199 SPEC = {'tag': 'discard-changes'}
202 ":seealso: :ref:`return`"
203 return self._request(DiscardChanges.SPEC)