X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=netconf%2Fcallhome-provider%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetconf%2Fcallhome%2Fmount%2FCallhomeStatusReporter.java;h=226fd27d78ae5728e34acdeacd09b8c243c94f2b;hb=a3022c29beea055ec8e7cacaa30dd64d5a80887c;hp=ba551202f92713fff13f7c85ed261201585aa91e;hpb=25c72615767a4315c0f519015ff10df1c381d246;p=netconf.git diff --git a/netconf/callhome-provider/src/main/java/org/opendaylight/netconf/callhome/mount/CallhomeStatusReporter.java b/netconf/callhome-provider/src/main/java/org/opendaylight/netconf/callhome/mount/CallhomeStatusReporter.java index ba551202f9..226fd27d78 100644 --- a/netconf/callhome-provider/src/main/java/org/opendaylight/netconf/callhome/mount/CallhomeStatusReporter.java +++ b/netconf/callhome-provider/src/main/java/org/opendaylight/netconf/callhome/mount/CallhomeStatusReporter.java @@ -9,24 +9,24 @@ package org.opendaylight.netconf.callhome.mount; import com.google.common.base.Optional; -import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.ListenableFuture; import java.io.IOException; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; +import java.security.GeneralSecurityException; 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 java.util.concurrent.ExecutionException; +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.netconf.callhome.protocol.StatusRecorder; import org.opendaylight.yang.gen.v1.urn.opendaylight.callhome.device.status.rev170112.Device1; @@ -47,13 +47,11 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology. 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, StatusRecorder, AutoCloseable { private static final InstanceIdentifier NETCONF_TOPO_IID = InstanceIdentifier.create(NetworkTopology.class).child(Topology.class, new TopologyKey(new TopologyId(TopologyNetconf.QNAME.getLocalName()))); @@ -61,45 +59,54 @@ class CallhomeStatusReporter implements DataChangeListener, StatusRecorder, Auto private static final Logger LOG = LoggerFactory.getLogger(CallhomeStatusReporter.class); private final DataBroker dataBroker; - private final ListenerRegistration reg; + private final ListenerRegistration reg; - CallhomeStatusReporter(DataBroker broker) { + CallhomeStatusReporter(final 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, 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(@Nonnull final Collection> changes) { + for (DataTreeModification change: changes) { + final DataObjectModification rootNode = change.getRootNode(); + final InstanceIdentifier 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, 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 static boolean isNetconfNode(final Node node) { + return node.getAugmentation(NetconfNode.class) != null; } - private NodeId getNodeId(final InstanceIdentifier path) { + private static NodeId getNodeId(final InstanceIdentifier path) { NodeKey key = path.firstKeyOf(Node.class); return key != null ? key.getNodeId() : null; } - private void handledNetconfNode(NodeId nodeId, NetconfNode nnode) { + private void handledNetconfNode(final NodeId nodeId, final NetconfNode nnode) { NetconfNodeConnectionStatus.ConnectionStatus csts = nnode.getConnectionStatus(); switch (csts) { @@ -115,7 +122,7 @@ class CallhomeStatusReporter implements DataChangeListener, StatusRecorder, Auto } } - private void handleConnectedNetconfNode(NodeId nodeId) { + private void handleConnectedNetconfNode(final NodeId nodeId) { // Fully connected, all services for remote device are // available from the MountPointService. LOG.debug("NETCONF Node: {} is fully connected", nodeId.getValue()); @@ -125,14 +132,15 @@ class CallhomeStatusReporter implements DataChangeListener, StatusRecorder, Auto LOG.warn("No corresponding callhome device found - exiting."); } else { Device modifiedDevice = withConnectedStatus(opDev); - if (modifiedDevice == null) + if (modifiedDevice == null) { return; + } LOG.info("Setting successful status for callhome device id:{}.", nodeId); writeDevice(nodeId, modifiedDevice); } } - private void handleDisconnectedNetconfNode(NodeId nodeId) { + private void handleDisconnectedNetconfNode(final NodeId nodeId) { LOG.debug("NETCONF Node: {} disconnected", nodeId.getValue()); Device opDev = readAndGetDevice(nodeId); @@ -140,14 +148,15 @@ class CallhomeStatusReporter implements DataChangeListener, StatusRecorder, Auto LOG.warn("No corresponding callhome device found - exiting."); } else { Device modifiedDevice = withDisconnectedStatus(opDev); - if (modifiedDevice == null) + if (modifiedDevice == null) { return; + } LOG.info("Setting disconnected status for callhome device id:{}.", nodeId); writeDevice(nodeId, modifiedDevice); } } - private void handleUnableToConnectNetconfNode(NodeId nodeId) { + private void handleUnableToConnectNetconfNode(final NodeId nodeId) { // The maximum configured number of reconnect attempts // have been reached. No more reconnects will be // attempted by the Netconf Connector. @@ -158,32 +167,32 @@ class CallhomeStatusReporter implements DataChangeListener, StatusRecorder, Auto LOG.warn("No corresponding callhome device found - exiting."); } else { Device modifiedDevice = withFailedStatus(opDev); - if (modifiedDevice == null) + if (modifiedDevice == null) { return; + } LOG.info("Setting failed status for callhome device id:{}.", nodeId); writeDevice(nodeId, modifiedDevice); } } - void asForceListedDevice(String id, PublicKey serverKey) { + void asForceListedDevice(final String id, final PublicKey serverKey) { NodeId nid = new NodeId(id); Device device = newDevice(id, serverKey, Device1.DeviceStatus.DISCONNECTED); writeDevice(nid, device); } - void asUnlistedDevice(String id, PublicKey serverKey) { + void asUnlistedDevice(final String id, final PublicKey serverKey) { NodeId nid = new NodeId(id); Device device = newDevice(id, serverKey, Device1.DeviceStatus.FAILEDNOTALLOWED); writeDevice(nid, device); } - private Device newDevice(String id, PublicKey serverKey, Device1.DeviceStatus status) { + private static Device newDevice(final String id, final PublicKey serverKey, final Device1.DeviceStatus status) { String sshEncodedKey = serverKey.toString(); try { sshEncodedKey = AuthorizedKeysDecoder.encodePublicKey(serverKey); } catch (IOException e) { - e.printStackTrace(); - LOG.warn("Unable to encode public key to ssh format."); + LOG.warn("Unable to encode public key to ssh format.", e); } Device1 d1 = new Device1Builder().setDeviceStatus(Device1.DeviceStatus.FAILEDNOTALLOWED).build(); DeviceBuilder builder = new DeviceBuilder() @@ -195,104 +204,89 @@ class CallhomeStatusReporter implements DataChangeListener, StatusRecorder, Auto return builder.build(); } - private Device readAndGetDevice(NodeId nodeId) { - Optional opDevGet = readDevice(nodeId); - if (opDevGet != null) { - if (opDevGet.isPresent()) { - return opDevGet.get(); - } - } - - return null; + private Device readAndGetDevice(final NodeId nodeId) { + return readDevice(nodeId).orNull(); } - private Optional readDevice(NodeId nodeId) { + @Nonnull + private Optional readDevice(final NodeId nodeId) { ReadOnlyTransaction opTx = dataBroker.newReadOnlyTransaction(); InstanceIdentifier deviceIID = buildDeviceInstanceIdentifier(nodeId); - CheckedFuture, ReadFailedException> devFuture = - opTx.read(LogicalDatastoreType.OPERATIONAL, deviceIID); - + ListenableFuture> devFuture = opTx.read(LogicalDatastoreType.OPERATIONAL, deviceIID); try { - return devFuture.checkedGet(); - } catch (ReadFailedException e) { - return null; + return devFuture.get(); + } catch (InterruptedException | ExecutionException e) { + return Optional.absent(); } } - private void writeDevice(NodeId nodeId, Device modifiedDevice) { + private void writeDevice(final NodeId nodeId, final Device modifiedDevice) { ReadWriteTransaction opTx = dataBroker.newReadWriteTransaction(); opTx.merge(LogicalDatastoreType.OPERATIONAL, buildDeviceInstanceIdentifier(nodeId), modifiedDevice); opTx.submit(); } - private InstanceIdentifier buildDeviceInstanceIdentifier(NodeId nodeId) { + private static InstanceIdentifier buildDeviceInstanceIdentifier(final NodeId nodeId) { return InstanceIdentifier.create(NetconfCallhomeServer.class) .child(AllowedDevices.class) .child(Device.class, new DeviceKey(nodeId.getValue())); } - private Device withConnectedStatus(Device opDev) { + private static Device withConnectedStatus(final Device opDev) { Device1 status = new Device1Builder().setDeviceStatus(Device1.DeviceStatus.CONNECTED).build(); return new DeviceBuilder().addAugmentation(Device1.class, status).setUniqueId(opDev.getUniqueId()) .setSshHostKey(opDev.getSshHostKey()).build(); } - private Device withFailedStatus(Device opDev) { + private static Device withFailedStatus(final Device opDev) { Device1 status = new Device1Builder().setDeviceStatus(Device1.DeviceStatus.FAILED).build(); return new DeviceBuilder().addAugmentation(Device1.class, status).setUniqueId(opDev.getUniqueId()) .setSshHostKey(opDev.getSshHostKey()).build(); } - private Device withDisconnectedStatus(Device opDev) { + private static Device withDisconnectedStatus(final Device opDev) { Device1 status = new Device1Builder().setDeviceStatus(Device1.DeviceStatus.DISCONNECTED).build(); return new DeviceBuilder().addAugmentation(Device1.class, status).setUniqueId(opDev.getUniqueId()) .setSshHostKey(opDev.getSshHostKey()).build(); } - private Device withFailedAuthStatus(Device opDev) { + private static Device withFailedAuthStatus(final Device opDev) { Device1 status = new Device1Builder().setDeviceStatus(Device1.DeviceStatus.FAILEDAUTHFAILURE).build(); return new DeviceBuilder().addAugmentation(Device1.class, status).setUniqueId(opDev.getUniqueId()) .setSshHostKey(opDev.getSshHostKey()).build(); } - private void setDeviceStatus(Device device) { + private void setDeviceStatus(final Device device) { WriteTransaction tx = dataBroker.newWriteOnlyTransaction(); - InstanceIdentifier Device_IID = + InstanceIdentifier deviceIId = InstanceIdentifier.create(NetconfCallhomeServer.class) .child(AllowedDevices.class) .child(Device.class, device.getKey()); - tx.merge(LogicalDatastoreType.OPERATIONAL, Device_IID, device); + tx.merge(LogicalDatastoreType.OPERATIONAL, deviceIId, device); tx.submit(); } - private AllowedDevices getDevices() { ReadOnlyTransaction rxTransaction = dataBroker.newReadOnlyTransaction(); - CheckedFuture, ReadFailedException> devicesFuture = + ListenableFuture> devicesFuture = rxTransaction.read(LogicalDatastoreType.OPERATIONAL, IetfZeroTouchCallHomeServerProvider.ALL_DEVICES); - try { - Optional opt = devicesFuture.checkedGet(); - if (opt.isPresent()) { - AllowedDevices devices = opt.get(); - return devices; - } - } catch (ReadFailedException e) { + return devicesFuture.get().orNull(); + } catch (ExecutionException | InterruptedException e) { LOG.error("Error trying to read the whitelist devices: {}", e); + return null; } - - return null; } private List getDevicesAsList() { AllowedDevices devices = getDevices(); - return (devices == null) ? new ArrayList() : devices.getDevice(); + return devices == null ? new ArrayList<>() : devices.getDevice(); } @Override - public void reportFailedAuth(PublicKey sshKey) { + public void reportFailedAuth(final PublicKey sshKey) { AuthorizedKeysDecoder decoder = new AuthorizedKeysDecoder(); for (Device device : getDevicesAsList()) { @@ -302,13 +296,14 @@ class CallhomeStatusReporter implements DataChangeListener, StatusRecorder, Auto PublicKey pubKey = decoder.decodePublicKey(keyString); if (sshKey.getAlgorithm().equals(pubKey.getAlgorithm()) && sshKey.equals(pubKey)) { Device failedDevice = withFailedAuthStatus(device); - if (failedDevice == null) + if (failedDevice == null) { return; + } LOG.info("Setting auth failed status for callhome device id:{}.", failedDevice.getUniqueId()); setDeviceStatus(failedDevice); return; } - } catch (InvalidKeySpecException | NoSuchAlgorithmException | NoSuchProviderException e) { + } catch (GeneralSecurityException e) { LOG.error("Failed decoding a device key with host key: {} {}", keyString, e); return; }