2 * Copyright (c) 2019 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.genius.cloudscaler.tests;
10 import static org.junit.Assert.assertTrue;
11 import static org.opendaylight.mdsal.common.api.LogicalDatastoreType.CONFIGURATION;
12 import static org.opendaylight.mdsal.common.api.LogicalDatastoreType.OPERATIONAL;
14 import com.google.common.collect.Lists;
15 import com.google.common.collect.Sets;
16 import com.google.common.util.concurrent.ListenableFuture;
17 import java.math.BigInteger;
18 import java.util.HashSet;
19 import java.util.List;
21 import java.util.concurrent.ExecutionException;
22 import java.util.concurrent.TimeUnit;
23 import javax.inject.Inject;
24 import org.awaitility.Awaitility;
25 import org.awaitility.core.ConditionFactory;
26 import org.junit.Before;
27 import org.junit.Rule;
28 import org.junit.Test;
29 import org.junit.rules.MethodRule;
30 import org.opendaylight.genius.cloudscaler.api.ScaleInConstants;
31 import org.opendaylight.genius.cloudscaler.rpcservice.CloudscalerRpcServiceImpl;
32 import org.opendaylight.genius.cloudscaler.rpcservice.ComputeNodeManager;
33 import org.opendaylight.genius.cloudscaler.rpcservice.TombstonedNodeManagerImpl;
34 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
35 import org.opendaylight.genius.datastoreutils.testutils.JobCoordinatorTestModule;
36 import org.opendaylight.infrautils.inject.guice.testutils.GuiceRule;
37 import org.opendaylight.infrautils.testutils.LogRule;
38 import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.cloudscaler.rpcs.rev171220.ComputeNodes;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.cloudscaler.rpcs.rev171220.ScaleinComputesRecoverInputBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.cloudscaler.rpcs.rev171220.ScaleinComputesRecoverOutput;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.cloudscaler.rpcs.rev171220.ScaleinComputesStartInputBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.cloudscaler.rpcs.rev171220.ScaleinComputesStartOutput;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.cloudscaler.rpcs.rev171220.compute.nodes.ComputeNode;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.cloudscaler.rpcs.rev171220.compute.nodes.ComputeNodeBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.cloudscaler.rpcs.rev171220.compute.nodes.ComputeNodeKey;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.BridgeRefInfo;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntry;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntryBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntryKey;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathId;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentationBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigsBuilder;
56 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
57 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
58 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
59 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
60 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
61 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
62 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
63 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
64 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
65 import org.opendaylight.yangtools.yang.common.RpcResult;
66 import org.opendaylight.yangtools.yang.common.Uint64;
67 import org.slf4j.Logger;
68 import org.slf4j.LoggerFactory;
70 public class CloudScalerServiceTest {
72 private static final Logger LOG = LoggerFactory.getLogger(CloudScalerServiceTest.class);
74 private static final String NODEID1 = "ovsdb://uuid/2de70a99-29a5-4f2a-b87e-96d6ed57e411/bridge/br-int";
75 private static final String NODEID2 = "ovsdb://uuid/2de70a99-29a5-4f2a-b87e-96d6ed57e412/bridge/br-int";
76 private static final String NODEID3 = "ovsdb://uuid/2de70a99-29a5-4f2a-b87e-96d6ed57e413/bridge/br-int";
78 private static final Uint64 DPN1 = Uint64.ONE;
79 private static final Uint64 DPN2 = Uint64.valueOf(2);
80 private static final Uint64 DPN3 = Uint64.valueOf(3);
81 private static final Uint64 DPN4 = Uint64.valueOf(4);
83 private static final String DPN1_DATAPATHID = new String("00:00:00:00:00:00:00:01");
84 private static final String DPN2_DATAPATHID = new String("00:00:00:00:00:00:00:02");
85 private static final String DPN3_DATAPATHID = new String("00:00:00:00:00:00:00:03");
86 private static final String DPN4_DATAPATHID = new String("00:00:00:00:00:00:00:04");
88 private static final String COMPUTE1 = new String("COMPUTE1");
89 private static final String COMPUTE2 = new String("COMPUTE2");
90 private static final String COMPUTE3 = new String("COMPUTE3");
92 private static final InstanceIdentifier<BridgeRefEntry> DPN1_BRIDGE_REF
93 = InstanceIdentifier.builder(BridgeRefInfo.class)
94 .child(BridgeRefEntry.class, new BridgeRefEntryKey(DPN1)).build();
96 private static final InstanceIdentifier<BridgeRefEntry> DPN2_BRIDGE_REF
97 = InstanceIdentifier.builder(BridgeRefInfo.class)
98 .child(BridgeRefEntry.class, new BridgeRefEntryKey(DPN2)).build();
100 private static final InstanceIdentifier<BridgeRefEntry> DPN3_BRIDGE_REF
101 = InstanceIdentifier.builder(BridgeRefInfo.class)
102 .child(BridgeRefEntry.class, new BridgeRefEntryKey(DPN3)).build();
104 private static ConditionFactory AWAITER = Awaitility.await("TestableListener")
105 .atMost(30, TimeUnit.SECONDS)
106 .pollInterval(100, TimeUnit.MILLISECONDS);
108 public @Rule LogRule logRule = new LogRule();
109 public @Rule MethodRule guice = new GuiceRule(CloudScalerServiceTestModule.class, JobCoordinatorTestModule.class);
111 private @Inject CloudscalerRpcServiceImpl scaleInRpcManager;
112 private @Inject TombstonedNodeManagerImpl tombstonedNodeManager;
113 private @Inject SingleTransactionDataBroker dataBroker;
114 private @Inject ComputeNodeManager computeNodeManager;
116 public CloudScalerServiceTest() {
119 private static InstanceIdentifier<ComputeNode> buildComputeNodeIid(String computeName) {
120 return InstanceIdentifier.builder(ComputeNodes.class)
121 .child(ComputeNode.class, new ComputeNodeKey(computeName))
125 private static InstanceIdentifier<Node> buildNodeId(String nodeId) {
126 return InstanceIdentifier
127 .create(NetworkTopology.class)
128 .child(Topology.class, new TopologyKey(new TopologyId("ovsdb:1")))
129 .child(Node.class, new NodeKey(new NodeId(nodeId)));
132 private static Node buildNode(String nodeId, String computeName, String datapathid) {
133 NodeBuilder nodeBuilder = new NodeBuilder();
134 nodeBuilder.setNodeId(new NodeId(nodeId));
135 OvsdbBridgeAugmentationBuilder bridge = new OvsdbBridgeAugmentationBuilder();
136 BridgeOtherConfigsBuilder otherConfigsBuilder = new BridgeOtherConfigsBuilder();
137 otherConfigsBuilder.setBridgeOtherConfigKey("dp-desc");
138 otherConfigsBuilder.setBridgeOtherConfigValue(computeName);
139 bridge.setDatapathId(new DatapathId(datapathid));
140 bridge.setBridgeOtherConfigs(Lists.newArrayList(otherConfigsBuilder.build()));
141 nodeBuilder.addAugmentation(bridge.build());
142 return nodeBuilder.build();
145 private static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node>
146 buildOpenflowNodeIid(Uint64 dpnid) {
147 return InstanceIdentifier.builder(Nodes.class)
148 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
149 new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey(
150 new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId(
151 "openflow:" + dpnid.toString()))).build();
154 private static org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node buildOpenflowNode(
156 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder nodeBuilder
157 = new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder();
158 nodeBuilder.setId(new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId(
159 "openflow:" + dpnId.toString()));
160 return nodeBuilder.build();
163 @Before public void before() throws TransactionCommitFailedException {
164 dataBroker.syncWrite(OPERATIONAL, DPN1_BRIDGE_REF, buildBridgeRefEntry(DPN1, NODEID1));
165 dataBroker.syncWrite(OPERATIONAL, DPN2_BRIDGE_REF, buildBridgeRefEntry(DPN2, NODEID2));
166 dataBroker.syncWrite(OPERATIONAL, DPN3_BRIDGE_REF, buildBridgeRefEntry(DPN3, NODEID3));
168 dataBroker.syncWrite(CONFIGURATION, buildNodeId(NODEID1), buildNode(NODEID1, COMPUTE1, DPN1_DATAPATHID));
169 dataBroker.syncWrite(CONFIGURATION, buildNodeId(NODEID2), buildNode(NODEID2, COMPUTE2, DPN2_DATAPATHID));
170 dataBroker.syncWrite(CONFIGURATION, buildNodeId(NODEID3), buildNode(NODEID3, COMPUTE3, DPN3_DATAPATHID));
172 dataBroker.syncWrite(CONFIGURATION, buildOpenflowNodeIid(DPN1), buildOpenflowNode(DPN1));
173 dataBroker.syncWrite(CONFIGURATION, buildOpenflowNodeIid(DPN2), buildOpenflowNode(DPN2));
174 dataBroker.syncWrite(CONFIGURATION, buildOpenflowNodeIid(DPN3), buildOpenflowNode(DPN3));
177 @Test public void testBridgeAdd()
178 throws ExecutionException, InterruptedException, TransactionCommitFailedException {
180 dataBroker.syncWrite(OPERATIONAL, buildNodeId(NODEID1), buildNode(NODEID1, COMPUTE1, DPN1_DATAPATHID));
181 dataBroker.syncWrite(OPERATIONAL, buildNodeId(NODEID2), buildNode(NODEID2, COMPUTE2, DPN2_DATAPATHID));
182 dataBroker.syncWrite(OPERATIONAL, buildNodeId(NODEID3), buildNode(NODEID3, COMPUTE3, DPN3_DATAPATHID));
184 AWAITER.until(() -> dataBroker.syncReadOptional(CONFIGURATION, buildComputeNodeIid(COMPUTE1)).isPresent());
187 @Test public void testScaleinComputesStartRpc()
188 throws ExecutionException, InterruptedException, TransactionCommitFailedException {
190 ListenableFuture<RpcResult<ScaleinComputesStartOutput>> ft = scaleInRpcManager.scaleinComputesStart(
191 new ScaleinComputesStartInputBuilder().setScaleinComputeNames(
192 Lists.newArrayList(COMPUTE1, COMPUTE2)).build());
193 assertTrue("Scalein computes start rpc should return success code ", ft.get().isSuccessful());
195 AWAITER.until(() -> dataBroker.syncReadOptional(
196 CONFIGURATION, buildComputeNodeIid(COMPUTE1)).get().isTombstoned());
197 AWAITER.until(() -> dataBroker.syncReadOptional(
198 CONFIGURATION, buildComputeNodeIid(COMPUTE2)).get().isTombstoned());
201 private static ComputeNode buildComputeNode(String nodeid1, BigInteger dpn1, String compute1) {
202 return new ComputeNodeBuilder()
203 .setComputeName(compute1)
209 @Test public void testScaleinComputesRecoverRpc()
210 throws ExecutionException, InterruptedException, TransactionCommitFailedException {
212 testScaleinComputesStartRpc();
214 ListenableFuture<RpcResult<ScaleinComputesRecoverOutput>> ft = scaleInRpcManager.scaleinComputesRecover(
215 new ScaleinComputesRecoverInputBuilder().setRecoverComputeNames(Lists.newArrayList(COMPUTE1)).build());
216 assertTrue("scalein computes recover rpc should return success code", ft.get().isSuccessful());
218 AWAITER.until(() -> !dataBroker.syncReadOptional(
219 CONFIGURATION, buildComputeNodeIid(COMPUTE1)).get().isTombstoned());
220 AWAITER.until(() -> dataBroker.syncReadOptional(
221 CONFIGURATION, buildComputeNodeIid(COMPUTE2)).get().isTombstoned());
224 @Test public void testIsDpnTombstonedApi()
225 throws ExecutionException, InterruptedException, TransactionCommitFailedException {
227 testScaleinComputesStartRpc();
228 assertTrue("Dpn 1 should be marked as tombstoned", tombstonedNodeManager.isDpnTombstoned(DPN1));
229 assertTrue("Dpn 2 should be marked as tombstoned", tombstonedNodeManager.isDpnTombstoned(DPN2));
232 @Test public void testfilterTombstoned()
233 throws ExecutionException, InterruptedException, TransactionCommitFailedException {
235 testScaleinComputesStartRpc();
236 List<Uint64> filtered = tombstonedNodeManager.filterTombStoned(Lists.newArrayList(DPN1, DPN2, DPN3, DPN4));
237 assertTrue("Dpn 1 and 2 should be filtered ",
238 Sets.difference(Sets.newHashSet(DPN3, DPN4), Sets.newHashSet(filtered)).isEmpty());
241 @Test public void testRecoveryCallback()
242 throws ExecutionException, InterruptedException, TransactionCommitFailedException {
244 Set<Uint64> nodesRecoverd = new HashSet<>();
245 tombstonedNodeManager.addOnRecoveryCallback(dpnId -> {
246 nodesRecoverd.add(dpnId);
249 testScaleinComputesRecoverRpc();
250 AWAITER.until(() -> nodesRecoverd.contains(DPN1));
253 private static BridgeRefEntry buildBridgeRefEntry(Uint64 dpnId, String nodeId) {
254 return new BridgeRefEntryBuilder()
256 .setBridgeReference(new OvsdbBridgeRef(buildNodeIid(nodeId)))
260 public static InstanceIdentifier<Node> buildNodeIid(String nodeId) {
261 return InstanceIdentifier.builder(NetworkTopology.class)
262 .child(Topology.class, new TopologyKey(ScaleInConstants.OVSDB_TOPOLOGY_ID))
263 .child(Node.class, new NodeKey(new NodeId(nodeId))).build();