monitoring/nebulous/ems-core/baguette-server/src/main/java/gr/iccs/imu/ems/baguette/server/NodeRegistry.java

161 lines
7.0 KiB
Java

/*
* Copyright (C) 2017-2023 Institute of Communication and Computer Systems (imu.iccs.gr)
*
* This Source Code Form is subject to the terms of the Mozilla Public License, v2.0, unless
* Esper library is used, in which case it is subject to the terms of General Public License v2.0.
* If a copy of the MPL was not distributed with this file, you can obtain one at
* https://www.mozilla.org/en-US/MPL/2.0/
*/
package gr.iccs.imu.ems.baguette.server;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;
import java.util.stream.Collectors;
/**
* Node Registry
*/
@Slf4j
@Service
public class NodeRegistry {
private final Map<String,NodeRegistryEntry> registry = new LinkedHashMap<>();
private final List<NodeRegistryEntry> archived = new LinkedList<>();
@Getter @Setter
private ServerCoordinator coordinator;
public synchronized NodeRegistryEntry addNode(Map<String,Object> nodeInfo, String clientId) throws UnknownHostException {
String hostnameOrAddress = getIpAddressFromNodeInfo(nodeInfo);
String ipAddress = hostnameOrAddress;
// Get IP address from provided hostname or address
Throwable errorObj = null;
try {
log.debug("NodeRegistry.addNode(): Resolving IP address from provided hostname/address: {}", hostnameOrAddress);
InetAddress host = InetAddress.getByName(hostnameOrAddress);
log.trace("NodeRegistry.addNode(): InetAddress for provided hostname/address: {}, InetAddress: {}", hostnameOrAddress, host);
String resolvedIpAddress = host.getHostAddress();
log.info("NodeRegistry.addNode(): Provided-Address={}, Resolved-IP-Address={}", hostnameOrAddress, resolvedIpAddress);
ipAddress = resolvedIpAddress;
} catch (UnknownHostException e) {
log.error("NodeRegistry.addNode(): EXCEPTION while resolving IP address from provided hostname/address: {}\n", ipAddress, e);
errorObj = e;
//throw e;
}
nodeInfo.put("original-address", hostnameOrAddress);
nodeInfo.put("address", ipAddress);
// Check if an entry with the same IP address is already registered
NodeRegistryEntry entry = registry.get(ipAddress);
if (entry!=null) {
log.debug("NodeRegistry.addNode(): Node already pre-registered: ip-address={}\nOld Node Info: {}\nNew Node Info: {}",
ipAddress, entry, nodeInfo);
if (coordinator!=null && coordinator.allowAlreadyPreregisteredNode(nodeInfo)) {
log.info("NodeRegistry.addNode(): PREVIOUS NODE INFO WILL BE OVERWRITTEN: ip-address={}\nOld Node Info: {}\nNew Node Info: {}",
ipAddress, entry, nodeInfo);
} else {
log.error("NodeRegistry.addNode(): Node already pre-registered and coordinator does not allow new pre-registration requests to overwrite the existing one: ip-address={}\nOld Node Info: {}\nNew Node Info: {}",
ipAddress, entry, nodeInfo);
throw new IllegalStateException("NODE ALREADY PRE-REGISTERED: "+ipAddress);
}
}
// Create and register node registry entry
entry = new NodeRegistryEntry(ipAddress, clientId, coordinator.getServer()).nodePreregistration(nodeInfo);
if (errorObj!=null) entry.getErrors().add(errorObj);
nodeInfo.put("baguette-client-id", clientId);
registry.put(ipAddress, entry);
log.debug("NodeRegistry.addNode(): Added info for node at address: {}\nNode info: {}", ipAddress, nodeInfo);
return entry;
}
public synchronized void removeNode(NodeRegistryEntry nodeEntry) {
String ipAddress = nodeEntry.getIpAddress();
removeNode(ipAddress);
}
public synchronized void removeNode(Map<String,Object> nodeInfo) {
String ipAddress = getIpAddressFromNodeInfo(nodeInfo);
removeNode(ipAddress);
}
public synchronized void removeNode(String ipAddress) {
registry.remove(ipAddress);
log.debug("NodeRegistry.removeNode(): Removed info for node at address: {}", ipAddress);
}
private String getIpAddressFromNodeInfo(Map<String,Object> nodeInfo) {
Object value = nodeInfo.get("ip-address");
if (value==null || StringUtils.isBlank(value.toString())) value = nodeInfo.get("address");
if (value==null || StringUtils.isBlank(value.toString())) value = nodeInfo.get("ip");
if (value==null || StringUtils.isBlank(value.toString())) return null;
return value.toString();
}
public synchronized void clearNodes() {
registry.clear();
log.debug("NodeRegistry.clearNodes(): Cleared node info registry");
}
public NodeRegistryEntry getNodeByAddress(String ipAddress) {
NodeRegistryEntry entry = registry.get(ipAddress);
log.debug("NodeRegistry.getNodeByAddress(): Returning info for node at address: {}\nNode Info: {}", ipAddress, entry);
return entry;
}
public NodeRegistryEntry getNodeByReference(String ref) {
return registry.values().stream()
.filter(n->n.getReference().equals(ref))
.findAny().orElse(null);
}
public NodeRegistryEntry getNodeByClientId(String clientId) {
return registry.values().stream()
.filter(n->n.getClientId().equals(clientId))
.findAny().orElse(null);
}
public Collection<String> getNodeAddresses() {
return registry.keySet();
}
public Collection<NodeRegistryEntry> getNodes() {
return registry.values();
}
public Collection<String> getNodeReferences() {
return registry.values().stream().map(NodeRegistryEntry::getReference).collect(Collectors.toList());
}
public synchronized void archiveNode(@NonNull NodeRegistryEntry entry) {
log.debug("NodeRegistry.archiveNode(): Archiving node: entry={}", entry);
// Run checks
if (StringUtils.isBlank(entry.getIpAddress())) {
log.warn("NodeRegistry.archiveNode(): Node entry does not have an IP address. Ignoring archiving operation: entry={}", entry);
return;
}
if (! registry.containsKey(entry.getIpAddress())) {
log.warn("NodeRegistry.archiveNode(): Node with IP address {} not found in registry. Ignoring archiving operation: entry={}", entry.getIpAddress(), entry);
return;
}
if (registry.get(entry.getIpAddress())!=entry) {
log.warn("NodeRegistry.archiveNode(): Node passed does not match with node registered to IP address {}. Ignoring archiving operation: entry={}", entry.getIpAddress(), entry);
return;
}
// Archive node
archived.add(entry);
registry.remove(entry.getIpAddress());
entry.nodeArchived(null);
}
}