import akka.actor.ActorContext;
import akka.actor.ActorRef;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
import io.netty.util.concurrent.EventExecutor;
import java.util.Collection;
import javax.annotation.Nonnull;
import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
import org.opendaylight.netconf.topology.AbstractNetconfTopology;
import org.opendaylight.netconf.topology.SchemaRepositoryProvider;
import org.opendaylight.netconf.topology.pipeline.TopologyMountPointFacade.ConnectionStatusListenerRegistration;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopologyBuilder;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public void onSessionInitiated(ProviderContext session) {
dataBroker = session.getSALService(DataBroker.class);
- LOG.warn("Registering datastore listener");
+ final WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+ initTopology(wtx, LogicalDatastoreType.CONFIGURATION);
+ initTopology(wtx, LogicalDatastoreType.OPERATIONAL);
+ Futures.addCallback(wtx.submit(), new FutureCallback<Void>() {
+ @Override
+ public void onSuccess(Void result) {
+ LOG.debug("topology initialization successful");
+ }
+
+ @Override
+ public void onFailure(Throwable t) {
+ LOG.error("Unable to initialize netconf-topology, {}", t);
+ }
+ });
+
+ LOG.debug("Registering datastore listener");
datastoreListenerRegistration =
dataBroker.registerDataTreeChangeListener(
new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, createTopologyId(topologyId).child(Node.class)), this);
+
+
}
@Override
}
}
+ private void initTopology(final WriteTransaction wtx, final LogicalDatastoreType datastoreType) {
+ final NetworkTopology networkTopology = new NetworkTopologyBuilder().build();
+ final InstanceIdentifier<NetworkTopology> networkTopologyId = InstanceIdentifier.builder(NetworkTopology.class).build();
+ wtx.merge(datastoreType, networkTopologyId, networkTopology);
+ final Topology topology = new TopologyBuilder().setTopologyId(new TopologyId(topologyId)).build();
+ wtx.merge(datastoreType, networkTopologyId.child(Topology.class, new TopologyKey(new TopologyId(topologyId))), topology);
+ }
+
}
// write an empty topology container at the start
final WriteTransaction wTx = txChain.newWriteOnlyTransaction();
- createNetworkTopologyIfNotPresent(wTx);
+ createNetworkTopologyIfNotPresent(wTx, LogicalDatastoreType.OPERATIONAL);
+ createNetworkTopologyIfNotPresent(wTx, LogicalDatastoreType.CONFIGURATION);
commitTransaction(wTx, "init topology container", new NodeId("topology-netconf"));
}
try {
final WriteTransaction writeTx = txChain.newWriteOnlyTransaction();
- createNetworkTopologyIfNotPresent(writeTx);
+ createNetworkTopologyIfNotPresent(writeTx, LogicalDatastoreType.OPERATIONAL);
final InstanceIdentifier<Node> path = createBindingPathForTopology(new NodeKey(id), topologyId);
LOG.trace("{}: Init device state transaction {} putting if absent operational data started. Putting data on path {}",
});
}
- private void createNetworkTopologyIfNotPresent(final WriteTransaction writeTx) {
+ private void createNetworkTopologyIfNotPresent(final WriteTransaction writeTx, final LogicalDatastoreType datastoreType) {
final NetworkTopology networkTopology = new NetworkTopologyBuilder().build();
LOG.trace("{}: Merging {} container to ensure its presence", topologyId,
NetworkTopology.QNAME, writeTx.getIdentifier());
- writeTx.merge(LogicalDatastoreType.OPERATIONAL, networkTopologyPath, networkTopology);
+ writeTx.merge(datastoreType, networkTopologyPath, networkTopology);
final Topology topology = new TopologyBuilder().setTopologyId(new TopologyId(topologyId)).build();
LOG.trace("{}: Merging {} container to ensure its presence", topologyId,
Topology.QNAME, writeTx.getIdentifier());
- writeTx.merge(LogicalDatastoreType.OPERATIONAL, topologyListPath, topology);
+ writeTx.merge(datastoreType, topologyListPath, topology);
}
private static InstanceIdentifier<Node> createBindingPathForTopology(final NodeKey key, final String topologyId) {
import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_RPC_QNAME;
import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_URI;
import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.toPath;
-
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import java.util.Date;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import javax.annotation.Nonnull;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
// We wrap the notification as a container node in order to reuse the parsers and builders for container node
final ContainerSchemaNode notificationAsContainerSchemaNode = NetconfMessageTransformUtil.createSchemaForNotification(next);
- final ContainerNode content = parserFactory.getContainerNodeParser().parse(Collections.singleton(stripped.getValue().getDomElement()),
+
+ final Element element = stripped.getValue().getDomElement();
+ final ContainerNode content;
+ try {
+ content = parserFactory.getContainerNodeParser().parse(Collections.singleton(element),
notificationAsContainerSchemaNode);
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException(String.format("Failed to parse notification %s", element), e);
+ }
return new NetconfDeviceNotification(content, stripped.getKey());
}
private static final ThreadLocal<SimpleDateFormat> EVENT_TIME_FORMAT = new ThreadLocal<SimpleDateFormat>() {
+ @Override
protected SimpleDateFormat initialValue() {
final SimpleDateFormat withMillis = new SimpleDateFormat(
NetconfNotification.RFC3339_DATE_FORMAT_WITH_MILLIS_BLUEPRINT);
return new SimpleDateFormat(NetconfNotification.RFC3339_DATE_FORMAT_BLUEPRINT) {
+ private static final long serialVersionUID = 1L;
+
@Override public Date parse(final String source) throws ParseException {
try {
return super.parse(source);
};
}
- public void set(SimpleDateFormat value) {
+ @Override
+ public void set(final SimpleDateFormat value) {
throw new UnsupportedOperationException();
}
};
"Transforming an rpc with input: %s, payload has to be a container, but was: %s", rpcQName, payload);
// Set the path to the input of rpc for the node stream writer
- rpc = rpc.createChild(QName.cachedReference(QName.create(rpcQName, "input")));
+ rpc = rpc.createChild(QName.create(rpcQName, "input").intern());
final DOMResult result = prepareDomResultForRpcRequest(rpcQName);
try {
return new DOMResult(elementNS);
}
- private void writeNormalizedRpc(final ContainerNode normalized, final DOMResult result, final SchemaPath schemaPath, final SchemaContext baseNetconfCtx) throws IOException, XMLStreamException {
- final OrderedNormalizedNodeWriter normalizedNodeWriter;
- NormalizedNodeStreamWriter normalizedNodeStreamWriter = null;
- XMLStreamWriter writer = null;
+ private static void writeNormalizedRpc(final ContainerNode normalized, final DOMResult result,
+ final SchemaPath schemaPath, final SchemaContext baseNetconfCtx) throws IOException, XMLStreamException {
+ final XMLStreamWriter writer = NetconfMessageTransformUtil.XML_FACTORY.createXMLStreamWriter(result);
try {
- writer = NetconfMessageTransformUtil.XML_FACTORY.createXMLStreamWriter(result);
- normalizedNodeStreamWriter = XMLStreamNormalizedNodeStreamWriter.create(writer, baseNetconfCtx, schemaPath);
- normalizedNodeWriter = new OrderedNormalizedNodeWriter(normalizedNodeStreamWriter, baseNetconfCtx, schemaPath);
- Collection<DataContainerChild<?, ?>> value = (Collection) normalized.getValue();
- normalizedNodeWriter.write(value);
- normalizedNodeWriter.flush();
+ try (final NormalizedNodeStreamWriter normalizedNodeStreamWriter =
+ XMLStreamNormalizedNodeStreamWriter.create(writer, baseNetconfCtx, schemaPath)) {
+ try (final OrderedNormalizedNodeWriter normalizedNodeWriter =
+ new OrderedNormalizedNodeWriter(normalizedNodeStreamWriter, baseNetconfCtx, schemaPath)) {
+ Collection<DataContainerChild<?, ?>> value = normalized.getValue();
+ normalizedNodeWriter.write(value);
+ normalizedNodeWriter.flush();
+ }
+ }
} finally {
try {
- if(normalizedNodeStreamWriter != null) {
- normalizedNodeStreamWriter.close();
- }
- if(writer != null) {
- writer.close();
- }
+ writer.close();
} catch (final Exception e) {
LOG.warn("Unable to close resource properly", e);
}
if (NetconfMessageTransformUtil.isDataRetrievalOperation(rpcQName)) {
final Element xmlData = NetconfMessageTransformUtil.getDataSubtree(message.getDocument());
final ContainerSchemaNode schemaForDataRead = NetconfMessageTransformUtil.createSchemaForDataRead(schemaContext);
- final ContainerNode dataNode = parserFactory.getContainerNodeParser().parse(Collections.singleton(xmlData), schemaForDataRead);
+ final ContainerNode dataNode;
+
+ try {
+ dataNode = parserFactory.getContainerNodeParser().parse(Collections.singleton(xmlData), schemaForDataRead);
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException(String.format("Failed to parse data response %s", xmlData), e);
+ }
normalizedNode = Builders.containerBuilder().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(NetconfMessageTransformUtil.NETCONF_RPC_REPLY_QNAME))
.withChild(dataNode).build();
} else {
- final Set<Element> documentElement = Collections.singleton(message.getDocument().getDocumentElement());
Map<QName, RpcDefinition> currentMappedRpcs = mappedRpcs;
// In case no input for rpc is defined, we can simply construct the payload here
if (rpcDefinition.getOutput() == null) {
- Preconditions.checkArgument(XmlElement.fromDomDocument(message.getDocument()).getOnlyChildElementWithSameNamespaceOptionally("ok").isPresent(),
- "Unexpected content in response of rpc: %s, %s", rpcDefinition.getQName(), message);
+ Preconditions.checkArgument(XmlElement.fromDomDocument(
+ message.getDocument()).getOnlyChildElementWithSameNamespaceOptionally("ok").isPresent(),
+ "Unexpected content in response of rpc: %s, %s", rpcDefinition.getQName(), message);
normalizedNode = null;
} else {
- normalizedNode = parserFactory.getContainerNodeParser().parse(documentElement, rpcDefinition.getOutput());
+ final Element element = message.getDocument().getDocumentElement();
+ try {
+ normalizedNode = parserFactory.getContainerNodeParser().parse(Collections.singleton(element),
+ rpcDefinition.getOutput());
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException(String.format("Failed to parse RPC response %s", element), e);
+ }
}
}
return new DefaultDOMRpcResult(normalizedNode);