From 22cd11dc2d6790b97f1e0993a964dadce4a9dee3 Mon Sep 17 00:00:00 2001 From: Riyazahmed Date: Mon, 22 Jan 2018 17:41:31 +0530 Subject: [PATCH] Scale-In Scale-Out RPC call to get DPN info Below changes exposes RPC call to get DPN details (DPN ID and Tep Ip of the DPN) by passing the compute node. Change-Id: I3d80e2d582e049e35bbd21d6f499e1e74c2c3b99 Signed-off-by: Riyazahmed --- .../genius/testutils/itm/ItmRpcTestImpl.java | 8 ++ itm/itm-api/src/main/yang/itm-rpc.yang | 34 +++++ .../genius/itm/rpc/ItmManagerRpcService.java | 119 ++++++++++++++++++ 3 files changed, 161 insertions(+) diff --git a/commons/testutils/src/main/java/org/opendaylight/genius/testutils/itm/ItmRpcTestImpl.java b/commons/testutils/src/main/java/org/opendaylight/genius/testutils/itm/ItmRpcTestImpl.java index dbf3e1e83..befa49297 100644 --- a/commons/testutils/src/main/java/org/opendaylight/genius/testutils/itm/ItmRpcTestImpl.java +++ b/commons/testutils/src/main/java/org/opendaylight/genius/testutils/itm/ItmRpcTestImpl.java @@ -24,6 +24,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.D import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsOutputBuilder; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnInfoInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnInfoOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameInput; @@ -85,6 +88,11 @@ public final class ItmRpcTestImpl implements ItmRpcService { return RpcResultBuilder.success().buildFuture(); } + @Override + public Future> getDpnInfo(GetDpnInfoInput input) { + throw new UnsupportedOperationException("getDpnInfo"); + } + @Override public synchronized Future> addL2GwMlagDevice(AddL2GwMlagDeviceInput input) { return RpcResultBuilder.success().buildFuture(); diff --git a/itm/itm-api/src/main/yang/itm-rpc.yang b/itm/itm-api/src/main/yang/itm-rpc.yang index efaa1280a..0880c5d8f 100644 --- a/itm/itm-api/src/main/yang/itm-rpc.yang +++ b/itm/itm-api/src/main/yang/itm-rpc.yang @@ -349,7 +349,41 @@ module itm-rpc { range "1000..30000"; } } + } + } + rpc get-dpn-info { + description "Gets the dpn id and tep ip information of compute nodes"; + input { + leaf-list compute-names { + type string; + } + } + output { + list computes { + key "compute-name"; + leaf compute-name { + type string; + } + leaf zone-name { + type string; + } + leaf prefix { + type inet:ip-prefix; + } + leaf dpn-id { + type uint64; + } + leaf-list tep-ip { + type inet:ip-address; + } + leaf port-name { + type string; + } + leaf node-id { + type string; + } + } } } } diff --git a/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/rpc/ItmManagerRpcService.java b/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/rpc/ItmManagerRpcService.java index 8ea83ab31..a08e386eb 100644 --- a/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/rpc/ItmManagerRpcService.java +++ b/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/rpc/ItmManagerRpcService.java @@ -12,18 +12,27 @@ import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.SettableFuture; + import java.math.BigInteger; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.Future; +import java.util.stream.Collectors; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.inject.Inject; import javax.inject.Singleton; + import org.opendaylight.controller.md.sal.binding.api.DataBroker; 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.genius.datastoreutils.SingleTransactionDataBroker; +import org.opendaylight.genius.infra.FutureRpcResults; import org.opendaylight.genius.itm.cache.DPNTEPsInfoCache; import org.opendaylight.genius.itm.confighelpers.ItmExternalTunnelAddWorker; import org.opendaylight.genius.itm.confighelpers.ItmExternalTunnelDeleteWorker; @@ -35,7 +44,11 @@ import org.opendaylight.genius.mdsalutil.NwConstants; import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager; import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.BridgeRefInfo; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntry; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntryKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeLogicalGroup; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig; @@ -59,6 +72,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transp import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.DeviceVteps; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.DeviceVtepsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.DeviceVtepsKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.Vteps; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddExternalTunnelEndpointInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwDeviceInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwMlagDeviceInput; @@ -69,6 +83,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.D import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnInfoInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnInfoOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnInfoOutputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameInput; @@ -93,6 +110,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.R import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelFromDpnsInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveTerminatingServiceActionsInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.SetBfdEnableOnTunnelInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.get.dpn.info.output.Computes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.get.dpn.info.output.ComputesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.RpcError; import org.opendaylight.yangtools.yang.common.RpcResult; @@ -108,6 +129,8 @@ public class ItmManagerRpcService implements ItmRpcService { private final IMdsalApiManager mdsalManager; private final DPNTEPsInfoCache dpnTEPsInfoCache; private final ItmExternalTunnelAddWorker externalTunnelAddWorker; + private final ItmConfig itmConfig; + private final SingleTransactionDataBroker singleTransactionDataBroker; @Inject public ItmManagerRpcService(final DataBroker dataBroker, final IMdsalApiManager mdsalManager, @@ -116,6 +139,8 @@ public class ItmManagerRpcService implements ItmRpcService { this.mdsalManager = mdsalManager; this.dpnTEPsInfoCache = dpnTEPsInfoCache; this.externalTunnelAddWorker = new ItmExternalTunnelAddWorker(dataBroker, itmConfig, dpnTEPsInfoCache); + this.itmConfig = itmConfig; + this.singleTransactionDataBroker = new SingleTransactionDataBroker(dataBroker); } @PostConstruct @@ -857,4 +882,98 @@ public class ItmManagerRpcService implements ItmRpcService { return Futures.immediateFuture(resultBld.build()); } + @Override + public Future> getDpnInfo(GetDpnInfoInput input) { + return FutureRpcResults.fromListenableFuture(LOG, "getDpnInfo", input, () -> { + return Futures.immediateFuture(getDpnInfoInternal(input)); + }).build(); + } + + private GetDpnInfoOutput getDpnInfoInternal(GetDpnInfoInput input) throws ReadFailedException { + Map computeNamesVsDpnIds + = getDpnIdByComputeNodeNameFromOpInventoryNodes(input.getComputeNames()); + Map dpnIdVsVtepsComputes + = getTunnelEndPointByDpnIdFromTranPortZone(computeNamesVsDpnIds.values()); + List computes = computeNamesVsDpnIds.entrySet().stream() + .map(entry -> dpnIdVsVtepsComputes.get(entry.getValue()).setComputeName(entry.getKey()).build()) + .collect(Collectors.toList()); + return new GetDpnInfoOutputBuilder().setComputes(computes).build(); + } + + private Map getTunnelEndPointByDpnIdFromTranPortZone(Collection dpnIds) + throws ReadFailedException { + TransportZones transportZones = singleTransactionDataBroker.syncRead( + LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.builder(TransportZones.class).build()); + if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) { + throw new IllegalStateException("Failed to find transport zones in config datastore"); + } + Map result = new HashMap<>(); + for (TransportZone transportZone : transportZones.getTransportZone()) { + if (transportZone.getSubnets() == null || transportZone.getSubnets().isEmpty()) { + LOG.debug("Transport Zone {} has no subnets", transportZone.getZoneName()); + continue; + } + for (Subnets sub : transportZone.getSubnets()) { + if (sub.getVteps() == null || sub.getVteps().isEmpty()) { + LOG.debug("Transport Zone {} subnet {} has no vteps configured", + transportZone.getZoneName(), sub.getPrefix()); + continue; + } + for (Vteps vtep : sub.getVteps()) { + if (dpnIds.contains(vtep.getDpnId())) { + result.putIfAbsent(vtep.getDpnId(), + new ComputesBuilder() + .setZoneName(transportZone.getZoneName()) + .setPrefix(sub.getPrefix()) + .setDpnId(vtep.getDpnId()) + .setPortName(vtep.getPortname()) + .setNodeId(getNodeId(vtep.getDpnId())) + .setTepIp(Collections.singletonList(vtep.getIpAddress()))); + } + } + } + } + for (BigInteger dpnId : dpnIds) { + if (!result.containsKey(dpnId)) { + throw new IllegalStateException("Failed to find dpn id " + dpnId + " in transport zone"); + } + } + return result; + } + + private Map getDpnIdByComputeNodeNameFromOpInventoryNodes(List nodeNames) + throws ReadFailedException { + Nodes operInventoryNodes = singleTransactionDataBroker.syncRead( + LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(Nodes.class).build()); + if (operInventoryNodes.getNode() == null || operInventoryNodes.getNode().isEmpty()) { + throw new IllegalStateException("Failed to find operational inventory nodes datastore"); + } + Map result = new HashMap<>(); + for (Node node : operInventoryNodes.getNode()) { + String name = node.getAugmentation(FlowCapableNode.class).getDescription(); + if (nodeNames.contains(name)) { + String[] nodeId = node.getId().getValue().split(":"); + result.put(name, new BigInteger(nodeId[1])); + } + } + for (String nodeName : nodeNames) { + if (!result.containsKey(nodeName)) { + throw new IllegalStateException("Failed to find dpn id of compute node name from oper inventory " + + nodeName); + } + } + return result; + } + + private String getNodeId(BigInteger dpnId) throws ReadFailedException { + InstanceIdentifier path = InstanceIdentifier + .builder(BridgeRefInfo.class) + .child(BridgeRefEntry.class, new BridgeRefEntryKey(dpnId)).build(); + BridgeRefEntry bridgeRefEntry = + singleTransactionDataBroker.syncRead(LogicalDatastoreType.OPERATIONAL, path); + return ((InstanceIdentifier)bridgeRefEntry.getBridgeReference().getValue()) + .firstKeyOf(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021 + .network.topology.topology.Node.class).getNodeId().getValue(); + } } -- 2.36.6