blob: cc0640741c852da36318b3ad09251ac17e06ccdd [file] [log] [blame]
Sean Condonfae8e662016-12-15 10:25:13 +00001/*
2 * Copyright 2016-present Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.drivers.netconf;
17
18import java.util.List;
19import java.util.concurrent.CompletableFuture;
20import java.util.concurrent.atomic.AtomicInteger;
21import java.util.regex.Pattern;
22
23import org.onosproject.netconf.NetconfDeviceInfo;
24import org.onosproject.netconf.NetconfDeviceOutputEventListener;
25import org.onosproject.netconf.NetconfException;
26import org.onosproject.netconf.NetconfSession;
27import org.onosproject.netconf.TargetConfig;
28import org.slf4j.Logger;
29import org.slf4j.LoggerFactory;
30
31public class MockNetconfSession implements NetconfSession {
32 private static final Logger log = LoggerFactory
33 .getLogger(MockNetconfSession.class);
34
35 private static final String MESSAGE_ID_STRING = "message-id";
36 private static final String EQUAL = "=";
37 private static final String RPC_OPEN = "<rpc ";
38 private static final String RPC_CLOSE = "</rpc>";
39 private static final String GET_OPEN = "<get>";
40 private static final String GET_CLOSE = "</get>";
41 private static final String NEW_LINE = "\n";
42 private static final String SUBTREE_FILTER_OPEN = "<filter type=\"subtree\">";
43 private static final String SUBTREE_FILTER_CLOSE = "</filter>";
44 private static final String WITH_DEFAULT_OPEN = "<with-defaults ";
45 private static final String WITH_DEFAULT_CLOSE = "</with-defaults>";
46 private static final String EDIT_CONFIG_OPEN = "<edit-config>";
47 private static final String EDIT_CONFIG_CLOSE = "</edit-config>";
48 private static final String COPY_CONFIG_OPEN = "<copy-config>";
49 private static final String COPY_CONFIG_CLOSE = "</copy-config>";
50 private static final String DELETE_CONFIG_OPEN = "<delete-config>";
51 private static final String DELETE_CONFIG_CLOSE = "</delete-config>";
52 private static final String TARGET_OPEN = "<target>";
53 private static final String TARGET_CLOSE = "</target>";
54 private static final String SOURCE_OPEN = "<source>";
55 private static final String SOURCE_CLOSE = "</source>";
56 private static final String DEFAULT_OPERATION_OPEN = "<default-operation>";
57 private static final String DEFAULT_OPERATION_CLOSE = "</default-operation>";
58 private static final String CONFIG_OPEN = "<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">";
59 private static final String CONFIG_CLOSE = "</config>";
60
61 private static final String ENDPATTERN = "]]>]]>";
62 private static final String XML_HEADER =
63 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
64 private static final String NETCONF_BASE_NAMESPACE =
65 "xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"";
66 private static final String NETCONF_WITH_DEFAULTS_NAMESPACE =
67 "xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\"";
68
69 private Pattern simpleGetConfig =
70 Pattern.compile("(<\\?xml version=\"1.0\" encoding=\"UTF-8\"\\?>)\\R?"
71 + "(<rpc message-id=\")[0-9]*(\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
72 + "(<get-config>)\\R?"
73 + "(<source>)\\R?(<running/>)\\R?(</source>)\\R?"
74 + "(</get-config>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
75
76 private static final String SAMPLE_MSEAEVCUNI_REPLY_INIT = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
77 + "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"1\">\n"
78 + "<data xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
79 + "</data>\n"
80 + "</rpc-reply>";
81
82
83
84 private NetconfDeviceInfo deviceInfo;
85
86 private final AtomicInteger messageIdInteger = new AtomicInteger(0);
87
88 public MockNetconfSession(NetconfDeviceInfo deviceInfo) throws NetconfException {
89 this.deviceInfo = deviceInfo;
90 }
91
92 @Override
93 public CompletableFuture<String> request(String request) throws NetconfException {
94 throw new NetconfException("Should be calling a higher level command or one that sets the message id");
95 }
96
97 @Override
98 public String get(String request) throws NetconfException {
99
100 return sendRequest(request);
101 }
102
103 @Override
104 public String get(String filterSchema, String withDefaultsMode) throws NetconfException {
105 StringBuilder rpc = new StringBuilder(XML_HEADER);
106 rpc.append(RPC_OPEN);
107 rpc.append(MESSAGE_ID_STRING);
108 rpc.append(EQUAL);
109 rpc.append("\"");
110 rpc.append(messageIdInteger.get());
111 rpc.append("\" ");
112 rpc.append(NETCONF_BASE_NAMESPACE).append(">\n");
113 rpc.append(GET_OPEN).append(NEW_LINE);
114 if (filterSchema != null) {
115 rpc.append(SUBTREE_FILTER_OPEN).append(NEW_LINE);
116 rpc.append(filterSchema).append(NEW_LINE);
117 rpc.append(SUBTREE_FILTER_CLOSE).append(NEW_LINE);
118 }
119 if (withDefaultsMode != null) {
120 rpc.append(WITH_DEFAULT_OPEN).append(NETCONF_WITH_DEFAULTS_NAMESPACE).append(">");
121 rpc.append(withDefaultsMode).append(WITH_DEFAULT_CLOSE).append(NEW_LINE);
122 }
123 rpc.append(GET_CLOSE).append(NEW_LINE);
124 rpc.append(RPC_CLOSE).append(NEW_LINE);
125 rpc.append(ENDPATTERN);
126 String reply = sendRequest(rpc.toString());
127 checkReply(reply);
128 return reply;
129 }
130
131 @Override
132 public String doWrappedRpc(String request) throws NetconfException {
133 StringBuilder rpc = new StringBuilder(XML_HEADER);
134 rpc.append(RPC_OPEN);
135 rpc.append(MESSAGE_ID_STRING);
136 rpc.append(EQUAL);
137 rpc.append("\"");
138 rpc.append(messageIdInteger.get());
139 rpc.append("\" ");
140 rpc.append(NETCONF_BASE_NAMESPACE).append(">\n");
141 rpc.append(request);
142 rpc.append(RPC_CLOSE).append(NEW_LINE);
143 rpc.append(ENDPATTERN);
144 String reply = sendRequest(rpc.toString());
145 checkReply(reply);
146 return reply;
147 }
148
149 @Override
150 public String requestSync(String request) throws NetconfException {
151 if (!request.contains(ENDPATTERN)) {
152 request = request + NEW_LINE + ENDPATTERN;
153 }
154 String reply = sendRequest(request);
155 checkReply(reply);
156 return reply;
157 }
158
159
160 @Override
161 public String getConfig(String targetConfiguration, String configurationSchema) throws NetconfException {
162 return getConfig(TargetConfig.valueOf(targetConfiguration));
163 }
164
165 @Override
166 public String getConfig(String targetConfiguration) throws NetconfException {
167 return getConfig(TargetConfig.valueOf(targetConfiguration), null);
168 }
169
170 @Override
171 public String getConfig(TargetConfig netconfTargetConfig)
172 throws NetconfException {
173 return getConfig(netconfTargetConfig, null);
174 }
175
176 @Override
177 public String getConfig(TargetConfig netconfTargetConfig, String configurationFilterSchema)
178 throws NetconfException {
179 StringBuilder rpc = new StringBuilder(XML_HEADER);
180 rpc.append("<rpc ");
181 rpc.append(MESSAGE_ID_STRING);
182 rpc.append(EQUAL);
183 rpc.append("\"");
184 rpc.append(messageIdInteger.get());
185 rpc.append("\" ");
186 rpc.append("xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n");
187 rpc.append("<get-config>\n");
188 rpc.append("<source>\n");
189 rpc.append("<").append(netconfTargetConfig).append("/>");
190 rpc.append("</source>");
191 if (netconfTargetConfig != null) {
192 rpc.append("<filter type=\"subtree\">\n");
193 rpc.append(configurationFilterSchema).append("\n");
194 rpc.append("</filter>\n");
195 }
196 rpc.append("</get-config>\n");
197 rpc.append("</rpc>\n");
198 rpc.append(ENDPATTERN);
199 String reply = sendRequest(rpc.toString());
200 return checkReply(reply) ? reply : "ERROR " + reply;
201 }
202
203 @Override
204 public boolean editConfig(TargetConfig netconfTargetConfig, String mode, String newConfiguration)
205 throws NetconfException {
206 newConfiguration = newConfiguration.trim();
207 StringBuilder rpc = new StringBuilder(XML_HEADER);
208 rpc.append(RPC_OPEN);
209 rpc.append(MESSAGE_ID_STRING);
210 rpc.append(EQUAL);
211 rpc.append("\"");
212 rpc.append(messageIdInteger.get());
213 rpc.append("\" ");
214 rpc.append(NETCONF_BASE_NAMESPACE).append(">\n");
215 rpc.append(EDIT_CONFIG_OPEN).append("\n");
216 rpc.append(TARGET_OPEN);
217 rpc.append("<").append(netconfTargetConfig).append("/>");
218 rpc.append(TARGET_CLOSE).append("\n");
219 if (mode != null) {
220 rpc.append(DEFAULT_OPERATION_OPEN);
221 rpc.append(mode);
222 rpc.append(DEFAULT_OPERATION_CLOSE).append("\n");
223 }
224 rpc.append(CONFIG_OPEN).append("\n");
225 rpc.append(newConfiguration);
226 rpc.append(CONFIG_CLOSE).append("\n");
227 rpc.append(EDIT_CONFIG_CLOSE).append("\n");
228 rpc.append(RPC_CLOSE);
229 rpc.append(ENDPATTERN);
230 log.debug(rpc.toString());
231 String reply = sendRequest(rpc.toString());
232 return checkReply(reply);
233 }
234
235 @Override
236 public boolean editConfig(String newConfiguration) throws NetconfException {
237 return editConfig(TargetConfig.RUNNING, null, newConfiguration);
238 }
239
240 @Override
241 public boolean editConfig(String targetConfiguration, String mode, String newConfiguration)
242 throws NetconfException {
243 return editConfig(TargetConfig.valueOf(targetConfiguration), mode, newConfiguration);
244 }
245
246 @Override
247 public boolean copyConfig(TargetConfig netconfTargetConfig, String newConfiguration) throws NetconfException {
248 newConfiguration = newConfiguration.trim();
249 StringBuilder rpc = new StringBuilder(XML_HEADER);
250 rpc.append(RPC_OPEN);
251 rpc.append(MESSAGE_ID_STRING);
252 rpc.append(EQUAL);
253 rpc.append("\"");
254 rpc.append(messageIdInteger.get());
255 rpc.append("\" ");
256 rpc.append(NETCONF_BASE_NAMESPACE).append(">\n");
257 rpc.append(COPY_CONFIG_OPEN).append("\n");
258 rpc.append(TARGET_OPEN);
259 rpc.append("<").append(netconfTargetConfig).append("/>");
260 rpc.append(TARGET_CLOSE).append("\n");
261 rpc.append(SOURCE_OPEN);
262 rpc.append("<").append(newConfiguration).append("/>");
263 rpc.append(SOURCE_CLOSE).append("\n");
264 rpc.append(COPY_CONFIG_CLOSE).append("\n");
265 rpc.append(RPC_CLOSE);
266 rpc.append(ENDPATTERN);
267 log.debug(rpc.toString());
268 String reply = sendRequest(rpc.toString());
269 return checkReply(reply);
270 }
271
272 @Override
273 public boolean copyConfig(String targetConfiguration, String newConfiguration) throws NetconfException {
274 return copyConfig(TargetConfig.valueOf(targetConfiguration), newConfiguration);
275 }
276
277 @Override
278 public boolean deleteConfig(TargetConfig netconfTargetConfig) throws NetconfException {
279 StringBuilder rpc = new StringBuilder(XML_HEADER);
280 rpc.append(RPC_OPEN);
281 rpc.append(MESSAGE_ID_STRING);
282 rpc.append(EQUAL);
283 rpc.append("\"");
284 rpc.append(messageIdInteger.get());
285 rpc.append("\" ");
286 rpc.append(NETCONF_BASE_NAMESPACE).append(">\n");
287 rpc.append(DELETE_CONFIG_OPEN).append("\n");
288 rpc.append(TARGET_OPEN);
289 rpc.append("<").append(netconfTargetConfig).append("/>");
290 rpc.append(TARGET_CLOSE).append("\n");
291 rpc.append(DELETE_CONFIG_CLOSE).append("\n");
292 rpc.append(RPC_CLOSE);
293 rpc.append(ENDPATTERN);
294 log.debug(rpc.toString());
295 String reply = sendRequest(rpc.toString());
296 return checkReply(reply);
297 }
298
299 @Override
300 public boolean deleteConfig(String targetConfiguration) throws NetconfException {
301 return deleteConfig(TargetConfig.valueOf(targetConfiguration));
302 }
303
304 @Override
305 public void startSubscription() throws NetconfException {
306 // TODO Auto-generated method stub
307
308 }
309
310 @Override
311 public void startSubscription(String filterSchema) throws NetconfException {
312 // TODO Auto-generated method stub
313
314 }
315
316 @Override
317 public void endSubscription() throws NetconfException {
318 // TODO Auto-generated method stub
319
320 }
321
322 @Override
323 public boolean lock(String configType) throws NetconfException {
324 // TODO Auto-generated method stub
325 return false;
326 }
327
328 @Override
329 public boolean unlock(String configType) throws NetconfException {
330 // TODO Auto-generated method stub
331 return false;
332 }
333
334 @Override
335 public boolean lock() throws NetconfException {
336 // TODO Auto-generated method stub
337 return false;
338 }
339
340 @Override
341 public boolean unlock() throws NetconfException {
342 // TODO Auto-generated method stub
343 return false;
344 }
345
346 @Override
347 public boolean close() throws NetconfException {
348 // TODO Auto-generated method stub
349 return false;
350 }
351
352 @Override
353 public String getSessionId() {
354 return "mockSessionId";
355 }
356
357 @Override
358 public String getServerCapabilities() {
359 // TODO Auto-generated method stub
360 return null;
361 }
362
363 @Override
364 public void setDeviceCapabilities(List<String> capabilities) {
365 // TODO Auto-generated method stub
366
367 }
368
369 @Override
370 public void addDeviceOutputListener(NetconfDeviceOutputEventListener listener) {
371 // TODO Auto-generated method stub
372
373 }
374
375 @Override
376 public void removeDeviceOutputListener(NetconfDeviceOutputEventListener listener) {
377 // TODO Auto-generated method stub
378
379 }
380
381 private boolean checkReply(String reply) throws NetconfException {
382 if (reply != null) {
383 if (!reply.contains("<rpc-error>")) {
384 log.debug("Device {} sent reply {}", deviceInfo, reply);
385 return true;
386 } else if (reply.contains("<ok/>")
387 || (reply.contains("<rpc-error>")
388 && reply.contains("warning"))) {
389 log.debug("Device {} sent reply {}", deviceInfo, reply);
390 return true;
391 }
392 }
393 log.warn("Device {} has error in reply {}", deviceInfo, reply);
394 return false;
395 }
396
397 private String sendRequest(String request) throws NetconfException {
398 log.info("Mocking NETCONF Session send request: \n" + request);
399
400 if (simpleGetConfig.matcher(request).matches()) {
401 return SAMPLE_MSEAEVCUNI_REPLY_INIT;
402
403 } else {
404 throw new NetconfException("MocknetconfSession. No sendRequest() case for query: " +
405 request);
406 }
407 }
408}