import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
-import java.util.Map;
import javax.annotation.Nonnull;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+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.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
import org.opendaylight.netconf.callhome.protocol.AuthorizedKeysDecoder;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-class CallhomeStatusReporter implements DataChangeListener, StatusRecorder, AutoCloseable {
+class CallhomeStatusReporter implements DataTreeChangeListener<Node>, StatusRecorder, AutoCloseable {
private static final InstanceIdentifier<Topology> NETCONF_TOPO_IID =
InstanceIdentifier.create(NetworkTopology.class).child(Topology.class,
new TopologyKey(new TopologyId(TopologyNetconf.QNAME.getLocalName())));
private static final Logger LOG = LoggerFactory.getLogger(CallhomeStatusReporter.class);
private final DataBroker dataBroker;
- private final ListenerRegistration<DataChangeListener> reg;
+ private final ListenerRegistration<CallhomeStatusReporter> reg;
CallhomeStatusReporter(DataBroker broker) {
this.dataBroker = broker;
- this.reg = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
- NETCONF_TOPO_IID.child(Node.class), this, AsyncDataBroker.DataChangeScope.SUBTREE);
+ this.reg = dataBroker.registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
+ NETCONF_TOPO_IID.child(Node.class)), this);
}
@Override
- public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
- for (InstanceIdentifier<?> removedPath : change.getRemovedPaths()) {
- if (removedPath.getTargetType() != NetconfNode.class) {
- continue;
- }
-
- final NodeId nodeId = getNodeId(removedPath);
- if (nodeId != null) {
- handleDisconnectedNetconfNode(nodeId);
- return;
+ public void onDataTreeChanged(Collection<DataTreeModification<Node>> changes) {
+ for (DataTreeModification<Node> change: changes) {
+ final DataObjectModification<Node> rootNode = change.getRootNode();
+ final InstanceIdentifier<Node> identifier = change.getRootPath().getRootIdentifier();
+ switch (rootNode.getModificationType()) {
+ case WRITE:
+ case SUBTREE_MODIFIED:
+ if (isNetconfNode(rootNode.getDataAfter())) {
+ NodeId nodeId = getNodeId(identifier);
+ if (nodeId != null) {
+ NetconfNode nnode = rootNode.getDataAfter().getAugmentation(NetconfNode.class);
+ handledNetconfNode(nodeId, nnode);
+ }
+ }
+ break;
+ case DELETE:
+ if (isNetconfNode(rootNode.getDataBefore())) {
+ final NodeId nodeId = getNodeId(identifier);
+ if (nodeId != null) {
+ handleDisconnectedNetconfNode(nodeId);
+ }
+ }
+ break;
+ default:
+ break;
}
}
+ }
- for (Map.Entry<InstanceIdentifier<?>, DataObject> entry : change.getUpdatedData().entrySet()) {
- if (entry.getKey().getTargetType() == NetconfNode.class) {
- NodeId nodeId = getNodeId(entry.getKey());
- if (nodeId != null) {
- NetconfNode nnode = (NetconfNode) entry.getValue();
- handledNetconfNode(nodeId, nnode);
- return;
- }
- }
- }
+ private boolean isNetconfNode(Node node) {
+ return node.getAugmentation(NetconfNode.class) != null;
}
private NodeId getNodeId(final InstanceIdentifier<?> path) {
private List<Device> getDevicesAsList() {
AllowedDevices devices = getDevices();
- return (devices == null) ? new ArrayList<Device>() : devices.getDevice();
+ return devices == null ? new ArrayList<>() : devices.getDevice();
}
@Override
package org.opendaylight.netconf.callhome.mount;
-import static com.google.common.base.Preconditions.checkArgument;
-
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.util.concurrent.CheckedFuture;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+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.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
import org.opendaylight.netconf.callhome.protocol.CallHomeAuthorizationProvider;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconf.callhome.server.rev161109.netconf.callhome.server.allowed.devices.DeviceBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconf.callhome.server.rev161109.netconf.callhome.server.allowed.devices.DeviceKey;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class IetfZeroTouchCallHomeServerProvider implements AutoCloseable, DataChangeListener {
+public class IetfZeroTouchCallHomeServerProvider implements AutoCloseable, DataTreeChangeListener<AllowedDevices> {
private static final String APPNAME = "CallHomeServer";
static final InstanceIdentifier<AllowedDevices> ALL_DEVICES = InstanceIdentifier.create(NetconfCallhomeServer.class)
.child(AllowedDevices.class);
private final DataBroker dataBroker;
private final CallHomeMountDispatcher mountDispacher;
- private CallHomeAuthProviderImpl authProvider;
+ private final CallHomeAuthProviderImpl authProvider;
protected NetconfCallHomeServer server;
private static final String CALL_HOME_PORT_KEY = "DefaultCallHomePort";
private int port = 0; // 0 = use default in NetconfCallHomeBuilder
- private CallhomeStatusReporter statusReporter;
+ private final CallhomeStatusReporter statusReporter;
public IetfZeroTouchCallHomeServerProvider(DataBroker dataBroker, CallHomeMountDispatcher mountDispacher) {
this.dataBroker = dataBroker;
try {
LOG.info("Initializing provider for {}", APPNAME);
initializeServer();
- dataBroker.registerDataChangeListener(
- LogicalDatastoreType.CONFIGURATION, ALL_DEVICES, this, AsyncDataBroker.DataChangeScope.SUBTREE);
+ listenerReg = dataBroker.registerDataTreeChangeListener(new DataTreeIdentifier<>(
+ LogicalDatastoreType.CONFIGURATION, ALL_DEVICES), this);
LOG.info("Initialization complete for {}", APPNAME);
} catch (IOException | Configuration.ConfigurationException e) {
LOG.error("Unable to successfully initialize", e);
}
@Override
- public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
-
+ public void onDataTreeChanged(Collection<DataTreeModification<AllowedDevices>> changes) {
// In case of any changes to the devices datatree, register the changed values with callhome server
// As of now, no way to add a new callhome client key to the CallHomeAuthorization instance since
// its created under CallHomeAuthorizationProvider.
CheckedFuture<Optional<AllowedDevices>, ReadFailedException> devicesFuture =
roConfigTx.read(LogicalDatastoreType.CONFIGURATION, IetfZeroTouchCallHomeServerProvider.ALL_DEVICES);
- if (hasDeletedDevices(change)) {
- handleDeletedDevices(change);
+ Set<InstanceIdentifier<?>> deletedDevices = new HashSet<>();
+ for (DataTreeModification<AllowedDevices> change: changes) {
+ DataObjectModification<AllowedDevices> rootNode = change.getRootNode();
+ switch (rootNode.getModificationType()) {
+ case DELETE:
+ deletedDevices.add(change.getRootPath().getRootIdentifier());
+ break;
+ default:
+ break;
+ }
}
+ handleDeletedDevices(deletedDevices);
+
try {
for (Device confDevice : getReadDevices(devicesFuture)) {
readAndUpdateStatus(confDevice);
}
}
- private boolean hasDeletedDevices(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
- return change.getRemovedPaths() != null;
- }
-
- private void handleDeletedDevices(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
- checkArgument(change.getRemovedPaths() != null);
+ private void handleDeletedDevices(Set<InstanceIdentifier<?>> deletedDevices) {
+ if (deletedDevices.isEmpty()) {
+ return;
+ }
ReadWriteTransaction opTx = dataBroker.newReadWriteTransaction();
- Set<InstanceIdentifier<?>> removedDevices = change.getRemovedPaths();
- int numRemoved = removedDevices.size();
+ int numRemoved = deletedDevices.size();
- Iterator<InstanceIdentifier<?>> iterator = removedDevices.iterator();
+ Iterator<InstanceIdentifier<?>> iterator = deletedDevices.iterator();
while (iterator.hasNext()) {
InstanceIdentifier<?> removedIID = iterator.next();
LOG.info("Deleting the entry for callhome device {}", removedIID);