blob: 155a5a0f7e4b05ea82f12dba8776f3d009bf1c8a [file] [log] [blame]
Sean Condonfae8e662016-12-15 10:25:13 +00001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Sean Condonfae8e662016-12-15 10:25:13 +00003 *
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
Sean Condonfae8e662016-12-15 10:25:13 +000018import java.util.concurrent.CompletableFuture;
19import java.util.concurrent.atomic.AtomicInteger;
20import java.util.regex.Pattern;
21
Yuta HIGUCHIdd7c3f82017-09-03 14:18:01 -070022import org.onosproject.netconf.DatastoreId;
Sean Condonfae8e662016-12-15 10:25:13 +000023import org.onosproject.netconf.NetconfDeviceInfo;
24import org.onosproject.netconf.NetconfDeviceOutputEventListener;
25import org.onosproject.netconf.NetconfException;
Yuta HIGUCHIdd7c3f82017-09-03 14:18:01 -070026import org.onosproject.netconf.NetconfSessionAdapter;
Sean Condonfae8e662016-12-15 10:25:13 +000027import org.slf4j.Logger;
28import org.slf4j.LoggerFactory;
29
Yuta HIGUCHIdd7c3f82017-09-03 14:18:01 -070030public class MockNetconfSession extends NetconfSessionAdapter {
Sean Condonfae8e662016-12-15 10:25:13 +000031 private static final Logger log = LoggerFactory
32 .getLogger(MockNetconfSession.class);
33
34 private static final String MESSAGE_ID_STRING = "message-id";
35 private static final String EQUAL = "=";
36 private static final String RPC_OPEN = "<rpc ";
37 private static final String RPC_CLOSE = "</rpc>";
38 private static final String GET_OPEN = "<get>";
39 private static final String GET_CLOSE = "</get>";
40 private static final String NEW_LINE = "\n";
41 private static final String SUBTREE_FILTER_OPEN = "<filter type=\"subtree\">";
42 private static final String SUBTREE_FILTER_CLOSE = "</filter>";
43 private static final String WITH_DEFAULT_OPEN = "<with-defaults ";
44 private static final String WITH_DEFAULT_CLOSE = "</with-defaults>";
45 private static final String EDIT_CONFIG_OPEN = "<edit-config>";
46 private static final String EDIT_CONFIG_CLOSE = "</edit-config>";
47 private static final String COPY_CONFIG_OPEN = "<copy-config>";
48 private static final String COPY_CONFIG_CLOSE = "</copy-config>";
49 private static final String DELETE_CONFIG_OPEN = "<delete-config>";
50 private static final String DELETE_CONFIG_CLOSE = "</delete-config>";
51 private static final String TARGET_OPEN = "<target>";
52 private static final String TARGET_CLOSE = "</target>";
53 private static final String SOURCE_OPEN = "<source>";
54 private static final String SOURCE_CLOSE = "</source>";
55 private static final String DEFAULT_OPERATION_OPEN = "<default-operation>";
56 private static final String DEFAULT_OPERATION_CLOSE = "</default-operation>";
57 private static final String CONFIG_OPEN = "<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">";
58 private static final String CONFIG_CLOSE = "</config>";
59
60 private static final String ENDPATTERN = "]]>]]>";
61 private static final String XML_HEADER =
62 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
63 private static final String NETCONF_BASE_NAMESPACE =
64 "xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"";
65 private static final String NETCONF_WITH_DEFAULTS_NAMESPACE =
66 "xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\"";
67
68 private Pattern simpleGetConfig =
69 Pattern.compile("(<\\?xml version=\"1.0\" encoding=\"UTF-8\"\\?>)\\R?"
70 + "(<rpc message-id=\")[0-9]*(\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
71 + "(<get-config>)\\R?"
72 + "(<source>)\\R?(<running/>)\\R?(</source>)\\R?"
73 + "(</get-config>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
74
75 private static final String SAMPLE_MSEAEVCUNI_REPLY_INIT = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
76 + "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"1\">\n"
77 + "<data xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
78 + "</data>\n"
79 + "</rpc-reply>";
80
81
82
83 private NetconfDeviceInfo deviceInfo;
84
85 private final AtomicInteger messageIdInteger = new AtomicInteger(0);
86
87 public MockNetconfSession(NetconfDeviceInfo deviceInfo) throws NetconfException {
88 this.deviceInfo = deviceInfo;
89 }
90
91 @Override
92 public CompletableFuture<String> request(String request) throws NetconfException {
93 throw new NetconfException("Should be calling a higher level command or one that sets the message id");
94 }
95
96 @Override
97 public String get(String request) throws NetconfException {
98
99 return sendRequest(request);
100 }
101
102 @Override
103 public String get(String filterSchema, String withDefaultsMode) throws NetconfException {
104 StringBuilder rpc = new StringBuilder(XML_HEADER);
105 rpc.append(RPC_OPEN);
106 rpc.append(MESSAGE_ID_STRING);
107 rpc.append(EQUAL);
108 rpc.append("\"");
109 rpc.append(messageIdInteger.get());
110 rpc.append("\" ");
111 rpc.append(NETCONF_BASE_NAMESPACE).append(">\n");
112 rpc.append(GET_OPEN).append(NEW_LINE);
113 if (filterSchema != null) {
114 rpc.append(SUBTREE_FILTER_OPEN).append(NEW_LINE);
115 rpc.append(filterSchema).append(NEW_LINE);
116 rpc.append(SUBTREE_FILTER_CLOSE).append(NEW_LINE);
117 }
118 if (withDefaultsMode != null) {
119 rpc.append(WITH_DEFAULT_OPEN).append(NETCONF_WITH_DEFAULTS_NAMESPACE).append(">");
120 rpc.append(withDefaultsMode).append(WITH_DEFAULT_CLOSE).append(NEW_LINE);
121 }
122 rpc.append(GET_CLOSE).append(NEW_LINE);
123 rpc.append(RPC_CLOSE).append(NEW_LINE);
124 rpc.append(ENDPATTERN);
125 String reply = sendRequest(rpc.toString());
126 checkReply(reply);
127 return reply;
128 }
129
130 @Override
131 public String doWrappedRpc(String request) throws NetconfException {
132 StringBuilder rpc = new StringBuilder(XML_HEADER);
133 rpc.append(RPC_OPEN);
134 rpc.append(MESSAGE_ID_STRING);
135 rpc.append(EQUAL);
136 rpc.append("\"");
137 rpc.append(messageIdInteger.get());
138 rpc.append("\" ");
139 rpc.append(NETCONF_BASE_NAMESPACE).append(">\n");
140 rpc.append(request);
141 rpc.append(RPC_CLOSE).append(NEW_LINE);
142 rpc.append(ENDPATTERN);
143 String reply = sendRequest(rpc.toString());
144 checkReply(reply);
145 return reply;
146 }
147
148 @Override
149 public String requestSync(String request) throws NetconfException {
150 if (!request.contains(ENDPATTERN)) {
151 request = request + NEW_LINE + ENDPATTERN;
152 }
153 String reply = sendRequest(request);
154 checkReply(reply);
155 return reply;
156 }
157
158
159 @Override
Yuta HIGUCHIdd7c3f82017-09-03 14:18:01 -0700160 public String getConfig(DatastoreId netconfTargetConfig)
Sean Condonfae8e662016-12-15 10:25:13 +0000161 throws NetconfException {
162 return getConfig(netconfTargetConfig, null);
163 }
164
165 @Override
Yuta HIGUCHIdd7c3f82017-09-03 14:18:01 -0700166 public String getConfig(DatastoreId netconfTargetConfig, String configurationFilterSchema)
Sean Condonfae8e662016-12-15 10:25:13 +0000167 throws NetconfException {
168 StringBuilder rpc = new StringBuilder(XML_HEADER);
169 rpc.append("<rpc ");
170 rpc.append(MESSAGE_ID_STRING);
171 rpc.append(EQUAL);
172 rpc.append("\"");
173 rpc.append(messageIdInteger.get());
174 rpc.append("\" ");
175 rpc.append("xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n");
176 rpc.append("<get-config>\n");
177 rpc.append("<source>\n");
178 rpc.append("<").append(netconfTargetConfig).append("/>");
179 rpc.append("</source>");
180 if (netconfTargetConfig != null) {
181 rpc.append("<filter type=\"subtree\">\n");
182 rpc.append(configurationFilterSchema).append("\n");
183 rpc.append("</filter>\n");
184 }
185 rpc.append("</get-config>\n");
186 rpc.append("</rpc>\n");
187 rpc.append(ENDPATTERN);
188 String reply = sendRequest(rpc.toString());
189 return checkReply(reply) ? reply : "ERROR " + reply;
190 }
191
192 @Override
Yuta HIGUCHIdd7c3f82017-09-03 14:18:01 -0700193 public boolean editConfig(DatastoreId netconfTargetConfig, String mode, String newConfiguration)
Sean Condonfae8e662016-12-15 10:25:13 +0000194 throws NetconfException {
195 newConfiguration = newConfiguration.trim();
196 StringBuilder rpc = new StringBuilder(XML_HEADER);
197 rpc.append(RPC_OPEN);
198 rpc.append(MESSAGE_ID_STRING);
199 rpc.append(EQUAL);
200 rpc.append("\"");
201 rpc.append(messageIdInteger.get());
202 rpc.append("\" ");
203 rpc.append(NETCONF_BASE_NAMESPACE).append(">\n");
204 rpc.append(EDIT_CONFIG_OPEN).append("\n");
205 rpc.append(TARGET_OPEN);
206 rpc.append("<").append(netconfTargetConfig).append("/>");
207 rpc.append(TARGET_CLOSE).append("\n");
208 if (mode != null) {
209 rpc.append(DEFAULT_OPERATION_OPEN);
210 rpc.append(mode);
211 rpc.append(DEFAULT_OPERATION_CLOSE).append("\n");
212 }
213 rpc.append(CONFIG_OPEN).append("\n");
214 rpc.append(newConfiguration);
215 rpc.append(CONFIG_CLOSE).append("\n");
216 rpc.append(EDIT_CONFIG_CLOSE).append("\n");
217 rpc.append(RPC_CLOSE);
218 rpc.append(ENDPATTERN);
219 log.debug(rpc.toString());
220 String reply = sendRequest(rpc.toString());
221 return checkReply(reply);
222 }
223
224 @Override
225 public boolean editConfig(String newConfiguration) throws NetconfException {
Yuta HIGUCHIdd7c3f82017-09-03 14:18:01 -0700226 return editConfig(DatastoreId.RUNNING, null, newConfiguration);
Sean Condonfae8e662016-12-15 10:25:13 +0000227 }
228
229 @Override
Yuta HIGUCHIdd7c3f82017-09-03 14:18:01 -0700230 public boolean copyConfig(DatastoreId netconfTargetConfig, String newConfiguration) throws NetconfException {
Sean Condonfae8e662016-12-15 10:25:13 +0000231 newConfiguration = newConfiguration.trim();
232 StringBuilder rpc = new StringBuilder(XML_HEADER);
233 rpc.append(RPC_OPEN);
234 rpc.append(MESSAGE_ID_STRING);
235 rpc.append(EQUAL);
236 rpc.append("\"");
237 rpc.append(messageIdInteger.get());
238 rpc.append("\" ");
239 rpc.append(NETCONF_BASE_NAMESPACE).append(">\n");
240 rpc.append(COPY_CONFIG_OPEN).append("\n");
241 rpc.append(TARGET_OPEN);
242 rpc.append("<").append(netconfTargetConfig).append("/>");
243 rpc.append(TARGET_CLOSE).append("\n");
244 rpc.append(SOURCE_OPEN);
245 rpc.append("<").append(newConfiguration).append("/>");
246 rpc.append(SOURCE_CLOSE).append("\n");
247 rpc.append(COPY_CONFIG_CLOSE).append("\n");
248 rpc.append(RPC_CLOSE);
249 rpc.append(ENDPATTERN);
250 log.debug(rpc.toString());
251 String reply = sendRequest(rpc.toString());
252 return checkReply(reply);
253 }
254
255 @Override
256 public boolean copyConfig(String targetConfiguration, String newConfiguration) throws NetconfException {
Yuta HIGUCHIdd7c3f82017-09-03 14:18:01 -0700257 return copyConfig(DatastoreId.datastore(targetConfiguration), newConfiguration);
Sean Condonfae8e662016-12-15 10:25:13 +0000258 }
259
260 @Override
Yuta HIGUCHIdd7c3f82017-09-03 14:18:01 -0700261 public boolean deleteConfig(DatastoreId netconfTargetConfig) throws NetconfException {
Sean Condonfae8e662016-12-15 10:25:13 +0000262 StringBuilder rpc = new StringBuilder(XML_HEADER);
263 rpc.append(RPC_OPEN);
264 rpc.append(MESSAGE_ID_STRING);
265 rpc.append(EQUAL);
266 rpc.append("\"");
267 rpc.append(messageIdInteger.get());
268 rpc.append("\" ");
269 rpc.append(NETCONF_BASE_NAMESPACE).append(">\n");
270 rpc.append(DELETE_CONFIG_OPEN).append("\n");
271 rpc.append(TARGET_OPEN);
272 rpc.append("<").append(netconfTargetConfig).append("/>");
273 rpc.append(TARGET_CLOSE).append("\n");
274 rpc.append(DELETE_CONFIG_CLOSE).append("\n");
275 rpc.append(RPC_CLOSE);
276 rpc.append(ENDPATTERN);
277 log.debug(rpc.toString());
278 String reply = sendRequest(rpc.toString());
279 return checkReply(reply);
280 }
281
282 @Override
Sean Condonfae8e662016-12-15 10:25:13 +0000283 public void startSubscription() throws NetconfException {
284 // TODO Auto-generated method stub
285
286 }
287
288 @Override
289 public void startSubscription(String filterSchema) throws NetconfException {
290 // TODO Auto-generated method stub
291
292 }
293
294 @Override
295 public void endSubscription() throws NetconfException {
296 // TODO Auto-generated method stub
297
298 }
299
300 @Override
Sean Condonfae8e662016-12-15 10:25:13 +0000301 public boolean lock() throws NetconfException {
302 // TODO Auto-generated method stub
303 return false;
304 }
305
306 @Override
307 public boolean unlock() throws NetconfException {
308 // TODO Auto-generated method stub
309 return false;
310 }
311
312 @Override
313 public boolean close() throws NetconfException {
314 // TODO Auto-generated method stub
315 return false;
316 }
317
318 @Override
319 public String getSessionId() {
320 return "mockSessionId";
321 }
322
323 @Override
Sean Condonfae8e662016-12-15 10:25:13 +0000324 public void addDeviceOutputListener(NetconfDeviceOutputEventListener listener) {
325 // TODO Auto-generated method stub
326
327 }
328
329 @Override
330 public void removeDeviceOutputListener(NetconfDeviceOutputEventListener listener) {
331 // TODO Auto-generated method stub
332
333 }
334
335 private boolean checkReply(String reply) throws NetconfException {
336 if (reply != null) {
337 if (!reply.contains("<rpc-error>")) {
338 log.debug("Device {} sent reply {}", deviceInfo, reply);
339 return true;
340 } else if (reply.contains("<ok/>")
341 || (reply.contains("<rpc-error>")
342 && reply.contains("warning"))) {
343 log.debug("Device {} sent reply {}", deviceInfo, reply);
344 return true;
345 }
346 }
347 log.warn("Device {} has error in reply {}", deviceInfo, reply);
348 return false;
349 }
350
351 private String sendRequest(String request) throws NetconfException {
352 log.info("Mocking NETCONF Session send request: \n" + request);
353
354 if (simpleGetConfig.matcher(request).matches()) {
355 return SAMPLE_MSEAEVCUNI_REPLY_INIT;
356
357 } else {
358 throw new NetconfException("MocknetconfSession. No sendRequest() case for query: " +
359 request);
360 }
361 }
362}