Revision 216bb34c ncclient/operations/edit.py
b/ncclient/operations/edit.py | ||
---|---|---|
18 | 18 |
|
19 | 19 |
import util |
20 | 20 |
|
21 |
"Operations related to configuration editing"
|
|
21 |
"Operations related to changing device configuration"
|
|
22 | 22 |
|
23 | 23 |
class EditConfig(RPC): |
24 | 24 |
|
25 |
"*<edit-config>* RPC" |
|
26 |
|
|
25 | 27 |
SPEC = {'tag': 'edit-config', 'subtree': []} |
26 | 28 |
|
27 |
def request(self, target=None, config=None, default_operation=None, |
|
28 |
test_option=None, error_option=None): |
|
29 |
util.one_of(target, config) |
|
29 |
def request(self, target, config, default_operation=None, test_option=None, |
|
30 |
error_option=None): |
|
31 |
""" |
|
32 |
:arg target: see :ref:`source_target` |
|
33 |
:type target: string |
|
34 |
|
|
35 |
:arg config: a config element in :ref:`dtree` |
|
36 |
:type config: `string` or `dict` or :class:`~xml.etree.ElementTree.Element` |
|
37 |
|
|
38 |
:arg default_operation: optional; one of {'merge', 'replace', 'none'} |
|
39 |
:type default_operation: `string` |
|
40 |
|
|
41 |
:arg test_option: optional; one of {'stop-on-error', 'continue-on-error', 'rollback-on-error'}. Last option depends on the *:rollback-on-error* capability |
|
42 |
:type test_option: string |
|
43 |
|
|
44 |
:seealso: :ref:`return` |
|
45 |
""" |
|
30 | 46 |
spec = EditConfig.SPEC.copy() |
31 | 47 |
subtree = spec['subtree'] |
32 | 48 |
subtree.append(util.store_or_url('target', target, self._assert)) |
33 |
subtree.append(content.validated_root(config, 'config'))
|
|
49 |
subtree.append(content.validated_element(config, ('config', content.qualify('config'))))
|
|
34 | 50 |
if default_operation is not None: |
35 | 51 |
subtree.append({ |
36 | 52 |
'tag': 'default-operation', |
... | ... | |
51 | 67 |
}) |
52 | 68 |
return self._request(spec) |
53 | 69 |
|
54 |
|
|
55 | 70 |
class DeleteConfig(RPC): |
56 | 71 |
|
72 |
"*<delete-config>* RPC" |
|
73 |
|
|
57 | 74 |
SPEC = {'tag': 'delete-config', 'subtree': []} |
58 | 75 |
|
59 | 76 |
def request(self, target): |
77 |
""" |
|
78 |
:arg target: See :ref:`source_target` |
|
79 |
:type target: `string` or `dict` or :class:`~xml.etree.ElementTree.Element` |
|
80 |
|
|
81 |
:seealso: :ref:`return` |
|
82 |
""" |
|
60 | 83 |
spec = DeleteConfig.SPEC.copy() |
61 | 84 |
spec['subtree'].append(util.store_or_url('target', target, self._assert)) |
62 | 85 |
return self._request(spec) |
... | ... | |
64 | 87 |
|
65 | 88 |
class CopyConfig(RPC): |
66 | 89 |
|
90 |
"*<copy-config>* RPC" |
|
91 |
|
|
67 | 92 |
SPEC = {'tag': 'copy-config', 'subtree': []} |
68 | 93 |
|
69 | 94 |
def request(self, source, target): |
95 |
""" |
|
96 |
:arg source: See :ref:`source_target` |
|
97 |
:type source: `string` or `dict` or :class:`~xml.etree.ElementTree.Element` |
|
98 |
|
|
99 |
:arg target: See :ref:`source_target` |
|
100 |
:type target: `string` or `dict` or :class:`~xml.etree.ElementTree.Element` |
|
101 |
|
|
102 |
:seealso: :ref:`return` |
|
103 |
""" |
|
70 | 104 |
spec = CopyConfig.SPEC.copy() |
71 | 105 |
spec['subtree'].append(util.store_or_url('source', source, self._assert)) |
72 | 106 |
spec['subtree'].append(util.store_or_url('target', target, self._assert)) |
... | ... | |
75 | 109 |
|
76 | 110 |
class Validate(RPC): |
77 | 111 |
|
112 |
"*<validate>* RPC. Depends on the *:validate* capability." |
|
113 |
|
|
78 | 114 |
DEPENDS = [':validate'] |
79 | 115 |
|
80 | 116 |
SPEC = {'tag': 'validate', 'subtree': []} |
81 | 117 |
|
82 | 118 |
def request(self, source): |
83 |
# determine if source is a <config> element |
|
119 |
""" |
|
120 |
:arg source: See :ref:`source_target` |
|
121 |
:type source: `string` or `dict` or :class:`~xml.etree.ElementTree.Element` |
|
122 |
|
|
123 |
:seealso: :ref:`return` |
|
124 |
""" |
|
84 | 125 |
spec = Validate.SPEC.copy() |
85 | 126 |
try: |
86 | 127 |
spec['subtree'].append({ |
87 | 128 |
'tag': 'source', |
88 |
'subtree': content.validated_root(config, ('config', content.qualify('config'))) |
|
129 |
'subtree': |
|
130 |
content.validated_element( |
|
131 |
config, ('config', content.qualify('config'))) |
|
89 | 132 |
}) |
90 |
except ContentError:
|
|
133 |
except: |
|
91 | 134 |
spec['subtree'].append(util.store_or_url('source', source, self._assert)) |
92 | 135 |
return self._request(spec) |
93 | 136 |
|
94 | 137 |
|
95 | 138 |
class Commit(RPC): |
96 | 139 |
|
140 |
"*<commit>* RPC. Depends on the *:candidate* capability." |
|
141 |
|
|
97 | 142 |
DEPENDS = [':candidate'] |
98 | 143 |
|
99 | 144 |
SPEC = {'tag': 'commit', 'subtree': []} |
... | ... | |
101 | 146 |
def _parse_hook(self): |
102 | 147 |
pass |
103 | 148 |
|
104 |
def request(self, confirmed=False): |
|
149 |
def request(self, confirmed=False, timeout=None): |
|
150 |
""" |
|
151 |
Requires *:confirmed-commit* capability if *confirmed* argument is |
|
152 |
:const:`True`. |
|
153 |
|
|
154 |
:arg confirmed: optional; request a confirmed commit |
|
155 |
:type confirmed: `bool` |
|
156 |
|
|
157 |
:arg timeout: specify timeout for confirmed commit |
|
158 |
:type timeout: `int` |
|
159 |
|
|
160 |
:seealso: :ref:`return` |
|
161 |
""" |
|
105 | 162 |
spec = SPEC.copy() |
106 | 163 |
if confirmed: |
107 | 164 |
self._assert(':confirmed-commit') |
... | ... | |
116 | 173 |
|
117 | 174 |
class DiscardChanges(RPC): |
118 | 175 |
|
176 |
"*<discard-changes>* RPC. Depends on the *:candidate* capability." |
|
177 |
|
|
119 | 178 |
DEPENDS = [':candidate'] |
120 | 179 |
|
121 | 180 |
SPEC = {'tag': 'discard-changes'} |
122 |
|
|
123 |
|
|
124 |
class ConfirmedCommit(Commit): |
|
125 |
"psuedo-op" |
|
126 |
|
|
127 |
DEPENDS = [':candidate', ':confirmed-commit'] |
|
128 |
|
|
129 |
def request(self): |
|
130 |
"Commit changes requiring that a confirm/discard follow" |
|
131 |
return Commit.request(self, confirmed=True) |
|
132 |
|
|
133 |
def confirm(self): |
|
134 |
"Confirm changes" |
|
135 |
return Commit.request(self, confirmed=True) |
|
136 |
|
|
137 |
def discard(self): |
|
138 |
"Discard changes" |
|
139 |
return DiscardChanges(self.session, self.async, self.timeout).request() |
Also available in: Unified diff