/* * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus.Connected; import static org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus.Connecting; import static org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus.UnableToConnect; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import javax.annotation.Nonnull; import org.junit.Before; import org.junit.Test; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.MountPointService; 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.LogicalDatastoreType; import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker; import org.opendaylight.groupbasedpolicy.test.CustomDataBrokerTest; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.Renderers; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererNodes; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNode; import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode; import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus; import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.AvailableCapabilities; import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.AvailableCapabilitiesBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability; import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapabilityBuilder; 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.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.TopologyKey; 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.NodeBuilder; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import com.google.common.base.Optional; import com.google.common.util.concurrent.CheckedFuture; public class NodeManagerTest extends CustomDataBrokerTest { private final NodeId NODE_NAME = new NodeId("testNode"); private final TopologyId TOPOLOGY_ID = new TopologyId("topology-netconf"); private final Ipv4Address IPv4_ADDRESS = new Ipv4Address("174.25.75.11"); private NodeManager nodeManager; private DataBroker dataBroker; @Nonnull @Override public Collection<java.lang.Class<?>> getClassesFromModules() { return Arrays.asList(Renderers.class, NetworkTopology.class, NetconfNode.class); } @Before public void init() { dataBroker = getDataBroker(); BindingAwareBroker.ProviderContext context = mock(BindingAwareBroker.ProviderContext.class); MountPointService mountPointService = mock(MountPointService.class); when(context.getSALService(any())).thenReturn(mountPointService); nodeManager = new NodeManager(dataBroker, context); } @Test public void testRegisterNewNode_connectingCase() throws Exception { Node testNode = createNode(Connecting, IPv4_ADDRESS, NODE_NAME, Capabilities.Full); nodeManager.syncNodes(testNode, null); List<RendererNode> result = rendererNodesReader(); assertTrue(result.isEmpty()); } // Create Cases @Test public void testRegisterNewNode_connectedCaseNoIpAddress() throws Exception { Node testNode = createNode(Connected, null, NODE_NAME, Capabilities.None); nodeManager.syncNodes(testNode, null); List<RendererNode> result = rendererNodesReader(); assertTrue(result.isEmpty()); } @Test public void testRegisterNewNode_connectedCaseNullCapabilities() throws Exception { Node testNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.None); nodeManager.syncNodes(testNode, null); List<RendererNode> result = rendererNodesReader(); assertTrue(result.isEmpty()); } @Test public void testRegisterNewNode_connectedCasePartialCapabilities() throws Exception { Node testNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Partial); nodeManager.syncNodes(testNode, null); List<RendererNode> result = rendererNodesReader(); assertTrue(result.isEmpty()); } @Test public void testRegisterNewNode_connectedCaseFullCapabilities() throws Exception { Node testNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Full); nodeManager.syncNodes(testNode, null); List<RendererNode> result = rendererNodesReader(); assertNotNull(result); assertTrue(result.size() == 1); } @Test public void testRegisterNewNode_unableToConnectCase() throws Exception { Node testNode = createNode(UnableToConnect, IPv4_ADDRESS, NODE_NAME, Capabilities.Full); nodeManager.syncNodes(testNode, null); List<RendererNode> result = rendererNodesReader(); assertTrue(result.isEmpty()); } @Test public void testUpdateNode_fromConnectingToConnected() throws Exception { Node oldNode = createNode(Connecting, IPv4_ADDRESS, NODE_NAME, Capabilities.Full); Node newNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Full); nodeManager.syncNodes(oldNode, null); List<RendererNode> result = rendererNodesReader(); assertTrue(result.isEmpty()); nodeManager.syncNodes(newNode, oldNode); result = rendererNodesReader(); assertNotNull(result); assertTrue(result.size() == 1); } // Update Cases @Test public void testUpdateNode_fromConnectingToUnableToConnect() throws Exception { Node oldNode = createNode(Connecting, IPv4_ADDRESS, NODE_NAME, Capabilities.Full); Node newNode = createNode(UnableToConnect, IPv4_ADDRESS, NODE_NAME, Capabilities.Full); nodeManager.syncNodes(oldNode, null); List<RendererNode> result = rendererNodesReader(); assertTrue(result.isEmpty()); nodeManager.syncNodes(newNode, oldNode); result = rendererNodesReader(); assertTrue(result.isEmpty()); } @Test public void testUpdateNode_fromConnectedToConnecting() throws Exception { Node oldNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Full); Node newNode = createNode(Connecting, IPv4_ADDRESS, NODE_NAME, Capabilities.Full); nodeManager.syncNodes(oldNode, null); List<RendererNode> result = rendererNodesReader(); assertNotNull(result); assertTrue(result.size() == 1); nodeManager.syncNodes(newNode, oldNode); result = rendererNodesReader(); assertTrue(result.isEmpty()); } @Test public void testUpdateNode_fromConnectedToUnableToConnect() throws Exception { Node oldNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Full); Node newNode = createNode(UnableToConnect, IPv4_ADDRESS, NODE_NAME, Capabilities.Full); nodeManager.syncNodes(oldNode, null); List<RendererNode> result = rendererNodesReader(); assertNotNull(result); assertTrue(result.size() == 1); nodeManager.syncNodes(newNode, oldNode); result = rendererNodesReader(); assertTrue(result.isEmpty()); } @Test public void testUpdateNode_fromUnableToConnectToConnecting() throws Exception { Node oldNode = createNode(UnableToConnect, IPv4_ADDRESS, NODE_NAME, Capabilities.Full); Node newNode = createNode(Connecting, IPv4_ADDRESS, NODE_NAME, Capabilities.Full); nodeManager.syncNodes(oldNode, null); List<RendererNode> result = rendererNodesReader(); assertTrue(result.isEmpty()); nodeManager.syncNodes(newNode, oldNode); result = rendererNodesReader(); assertTrue(result.isEmpty()); } @Test public void testUpdateNode_fromUnableToConnectToConnected() throws Exception { Node oldNode = createNode(UnableToConnect, IPv4_ADDRESS, NODE_NAME, Capabilities.Full); Node newNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Full); nodeManager.syncNodes(oldNode, null); List<RendererNode> result = rendererNodesReader(); assertTrue(result.isEmpty()); nodeManager.syncNodes(newNode, oldNode); result = rendererNodesReader(); assertNotNull(result); assertTrue(result.size() == 1); } @Test public void testUpdateNode_advancedCase() throws Exception { Node oldNode = createNode(Connecting, IPv4_ADDRESS, NODE_NAME, Capabilities.Partial); nodeManager.syncNodes(oldNode, null); List<RendererNode> result = rendererNodesReader(); // One node is connecting, partial capabilities = empty list assertTrue(result.isEmpty()); Node newNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Partial); nodeManager.syncNodes(newNode, oldNode); result = rendererNodesReader(); // Update 1.: node is connected, still partial capabilities = empty list assertTrue(result.isEmpty()); oldNode = newNode; newNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Full); nodeManager.syncNodes(newNode, oldNode); result = rendererNodesReader(); // Update 2.: node is connected, full capabilities = 1 entry in list assertNotNull(result); assertTrue(result.size() == 1); oldNode = newNode; newNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.None); nodeManager.syncNodes(newNode, oldNode); result = rendererNodesReader(); // Update 3.: node remains connected, but without capabilities = empty list assertTrue(result.isEmpty()); } // Advanced update Case @Test public void testRemoveNode() throws Exception { Node testNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Full); nodeManager.syncNodes(testNode, null); List<RendererNode> result = rendererNodesReader(); assertNotNull(result); assertTrue(result.size() == 1); nodeManager.syncNodes(null, testNode); result = rendererNodesReader(); assertTrue(result.isEmpty()); } // Remove Case @Test public void getNodeManagementIpByMountPointIid_absentNode() { NodeId testNodeId = new NodeId(NODE_NAME); InstanceIdentifier mountpointIid = InstanceIdentifier.builder(NetworkTopology.class) .child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_ID))) .child(Node.class, new NodeKey(testNodeId)).build(); java.util.Optional<String> optionalIpAddress = nodeManager.getNodeManagementIpByMountPointIid(mountpointIid); assertFalse(optionalIpAddress.isPresent()); } @Test public void getNodeManagementIpByMountPointIid_ipV4Case() throws Exception { // Put node Node testNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Full); InstanceIdentifier<Node> testNodeIid = InstanceIdentifier.builder(NetworkTopology.class) .child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_ID))) .child(Node.class, new NodeKey(testNode.getNodeId())).build(); WriteTransaction wTx = dataBroker.newWriteOnlyTransaction(); wTx.put(LogicalDatastoreType.CONFIGURATION, testNodeIid, testNode, true); wTx.submit().checkedGet(); java.util.Optional<String> optionalResult = nodeManager.getNodeManagementIpByMountPointIid(testNodeIid); assertTrue(optionalResult.isPresent()); assertEquals(IPv4_ADDRESS.getValue(), optionalResult.get()); } private Node createNode(final NetconfNodeConnectionStatus.ConnectionStatus connectionStatus, final Ipv4Address ipAddress, final NodeId nodeName, final Capabilities choice) { AvailableCapabilities capabilities = null; switch (choice) { case None: { capabilities = emptyCapabilities(); break; } case Partial: { capabilities = partialCapabilities(); break; } case Full: { capabilities = fullCapabilities(); } } // Netconf node NetconfNodeBuilder netconfNodeBuilder = new NetconfNodeBuilder(); netconfNodeBuilder.setConnectionStatus(connectionStatus) .setAvailableCapabilities(capabilities) .setHost(new Host(new IpAddress(ipAddress))); // Node NodeBuilder nodeBuilder = new NodeBuilder(); nodeBuilder.setNodeId(new NodeId(nodeName)) .setKey(new NodeKey(new NodeId(nodeName))) .addAugmentation(NetconfNode.class, netconfNodeBuilder.build()); return nodeBuilder.build(); } // Utility methods private List<RendererNode> rendererNodesReader() throws Exception { InstanceIdentifier<Renderers> renderersIid = InstanceIdentifier.builder(Renderers.class).build(); ReadWriteTransaction rwt = dataBroker.newReadWriteTransaction(); CheckedFuture<Optional<Renderers>, ReadFailedException> submitFuture = rwt.read(LogicalDatastoreType.OPERATIONAL, renderersIid); Optional<Renderers> optionalRenderers = submitFuture.checkedGet(); if (optionalRenderers.isPresent()) { Renderers renderers = optionalRenderers.get(); if (renderers != null && renderers.getRenderer() != null && !renderers.getRenderer().isEmpty()) { RendererNodes writtenNodes = renderers.getRenderer().get(0).getRendererNodes(); if (writtenNodes != null) { return writtenNodes.getRendererNode(); } } } return Collections.emptyList(); } private AvailableCapabilities emptyCapabilities() { AvailableCapabilitiesBuilder availableCapabilitiesBuilder = new AvailableCapabilitiesBuilder(); return availableCapabilitiesBuilder.build(); } private AvailableCapabilities partialCapabilities() { final AvailableCapability c1 = new AvailableCapabilityBuilder() .setCapability("(urn:ios?revision=2016-03-08)ned") .build(); final AvailableCapability c2 = new AvailableCapabilityBuilder() .setCapability("(http://tail-f.com/yang/common?revision=2015-05-22)tailf-common") .build(); final AvailableCapability c3 = new AvailableCapabilityBuilder() .setCapability("(http://tail-f.com/yang/common?revision=2015-03-19)tailf-cli-extensions") .build(); AvailableCapability[] capabilityList = {c1, c2, c3}; AvailableCapabilitiesBuilder availableCapabilitiesBuilder = new AvailableCapabilitiesBuilder(); availableCapabilitiesBuilder.setAvailableCapability(Arrays.asList(capabilityList)); return availableCapabilitiesBuilder.build(); } private AvailableCapabilities fullCapabilities() { final AvailableCapability c1 = new AvailableCapabilityBuilder() .setCapability("(urn:ios?revision=2016-03-08)ned") .build(); final AvailableCapability c2 = new AvailableCapabilityBuilder() .setCapability("(http://tail-f.com/yang/common?revision=2015-05-22)tailf-common") .build(); final AvailableCapability c3 = new AvailableCapabilityBuilder() .setCapability("(http://tail-f.com/yang/common?revision=2015-03-19)tailf-cli-extensions") .build(); final AvailableCapability c4 = new AvailableCapabilityBuilder() .setCapability("(http://tail-f.com/yang/common?revision=2013-11-07)tailf-meta-extensions") .build(); final AvailableCapability c5 = new AvailableCapabilityBuilder() .setCapability("(urn:ietf:params:xml:ns:yang:ietf-yang-types?revision=2013-07-15)ietf-yang-types") .build(); final AvailableCapability c6 = new AvailableCapabilityBuilder() .setCapability("(urn:ietf:params:xml:ns:yang:ietf-inet-types?revision=2013-07-15)ietf-inet-types") .build(); AvailableCapability[] capabilityList = {c1, c2, c3, c4, c5, c6}; AvailableCapabilitiesBuilder availableCapabilitiesBuilder = new AvailableCapabilitiesBuilder(); availableCapabilitiesBuilder.setAvailableCapability(Arrays.asList(capabilityList)); return availableCapabilitiesBuilder.build(); } private enum Capabilities {None, Partial, Full} }