blob: 774d70676c296319798ca5e7d8aadff7c172c483 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.hdds.scm.container;
import org.apache.hadoop.hdds.protocol.DatanodeDetails;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos;
import org.apache.hadoop.hdds.scm.container.placement.metrics.SCMNodeMetric;
import org.apache.hadoop.hdds.scm.container.placement.metrics.SCMNodeStat;
import org.apache.hadoop.hdds.scm.net.NetworkTopology;
import org.apache.hadoop.hdds.scm.node.DatanodeInfo;
import org.apache.hadoop.hdds.scm.node.DatanodeUsageInfo;
import org.apache.hadoop.hdds.scm.node.NodeManager;
import org.apache.hadoop.hdds.scm.node.NodeStatus;
import org.apache.hadoop.hdds.scm.node.states.NodeNotFoundException;
import org.apache.hadoop.hdds.scm.pipeline.Pipeline;
import org.apache.hadoop.hdds.scm.pipeline.PipelineID;
import org.apache.hadoop.hdds.server.events.EventPublisher;
import org.apache.hadoop.ozone.protocol.VersionResponse;
import org.apache.hadoop.ozone.protocol.commands.CommandForDatanode;
import org.apache.hadoop.ozone.protocol.commands.RegisteredCommand;
import org.apache.hadoop.ozone.protocol.commands.SCMCommand;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* Basic implementation of the NodeManager interface which can be used in tests.
*
* TODO - Merge the functionality with MockNodeManager, as it needs refactored
* after the introduction of decommission and maintenance states.
*/
public class SimpleMockNodeManager implements NodeManager {
private Map<UUID, DatanodeInfo> nodeMap = new ConcurrentHashMap<>();
private Map<UUID, Set<PipelineID>> pipelineMap = new ConcurrentHashMap<>();
private Map<UUID, Set<ContainerID>> containerMap = new ConcurrentHashMap<>();
public void register(DatanodeDetails dd, NodeStatus status) {
dd.setPersistedOpState(status.getOperationalState());
dd.setPersistedOpStateExpiryEpochSec(status.getOpStateExpiryEpochSeconds());
nodeMap.put(dd.getUuid(), new DatanodeInfo(dd, status));
}
public void setNodeStatus(DatanodeDetails dd, NodeStatus status) {
dd.setPersistedOpState(status.getOperationalState());
dd.setPersistedOpStateExpiryEpochSec(status.getOpStateExpiryEpochSeconds());
DatanodeInfo dni = nodeMap.get(dd.getUuid());
dni.setNodeStatus(status);
}
/**
* Set the number of pipelines for the given node. This simply generates
* new PipelineID objects and places them in a set. No actual pipelines are
* created.
*
* Setting the count to zero effectively deletes the pipelines for the node
*
* @param dd The DatanodeDetails for which to create the pipelines
* @param count The number of pipelines to create or zero to delete all
* pipelines
*/
public void setPipelines(DatanodeDetails dd, int count) {
Set<PipelineID> pipelines = new HashSet<>();
for (int i=0; i<count; i++) {
pipelines.add(PipelineID.randomId());
}
pipelineMap.put(dd.getUuid(), pipelines);
}
/**
* If the given node was registered with the nodeManager, return the
* NodeStatus for the node. Otherwise return a NodeStatus of "In Service
* and Healthy".
* @param datanodeDetails DatanodeDetails
* @return The NodeStatus of the node if it is registered, otherwise an
* Inservice and Healthy NodeStatus.
*/
@Override
public NodeStatus getNodeStatus(DatanodeDetails datanodeDetails)
throws NodeNotFoundException {
DatanodeInfo dni = nodeMap.get(datanodeDetails.getUuid());
if (dni != null) {
return dni.getNodeStatus();
} else {
return NodeStatus.inServiceHealthy();
}
}
@Override
public void setNodeOperationalState(DatanodeDetails dn,
HddsProtos.NodeOperationalState newState) throws NodeNotFoundException {
setNodeOperationalState(dn, newState, 0);
}
@Override
public void setNodeOperationalState(DatanodeDetails dn,
HddsProtos.NodeOperationalState newState, long opStateExpiryEpocSec)
throws NodeNotFoundException {
DatanodeInfo dni = nodeMap.get(dn.getUuid());
if (dni == null) {
throw new NodeNotFoundException();
}
dni.setNodeStatus(
new NodeStatus(
newState, dni.getNodeStatus().getHealth(), opStateExpiryEpocSec));
}
/**
* Return the set of PipelineID associated with the given DatanodeDetails.
*
* If there are no pipelines, null is return, to mirror the behaviour of
* SCMNodeManager.
*
* @param datanodeDetails The datanode for which to return the pipelines
* @return A set of PipelineID or null if there are none
*/
@Override
public Set<PipelineID> getPipelines(DatanodeDetails datanodeDetails) {
Set<PipelineID> p = pipelineMap.get(datanodeDetails.getUuid());
if (p == null || p.size() == 0) {
return null;
} else {
return p;
}
}
@Override
public int getPipelinesCount(DatanodeDetails datanodeDetails) {
return 0;
}
@Override
public void setContainers(DatanodeDetails dn,
Set<ContainerID> containerIds) throws NodeNotFoundException {
containerMap.put(dn.getUuid(), containerIds);
}
/**
* Return the set of ContainerID associated with the datanode. If there are no
* container present, an empty set is return to mirror the behaviour of
* SCMNodeManaer
*
* @param dn The datanodeDetails for which to return the containers
* @return A Set of ContainerID or an empty Set if none are present
* @throws NodeNotFoundException
*/
@Override
public Set<ContainerID> getContainers(DatanodeDetails dn)
throws NodeNotFoundException {
// The concrete implementation of this method in SCMNodeManager will return
// an empty set if there are no containers, and will never return null.
return containerMap
.computeIfAbsent(dn.getUuid(), key -> new HashSet<>());
}
/**
* Below here, are all auto-generate placeholder methods to implement the
* interface.
*/
@Override
public List<DatanodeDetails> getNodes(NodeStatus nodeStatus) {
return null;
}
@Override
public List<DatanodeDetails> getNodes(
HddsProtos.NodeOperationalState opState, HddsProtos.NodeState health) {
return null;
}
@Override
public int getNodeCount(NodeStatus nodeStatus) {
return 0;
}
@Override
public int getNodeCount(HddsProtos.NodeOperationalState opState,
HddsProtos.NodeState health) {
return 0;
}
@Override
public List<DatanodeDetails> getAllNodes() {
return null;
}
@Override
public SCMNodeStat getStats() {
return null;
}
@Override
public Map<DatanodeDetails, SCMNodeStat> getNodeStats() {
return null;
}
/**
* Gets a sorted list of most or least used DatanodeUsageInfo containing
* healthy, in-service nodes. If the specified mostUsed is true, the returned
* list is in descending order of usage. Otherwise, the returned list is in
* ascending order of usage.
*
* @param mostUsed true if most used, false if least used
* @return List of DatanodeUsageInfo
*/
@Override
public List<DatanodeUsageInfo> getMostOrLeastUsedDatanodes(boolean mostUsed) {
return null;
}
@Override
public SCMNodeMetric getNodeStat(DatanodeDetails datanodeDetails) {
return null;
}
@Override
public void addPipeline(Pipeline pipeline) {
}
@Override
public void removePipeline(Pipeline pipeline) {
}
@Override
public void addContainer(DatanodeDetails datanodeDetails,
ContainerID containerId) throws NodeNotFoundException {
}
@Override
public void addDatanodeCommand(UUID dnId, SCMCommand command) {
}
@Override
public void processNodeReport(DatanodeDetails datanodeDetails,
StorageContainerDatanodeProtocolProtos.NodeReportProto nodeReport) {
}
@Override
public List<SCMCommand> getCommandQueue(UUID dnID) {
return null;
}
@Override
public DatanodeDetails getNodeByUuid(String uuid) {
return null;
}
@Override
public List<DatanodeDetails> getNodesByAddress(String address) {
return null;
}
@Override
public NetworkTopology getClusterNetworkTopologyMap() {
return null;
}
@Override
public int minHealthyVolumeNum(List<DatanodeDetails> dnList) {
return 0;
}
@Override
public int pipelineLimit(DatanodeDetails dn) {
return 1;
}
@Override
public int minPipelineLimit(List<DatanodeDetails> dn) {
return 0;
}
@Override
public void close() throws IOException {
}
@Override
public Map<String, Map<String, Integer>> getNodeCount() {
return null;
}
@Override
public Map<String, Long> getNodeInfo() {
return null;
}
@Override
public void onMessage(CommandForDatanode commandForDatanode,
EventPublisher publisher) {
}
@Override
public VersionResponse getVersion(
StorageContainerDatanodeProtocolProtos.SCMVersionRequestProto
versionRequest) {
return null;
}
@Override
public RegisteredCommand register(DatanodeDetails datanodeDetails,
StorageContainerDatanodeProtocolProtos.NodeReportProto nodeReport,
StorageContainerDatanodeProtocolProtos.PipelineReportsProto
pipelineReport) {
return null;
}
@Override
public List<SCMCommand> processHeartbeat(DatanodeDetails datanodeDetails) {
return null;
}
@Override
public Boolean isNodeRegistered(DatanodeDetails datanodeDetails) {
return false;
}
}