Migrate to simplified addAugmentation() method
[genius.git] / cloudscaler / impl / src / test / java / org / opendaylight / genius / cloudscaler / tests / CloudScalerServiceTest.java
1 /*
2  * Copyright (c) 2019 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.genius.cloudscaler.tests;
9
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;
13
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;
20 import java.util.Set;
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;
69
70 public class CloudScalerServiceTest {
71
72     private static final Logger LOG = LoggerFactory.getLogger(CloudScalerServiceTest.class);
73
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";
77
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);
82
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");
87
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");
91
92     private static final InstanceIdentifier<BridgeRefEntry> DPN1_BRIDGE_REF
93         = InstanceIdentifier.builder(BridgeRefInfo.class)
94         .child(BridgeRefEntry.class, new BridgeRefEntryKey(DPN1)).build();
95
96     private static final InstanceIdentifier<BridgeRefEntry> DPN2_BRIDGE_REF
97         = InstanceIdentifier.builder(BridgeRefInfo.class)
98         .child(BridgeRefEntry.class, new BridgeRefEntryKey(DPN2)).build();
99
100     private static final InstanceIdentifier<BridgeRefEntry> DPN3_BRIDGE_REF
101         = InstanceIdentifier.builder(BridgeRefInfo.class)
102         .child(BridgeRefEntry.class, new BridgeRefEntryKey(DPN3)).build();
103
104     private static ConditionFactory AWAITER = Awaitility.await("TestableListener")
105         .atMost(30, TimeUnit.SECONDS)
106         .pollInterval(100, TimeUnit.MILLISECONDS);
107
108     public @Rule LogRule logRule = new LogRule();
109     public @Rule MethodRule guice = new GuiceRule(CloudScalerServiceTestModule.class, JobCoordinatorTestModule.class);
110
111     private @Inject CloudscalerRpcServiceImpl scaleInRpcManager;
112     private @Inject TombstonedNodeManagerImpl tombstonedNodeManager;
113     private @Inject SingleTransactionDataBroker dataBroker;
114     private @Inject ComputeNodeManager computeNodeManager;
115
116     public CloudScalerServiceTest() {
117     }
118
119     private static InstanceIdentifier<ComputeNode> buildComputeNodeIid(String computeName) {
120         return InstanceIdentifier.builder(ComputeNodes.class)
121                 .child(ComputeNode.class, new ComputeNodeKey(computeName))
122                 .build();
123     }
124
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)));
130     }
131
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();
143     }
144
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();
152     }
153
154     private static org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node buildOpenflowNode(
155             Uint64 dpnId) {
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();
161     }
162
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));
167
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));
171
172         dataBroker.syncWrite(CONFIGURATION, buildOpenflowNodeIid(DPN1), buildOpenflowNode(DPN1));
173         dataBroker.syncWrite(CONFIGURATION, buildOpenflowNodeIid(DPN2), buildOpenflowNode(DPN2));
174         dataBroker.syncWrite(CONFIGURATION, buildOpenflowNodeIid(DPN3), buildOpenflowNode(DPN3));
175     }
176
177     @Test public void testBridgeAdd()
178             throws ExecutionException, InterruptedException, TransactionCommitFailedException {
179
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));
183
184         AWAITER.until(() -> dataBroker.syncReadOptional(CONFIGURATION, buildComputeNodeIid(COMPUTE1)).isPresent());
185     }
186
187     @Test public void testScaleinComputesStartRpc()
188             throws ExecutionException, InterruptedException, TransactionCommitFailedException {
189         testBridgeAdd();
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());
194
195         AWAITER.until(() -> dataBroker.syncReadOptional(
196                 CONFIGURATION, buildComputeNodeIid(COMPUTE1)).get().isTombstoned());
197         AWAITER.until(() -> dataBroker.syncReadOptional(
198                 CONFIGURATION, buildComputeNodeIid(COMPUTE2)).get().isTombstoned());
199     }
200
201     private static ComputeNode buildComputeNode(String nodeid1, BigInteger dpn1, String compute1) {
202         return new ComputeNodeBuilder()
203                 .setComputeName(compute1)
204                 .setDpnid(dpn1)
205                 .setNodeid(nodeid1)
206                 .build();
207     }
208
209     @Test public void testScaleinComputesRecoverRpc()
210             throws ExecutionException, InterruptedException, TransactionCommitFailedException {
211
212         testScaleinComputesStartRpc();
213
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());
217
218         AWAITER.until(() -> !dataBroker.syncReadOptional(
219                 CONFIGURATION, buildComputeNodeIid(COMPUTE1)).get().isTombstoned());
220         AWAITER.until(() -> dataBroker.syncReadOptional(
221                 CONFIGURATION, buildComputeNodeIid(COMPUTE2)).get().isTombstoned());
222     }
223
224     @Test public void testIsDpnTombstonedApi()
225             throws ExecutionException, InterruptedException, TransactionCommitFailedException {
226
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));
230     }
231
232     @Test public void testfilterTombstoned()
233             throws ExecutionException, InterruptedException, TransactionCommitFailedException {
234
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());
239     }
240
241     @Test public void testRecoveryCallback()
242             throws ExecutionException, InterruptedException, TransactionCommitFailedException {
243
244         Set<Uint64> nodesRecoverd = new HashSet<>();
245         tombstonedNodeManager.addOnRecoveryCallback(dpnId -> {
246             nodesRecoverd.add(dpnId);
247             return null;
248         });
249         testScaleinComputesRecoverRpc();
250         AWAITER.until(() -> nodesRecoverd.contains(DPN1));
251     }
252
253     private static BridgeRefEntry buildBridgeRefEntry(Uint64 dpnId, String nodeId) {
254         return new BridgeRefEntryBuilder()
255             .setDpid(dpnId)
256             .setBridgeReference(new OvsdbBridgeRef(buildNodeIid(nodeId)))
257             .build();
258     }
259
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();
264     }
265 }