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.rpcservice;
10 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
12 import java.util.Objects;
13 import java.util.Optional;
14 import java.util.concurrent.ConcurrentHashMap;
15 import java.util.concurrent.ExecutionException;
16 import java.util.concurrent.ExecutorService;
17 import javax.inject.Inject;
18 import javax.inject.Singleton;
19 import org.eclipse.jdt.annotation.NonNull;
20 import org.opendaylight.genius.mdsalutil.cache.InstanceIdDataObjectCache;
21 import org.opendaylight.infrautils.caches.CacheProvider;
22 import org.opendaylight.infrautils.utils.concurrent.Executors;
23 import org.opendaylight.mdsal.binding.api.DataBroker;
24 import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
25 import org.opendaylight.mdsal.binding.util.Datastore.Configuration;
26 import org.opendaylight.mdsal.binding.util.TypedReadWriteTransaction;
27 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
28 import org.opendaylight.mdsal.common.api.ReadFailedException;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.cloudscaler.rpcs.rev171220.ComputeNodes;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.cloudscaler.rpcs.rev171220.compute.nodes.ComputeNode;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.cloudscaler.rpcs.rev171220.compute.nodes.ComputeNodeBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.cloudscaler.rpcs.rev171220.compute.nodes.ComputeNodeKey;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigs;
35 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
36 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
37 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
38 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
39 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
40 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
41 import org.opendaylight.yangtools.yang.common.Uint64;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
46 public class ComputeNodeManager {
48 private static final Logger LOG = LoggerFactory.getLogger("GeniusEventLogger");
50 private final DataBroker dataBroker;
52 private final InstanceIdDataObjectCache<ComputeNode> computeNodeCache;
53 private final InstanceIdDataObjectCache<Node> ovsdbTopologyNodeCache;
54 private final Map<Uint64, ComputeNode> dpnIdVsComputeNode;
55 // FIXME: this service is never shut down
56 private final ExecutorService executorService = Executors.newSingleThreadExecutor("compute-node-manager", LOG);
59 @SuppressFBWarnings({"URF_UNREAD_FIELD", "NP_LOAD_OF_KNOWN_NULL_VALUE"})
60 public ComputeNodeManager(DataBroker dataBroker,
61 CacheProvider cacheProvider) {
62 this.dataBroker = dataBroker;
63 this.dpnIdVsComputeNode = new ConcurrentHashMap<>();
64 this.computeNodeCache = new InstanceIdDataObjectCache<>(ComputeNode.class, dataBroker,
65 LogicalDatastoreType.CONFIGURATION,
66 InstanceIdentifier.builder(ComputeNodes.class).child(ComputeNode.class).build(),
69 protected void added(InstanceIdentifier<ComputeNode> path, ComputeNode computeNode) {
70 LOG.info("ComputeNodeManager add compute {}", computeNode);
71 dpnIdVsComputeNode.put(computeNode.getDpnid(), computeNode);
75 protected void removed(InstanceIdentifier<ComputeNode> path, ComputeNode computeNode) {
76 LOG.info("ComputeNodeManager remove compute {}", computeNode);
77 dpnIdVsComputeNode.remove(computeNode.getDpnid());
80 this.ovsdbTopologyNodeCache = new InstanceIdDataObjectCache<>(Node.class, dataBroker,
81 LogicalDatastoreType.OPERATIONAL,
85 @SuppressWarnings("checkstyle:IllegalCatch")
86 protected void added(InstanceIdentifier<Node> path, Node dataObject) {
87 executorService.execute(() -> {
90 } catch (Exception e) {
91 LOG.error("ComputeNodeManager Failed to handle ovsdb node add", e);
96 //LOG.info("Compute node manager is initialized ");
99 public ComputeNode getComputeNodeFromName(String computeName) throws ReadFailedException {
100 InstanceIdentifier<ComputeNode> computeIid = buildComputeNodeIid(computeName);
101 return computeNodeCache.get(computeIid).orElse(null);
104 public void deleteComputeNode(TypedReadWriteTransaction<@NonNull Configuration> tx, ComputeNode computeNode) {
105 tx.delete(buildComputeNodeIid(computeNode.getComputeName()));
108 public void add(@NonNull Node node) throws ExecutionException, InterruptedException {
109 OvsdbBridgeAugmentation bridgeAugmentation = node.augmentation(OvsdbBridgeAugmentation.class);
110 if (bridgeAugmentation != null && bridgeAugmentation.getBridgeOtherConfigs() != null) {
111 Uint64 datapathid = getDpnIdFromBridge(bridgeAugmentation);
112 Optional<BridgeOtherConfigs> otherConfigOptional = bridgeAugmentation.getBridgeOtherConfigs().values()
114 .filter(otherConfig -> otherConfig.getBridgeOtherConfigKey().equals("dp-desc"))
116 if (!otherConfigOptional.isPresent()) {
117 LOG.debug("ComputeNodeManager Compute node name is not present in bridge {}", node.getNodeId());
120 String computeName = otherConfigOptional.get().getBridgeOtherConfigValue();
121 String nodeId = node.getNodeId().getValue();
122 InstanceIdentifier<ComputeNode> computeIid = buildComputeNodeIid(computeName);
123 ComputeNode computeNode = new ComputeNodeBuilder()
124 .setComputeName(computeName)
125 .setDpnid(datapathid)
128 Optional<ComputeNode> computeNodeOptional = Optional.empty();
130 computeNodeOptional = computeNodeCache.get(computeIid);
131 } catch (ReadFailedException e) {
132 LOG.error("ComputeNodeManager Failed to read {}", computeIid);
134 if (computeNodeOptional.isPresent()) {
135 logErrorIfComputeNodeIsAlreadyTaken(datapathid, nodeId, computeNodeOptional);
137 LOG.info("ComputeNodeManager add ovsdb node {}", node.getNodeId());
138 putComputeDetailsInConfigDatastore(computeIid, computeNode);
143 public InstanceIdentifier<ComputeNode> buildComputeNodeIid(String computeName) {
144 return InstanceIdentifier.builder(ComputeNodes.class)
145 .child(ComputeNode.class, new ComputeNodeKey(computeName))
149 private Uint64 getDpnIdFromBridge(OvsdbBridgeAugmentation bridgeAugmentation) {
150 if (bridgeAugmentation.getDatapathId() == null) {
153 String datapathIdStr = bridgeAugmentation.getDatapathId().getValue() != null
154 ? bridgeAugmentation.getDatapathId().getValue().replace(":", "") : null;
155 return datapathIdStr != null ? Uint64.valueOf(datapathIdStr, 16) : Uint64.ZERO;
158 public void putComputeDetailsInConfigDatastore(InstanceIdentifier<ComputeNode> computeIid,
159 ComputeNode computeNode)
160 throws ExecutionException, InterruptedException {
161 ReadWriteTransaction tx = dataBroker.newReadWriteTransaction();
162 tx.put(LogicalDatastoreType.CONFIGURATION, computeIid, computeNode);
164 dpnIdVsComputeNode.put(computeNode.getDpnid(), computeNode);
165 //LOG.info("Write comute node details {}", computeNode);
169 private void logErrorIfComputeNodeIsAlreadyTaken(Uint64 datapathid, String nodeId, Optional<ComputeNode> optional) {
170 ComputeNode existingNode = optional.get();
171 if (!Objects.equals(existingNode.getNodeid(), nodeId)) {
172 LOG.error("ComputeNodeManager Compute is already connected by compute {}", existingNode);
175 if (!Objects.equals(existingNode.getDpnid(), datapathid)) {
176 LOG.error("ComputeNodeManager Compute is already connected by compute {}", existingNode);
180 private InstanceIdentifier<Node> getWildcardPath() {
181 return InstanceIdentifier
182 .create(NetworkTopology.class)
183 .child(Topology.class, new TopologyKey(new TopologyId("ovsdb:1")))
187 public ComputeNode getComputeNode(Uint64 dpnId) {
188 return dpnIdVsComputeNode.get(dpnId);