blob: cc0640741c852da36318b3ad09251ac17e06ccdd [file] [log] [blame]
/*
* 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);
}
}
}