| /* |
| * Copyright 2016-present Open Networking Laboratory |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.onosproject.drivers.netconf; |
| |
| import java.util.List; |
| import java.util.concurrent.CompletableFuture; |
| import java.util.concurrent.atomic.AtomicInteger; |
| import java.util.regex.Pattern; |
| |
| import org.onosproject.netconf.NetconfDeviceInfo; |
| import org.onosproject.netconf.NetconfDeviceOutputEventListener; |
| import org.onosproject.netconf.NetconfException; |
| import org.onosproject.netconf.NetconfSession; |
| import org.onosproject.netconf.TargetConfig; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| public class MockNetconfSession implements NetconfSession { |
| private static final Logger log = LoggerFactory |
| .getLogger(MockNetconfSession.class); |
| |
| private static final String MESSAGE_ID_STRING = "message-id"; |
| private static final String EQUAL = "="; |
| private static final String RPC_OPEN = "<rpc "; |
| private static final String RPC_CLOSE = "</rpc>"; |
| private static final String GET_OPEN = "<get>"; |
| private static final String GET_CLOSE = "</get>"; |
| private static final String NEW_LINE = "\n"; |
| private static final String SUBTREE_FILTER_OPEN = "<filter type=\"subtree\">"; |
| private static final String SUBTREE_FILTER_CLOSE = "</filter>"; |
| private static final String WITH_DEFAULT_OPEN = "<with-defaults "; |
| private static final String WITH_DEFAULT_CLOSE = "</with-defaults>"; |
| private static final String EDIT_CONFIG_OPEN = "<edit-config>"; |
| private static final String EDIT_CONFIG_CLOSE = "</edit-config>"; |
| private static final String COPY_CONFIG_OPEN = "<copy-config>"; |
| private static final String COPY_CONFIG_CLOSE = "</copy-config>"; |
| private static final String DELETE_CONFIG_OPEN = "<delete-config>"; |
| private static final String DELETE_CONFIG_CLOSE = "</delete-config>"; |
| private static final String TARGET_OPEN = "<target>"; |
| private static final String TARGET_CLOSE = "</target>"; |
| private static final String SOURCE_OPEN = "<source>"; |
| private static final String SOURCE_CLOSE = "</source>"; |
| private static final String DEFAULT_OPERATION_OPEN = "<default-operation>"; |
| private static final String DEFAULT_OPERATION_CLOSE = "</default-operation>"; |
| private static final String CONFIG_OPEN = "<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">"; |
| private static final String CONFIG_CLOSE = "</config>"; |
| |
| private static final String ENDPATTERN = "]]>]]>"; |
| private static final String XML_HEADER = |
| "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; |
| private static final String NETCONF_BASE_NAMESPACE = |
| "xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\""; |
| private static final String NETCONF_WITH_DEFAULTS_NAMESPACE = |
| "xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\""; |
| |
| private Pattern simpleGetConfig = |
| Pattern.compile("(<\\?xml version=\"1.0\" encoding=\"UTF-8\"\\?>)\\R?" |
| + "(<rpc message-id=\")[0-9]*(\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?" |
| + "(<get-config>)\\R?" |
| + "(<source>)\\R?(<running/>)\\R?(</source>)\\R?" |
| + "(</get-config>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL); |
| |
| private static final String SAMPLE_MSEAEVCUNI_REPLY_INIT = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| + "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"1\">\n" |
| + "<data xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n" |
| + "</data>\n" |
| + "</rpc-reply>"; |
| |
| |
| |
| private NetconfDeviceInfo deviceInfo; |
| |
| private final AtomicInteger messageIdInteger = new AtomicInteger(0); |
| |
| public MockNetconfSession(NetconfDeviceInfo deviceInfo) throws NetconfException { |
| this.deviceInfo = deviceInfo; |
| } |
| |
| @Override |
| public CompletableFuture<String> request(String request) throws NetconfException { |
| throw new NetconfException("Should be calling a higher level command or one that sets the message id"); |
| } |
| |
| @Override |
| public String get(String request) throws NetconfException { |
| |
| return sendRequest(request); |
| } |
| |
| @Override |
| public String get(String filterSchema, String withDefaultsMode) throws NetconfException { |
| StringBuilder rpc = new StringBuilder(XML_HEADER); |
| rpc.append(RPC_OPEN); |
| rpc.append(MESSAGE_ID_STRING); |
| rpc.append(EQUAL); |
| rpc.append("\""); |
| rpc.append(messageIdInteger.get()); |
| rpc.append("\" "); |
| rpc.append(NETCONF_BASE_NAMESPACE).append(">\n"); |
| rpc.append(GET_OPEN).append(NEW_LINE); |
| if (filterSchema != null) { |
| rpc.append(SUBTREE_FILTER_OPEN).append(NEW_LINE); |
| rpc.append(filterSchema).append(NEW_LINE); |
| rpc.append(SUBTREE_FILTER_CLOSE).append(NEW_LINE); |
| } |
| if (withDefaultsMode != null) { |
| rpc.append(WITH_DEFAULT_OPEN).append(NETCONF_WITH_DEFAULTS_NAMESPACE).append(">"); |
| rpc.append(withDefaultsMode).append(WITH_DEFAULT_CLOSE).append(NEW_LINE); |
| } |
| rpc.append(GET_CLOSE).append(NEW_LINE); |
| rpc.append(RPC_CLOSE).append(NEW_LINE); |
| rpc.append(ENDPATTERN); |
| String reply = sendRequest(rpc.toString()); |
| checkReply(reply); |
| return reply; |
| } |
| |
| @Override |
| public String doWrappedRpc(String request) throws NetconfException { |
| StringBuilder rpc = new StringBuilder(XML_HEADER); |
| rpc.append(RPC_OPEN); |
| rpc.append(MESSAGE_ID_STRING); |
| rpc.append(EQUAL); |
| rpc.append("\""); |
| rpc.append(messageIdInteger.get()); |
| rpc.append("\" "); |
| rpc.append(NETCONF_BASE_NAMESPACE).append(">\n"); |
| rpc.append(request); |
| rpc.append(RPC_CLOSE).append(NEW_LINE); |
| rpc.append(ENDPATTERN); |
| String reply = sendRequest(rpc.toString()); |
| checkReply(reply); |
| return reply; |
| } |
| |
| @Override |
| public String requestSync(String request) throws NetconfException { |
| if (!request.contains(ENDPATTERN)) { |
| request = request + NEW_LINE + ENDPATTERN; |
| } |
| String reply = sendRequest(request); |
| checkReply(reply); |
| return reply; |
| } |
| |
| |
| @Override |
| public String getConfig(String targetConfiguration, String configurationSchema) throws NetconfException { |
| return getConfig(TargetConfig.valueOf(targetConfiguration)); |
| } |
| |
| @Override |
| public String getConfig(String targetConfiguration) throws NetconfException { |
| return getConfig(TargetConfig.valueOf(targetConfiguration), null); |
| } |
| |
| @Override |
| public String getConfig(TargetConfig netconfTargetConfig) |
| throws NetconfException { |
| return getConfig(netconfTargetConfig, null); |
| } |
| |
| @Override |
| public String getConfig(TargetConfig netconfTargetConfig, String configurationFilterSchema) |
| throws NetconfException { |
| StringBuilder rpc = new StringBuilder(XML_HEADER); |
| rpc.append("<rpc "); |
| rpc.append(MESSAGE_ID_STRING); |
| rpc.append(EQUAL); |
| rpc.append("\""); |
| rpc.append(messageIdInteger.get()); |
| rpc.append("\" "); |
| rpc.append("xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"); |
| rpc.append("<get-config>\n"); |
| rpc.append("<source>\n"); |
| rpc.append("<").append(netconfTargetConfig).append("/>"); |
| rpc.append("</source>"); |
| if (netconfTargetConfig != null) { |
| rpc.append("<filter type=\"subtree\">\n"); |
| rpc.append(configurationFilterSchema).append("\n"); |
| rpc.append("</filter>\n"); |
| } |
| rpc.append("</get-config>\n"); |
| rpc.append("</rpc>\n"); |
| rpc.append(ENDPATTERN); |
| String reply = sendRequest(rpc.toString()); |
| return checkReply(reply) ? reply : "ERROR " + reply; |
| } |
| |
| @Override |
| public boolean editConfig(TargetConfig netconfTargetConfig, String mode, String newConfiguration) |
| throws NetconfException { |
| newConfiguration = newConfiguration.trim(); |
| StringBuilder rpc = new StringBuilder(XML_HEADER); |
| rpc.append(RPC_OPEN); |
| rpc.append(MESSAGE_ID_STRING); |
| rpc.append(EQUAL); |
| rpc.append("\""); |
| rpc.append(messageIdInteger.get()); |
| rpc.append("\" "); |
| rpc.append(NETCONF_BASE_NAMESPACE).append(">\n"); |
| rpc.append(EDIT_CONFIG_OPEN).append("\n"); |
| rpc.append(TARGET_OPEN); |
| rpc.append("<").append(netconfTargetConfig).append("/>"); |
| rpc.append(TARGET_CLOSE).append("\n"); |
| if (mode != null) { |
| rpc.append(DEFAULT_OPERATION_OPEN); |
| rpc.append(mode); |
| rpc.append(DEFAULT_OPERATION_CLOSE).append("\n"); |
| } |
| rpc.append(CONFIG_OPEN).append("\n"); |
| rpc.append(newConfiguration); |
| rpc.append(CONFIG_CLOSE).append("\n"); |
| rpc.append(EDIT_CONFIG_CLOSE).append("\n"); |
| rpc.append(RPC_CLOSE); |
| rpc.append(ENDPATTERN); |
| log.debug(rpc.toString()); |
| String reply = sendRequest(rpc.toString()); |
| return checkReply(reply); |
| } |
| |
| @Override |
| public boolean editConfig(String newConfiguration) throws NetconfException { |
| return editConfig(TargetConfig.RUNNING, null, newConfiguration); |
| } |
| |
| @Override |
| public boolean editConfig(String targetConfiguration, String mode, String newConfiguration) |
| throws NetconfException { |
| return editConfig(TargetConfig.valueOf(targetConfiguration), mode, newConfiguration); |
| } |
| |
| @Override |
| public boolean copyConfig(TargetConfig netconfTargetConfig, String newConfiguration) throws NetconfException { |
| newConfiguration = newConfiguration.trim(); |
| StringBuilder rpc = new StringBuilder(XML_HEADER); |
| rpc.append(RPC_OPEN); |
| rpc.append(MESSAGE_ID_STRING); |
| rpc.append(EQUAL); |
| rpc.append("\""); |
| rpc.append(messageIdInteger.get()); |
| rpc.append("\" "); |
| rpc.append(NETCONF_BASE_NAMESPACE).append(">\n"); |
| rpc.append(COPY_CONFIG_OPEN).append("\n"); |
| rpc.append(TARGET_OPEN); |
| rpc.append("<").append(netconfTargetConfig).append("/>"); |
| rpc.append(TARGET_CLOSE).append("\n"); |
| rpc.append(SOURCE_OPEN); |
| rpc.append("<").append(newConfiguration).append("/>"); |
| rpc.append(SOURCE_CLOSE).append("\n"); |
| rpc.append(COPY_CONFIG_CLOSE).append("\n"); |
| rpc.append(RPC_CLOSE); |
| rpc.append(ENDPATTERN); |
| log.debug(rpc.toString()); |
| String reply = sendRequest(rpc.toString()); |
| return checkReply(reply); |
| } |
| |
| @Override |
| public boolean copyConfig(String targetConfiguration, String newConfiguration) throws NetconfException { |
| return copyConfig(TargetConfig.valueOf(targetConfiguration), newConfiguration); |
| } |
| |
| @Override |
| public boolean deleteConfig(TargetConfig netconfTargetConfig) throws NetconfException { |
| StringBuilder rpc = new StringBuilder(XML_HEADER); |
| rpc.append(RPC_OPEN); |
| rpc.append(MESSAGE_ID_STRING); |
| rpc.append(EQUAL); |
| rpc.append("\""); |
| rpc.append(messageIdInteger.get()); |
| rpc.append("\" "); |
| rpc.append(NETCONF_BASE_NAMESPACE).append(">\n"); |
| rpc.append(DELETE_CONFIG_OPEN).append("\n"); |
| rpc.append(TARGET_OPEN); |
| rpc.append("<").append(netconfTargetConfig).append("/>"); |
| rpc.append(TARGET_CLOSE).append("\n"); |
| rpc.append(DELETE_CONFIG_CLOSE).append("\n"); |
| rpc.append(RPC_CLOSE); |
| rpc.append(ENDPATTERN); |
| log.debug(rpc.toString()); |
| String reply = sendRequest(rpc.toString()); |
| return checkReply(reply); |
| } |
| |
| @Override |
| public boolean deleteConfig(String targetConfiguration) throws NetconfException { |
| return deleteConfig(TargetConfig.valueOf(targetConfiguration)); |
| } |
| |
| @Override |
| public void startSubscription() throws NetconfException { |
| // TODO Auto-generated method stub |
| |
| } |
| |
| @Override |
| public void startSubscription(String filterSchema) throws NetconfException { |
| // TODO Auto-generated method stub |
| |
| } |
| |
| @Override |
| public void endSubscription() throws NetconfException { |
| // TODO Auto-generated method stub |
| |
| } |
| |
| @Override |
| public boolean lock(String configType) throws NetconfException { |
| // TODO Auto-generated method stub |
| return false; |
| } |
| |
| @Override |
| public boolean unlock(String configType) throws NetconfException { |
| // TODO Auto-generated method stub |
| return false; |
| } |
| |
| @Override |
| public boolean lock() throws NetconfException { |
| // TODO Auto-generated method stub |
| return false; |
| } |
| |
| @Override |
| public boolean unlock() throws NetconfException { |
| // TODO Auto-generated method stub |
| return false; |
| } |
| |
| @Override |
| public boolean close() throws NetconfException { |
| // TODO Auto-generated method stub |
| return false; |
| } |
| |
| @Override |
| public String getSessionId() { |
| return "mockSessionId"; |
| } |
| |
| @Override |
| public String getServerCapabilities() { |
| // TODO Auto-generated method stub |
| return null; |
| } |
| |
| @Override |
| public void setDeviceCapabilities(List<String> capabilities) { |
| // TODO Auto-generated method stub |
| |
| } |
| |
| @Override |
| public void addDeviceOutputListener(NetconfDeviceOutputEventListener listener) { |
| // TODO Auto-generated method stub |
| |
| } |
| |
| @Override |
| public void removeDeviceOutputListener(NetconfDeviceOutputEventListener listener) { |
| // TODO Auto-generated method stub |
| |
| } |
| |
| private boolean checkReply(String reply) throws NetconfException { |
| if (reply != null) { |
| if (!reply.contains("<rpc-error>")) { |
| log.debug("Device {} sent reply {}", deviceInfo, reply); |
| return true; |
| } else if (reply.contains("<ok/>") |
| || (reply.contains("<rpc-error>") |
| && reply.contains("warning"))) { |
| log.debug("Device {} sent reply {}", deviceInfo, reply); |
| return true; |
| } |
| } |
| log.warn("Device {} has error in reply {}", deviceInfo, reply); |
| return false; |
| } |
| |
| private String sendRequest(String request) throws NetconfException { |
| log.info("Mocking NETCONF Session send request: \n" + request); |
| |
| if (simpleGetConfig.matcher(request).matches()) { |
| return SAMPLE_MSEAEVCUNI_REPLY_INIT; |
| |
| } else { |
| throw new NetconfException("MocknetconfSession. No sendRequest() case for query: " + |
| request); |
| } |
| } |
| } |