Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions hadoop-hdds/common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,11 @@ http://maven.apache.org/xsd/maven-4.0.0.xsd">
<artifactId>opentracing-util</artifactId>
<version>0.31.0</version>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.16</version>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,8 @@ public final class ScmConfigKeys {
"hdds.scm.http.kerberos.keytab";

// Network topology
public static final String OZONE_SCM_NETWORK_TOPOLOGY_SCHEMA_FILE_TYPE =
"ozone.scm.network.topology.schema.file.type";
public static final String OZONE_SCM_NETWORK_TOPOLOGY_SCHEMA_FILE =
"ozone.scm.network.topology.schema.file";
public static final String OZONE_SCM_NETWORK_TOPOLOGY_SCHEMA_FILE_DEFAULT =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

import org.apache.hadoop.HadoopIllegalArgumentException;

import java.util.List;

/**
* Network topology schema to housekeeper relevant information.
*/
Expand Down Expand Up @@ -59,13 +61,15 @@ public static LayerType getType(String typeStr) {
}

// default cost
private final int cost;
private int cost;
// layer Type, mandatory property
private final LayerType type;
private LayerType type;
// default name, can be null or ""
private final String defaultName;
private String defaultName;
// layer prefix, can be null or ""
private final String prefix;
private String prefix;
// sublayer
private List<NodeSchema> sublayer;

/**
* Builder for NodeSchema.
Expand Down Expand Up @@ -123,6 +127,14 @@ public NodeSchema(LayerType type, int cost, String prefix,
this.defaultName = defaultName;
}

/**
* Constructor. This constructor is only used when build NodeSchema from
* YAML file.
*/
public NodeSchema() {
this.type = LayerType.INNER_NODE;
}

public boolean matchPrefix(String name) {
if (name == null || name.isEmpty() || prefix == null || prefix.isEmpty()) {
return false;
Expand All @@ -134,15 +146,38 @@ public LayerType getType() {
return this.type;
}

public void setType(LayerType type) {
this.type = type;
}

public String getPrefix() {
return this.prefix;
}

public void setPrefix(String prefix) {
this.prefix = prefix;
}

public String getDefaultName() {
return this.defaultName;
}

public void setDefaultName(String name) {
this.defaultName = name;
}

public int getCost() {
return this.cost;
}
public void setCost(int cost) {
this.cost = cost;
}

public void setSublayer(List<NodeSchema> sublayer) {
this.sublayer = sublayer;
}

public List<NodeSchema> getSublayer() {
return sublayer;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,15 @@
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.hadoop.hdds.scm.net.NodeSchema.LayerType;
import org.yaml.snakeyaml.Yaml;

/**
* A Network topology layer schema loading tool that loads user defined network
Expand Down Expand Up @@ -95,7 +97,7 @@ public List<NodeSchema> getSchemaList() {
* @param schemaFilePath path of schema file
* @return all valid node schemas defined in schema file
*/
public NodeSchemaLoadResult loadSchemaFromFile(String schemaFilePath)
public NodeSchemaLoadResult loadSchemaFromXml(String schemaFilePath)
throws IllegalArgumentException {
try {
File schemaFile = new File(schemaFilePath);
Expand Down Expand Up @@ -165,6 +167,88 @@ private NodeSchemaLoadResult loadSchema(File schemaFile) throws
return schemaList;
}

/**
* Load user defined network layer schemas from a YAML configuration file.
* @param schemaFilePath path of schema file
* @return all valid node schemas defined in schema file
*/
public NodeSchemaLoadResult loadSchemaFromYaml(String schemaFilePath)
throws IllegalArgumentException {
try {
File schemaFile = new File(schemaFilePath);
if (!schemaFile.exists()) {
String msg = "Network topology layer schema file " + schemaFilePath +
" is not found.";
LOG.warn(msg);
throw new IllegalArgumentException(msg);
}
return loadSchemaFromYaml(schemaFile);
} catch (Exception e) {
throw new IllegalArgumentException("Fail to load network topology node"
+ " schema file: " + schemaFilePath + " , error:"
+ e.getMessage());
}
}

/**
* Load network topology layer schemas from a YAML configuration file.
* @param schemaFile schema file
* @return all valid node schemas defined in schema file
* @throws ParserConfigurationException ParserConfigurationException happen
* @throws IOException no such schema file
* @throws SAXException xml file has some invalid elements
* @throws IllegalArgumentException xml file content is logically invalid
*/
private NodeSchemaLoadResult loadSchemaFromYaml(File schemaFile) {
LOG.info("Loading network topology layer schema file {}", schemaFile);
NodeSchemaLoadResult finalSchema;

try {
Yaml yaml = new Yaml();
NodeSchema nodeTree;

try (FileInputStream fileInputStream = new FileInputStream(schemaFile)) {
nodeTree = yaml.loadAs(fileInputStream, NodeSchema.class);
}
List<NodeSchema> schemaList = new ArrayList<>();
if (nodeTree.getType() != LayerType.ROOT) {
throw new IllegalArgumentException("First layer is not a ROOT node."
+ " schema file: " + schemaFile.getAbsolutePath());
}
schemaList.add(nodeTree);
if (nodeTree.getSublayer() != null) {
nodeTree = nodeTree.getSublayer().get(0);
}

while (nodeTree != null) {
if (nodeTree.getType() == LayerType.LEAF_NODE
&& nodeTree.getSublayer() != null) {
throw new IllegalArgumentException("Leaf node in the middle of path."
+ " schema file: " + schemaFile.getAbsolutePath());
}
if (nodeTree.getType() == LayerType.ROOT) {
throw new IllegalArgumentException("Multiple root nodes are defined."
+ " schema file: " + schemaFile.getAbsolutePath());
}
schemaList.add(nodeTree);
if (nodeTree.getSublayer() != null) {
nodeTree = nodeTree.getSublayer().get(0);
} else {
break;
}
}
finalSchema = new NodeSchemaLoadResult(schemaList, true);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new IllegalArgumentException("Fail to load network topology node"
+ " schema file: " + schemaFile.getAbsolutePath() + " , error:"
+ e.getMessage());
}

return finalSchema;
}

/**
* Load layoutVersion from root element in the XML configuration file.
* @param root root element
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,20 @@ public void init(Configuration conf) {
/**
* Load schemas from network topology schema configuration file
*/
String schemaFileType = conf.get(
ScmConfigKeys.OZONE_SCM_NETWORK_TOPOLOGY_SCHEMA_FILE_TYPE);

String schemaFile = conf.get(
ScmConfigKeys.OZONE_SCM_NETWORK_TOPOLOGY_SCHEMA_FILE,
ScmConfigKeys.OZONE_SCM_NETWORK_TOPOLOGY_SCHEMA_FILE_DEFAULT);

NodeSchemaLoadResult result;
try {
result = NodeSchemaLoader.getInstance().loadSchemaFromFile(schemaFile);
if (schemaFileType.toLowerCase().compareTo("yaml") == 0) {
result = NodeSchemaLoader.getInstance().loadSchemaFromYaml(schemaFile);
} else {
result = NodeSchemaLoader.getInstance().loadSchemaFromXml(schemaFile);
}
allSchema = result.getSchemaList();
enforcePrefix = result.isEnforePrefix();
maxLevel = allSchema.size();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# 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
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# 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.

---
# Cost: The cost of crossing this layer.
# The value should be positive integer or 0. This field is optional.
# When it's not defined, it's value is default "1".
cost: 1

# The prefix of this layer.
# If the prefix is "dc", then every name in this layer should start with "dc",
# such as "dc1", "dc2".
# Note that unlike XML schema, the prefix must be specified explicitly if the type is InnerNode.
prefix: /

# Layer type, optional field, default value InnerNode.
# Current value range : {ROOT, INNER_NODE, LEAF_NODE}
type: ROOT

# Layer name
defaultName: root

# Sub layer
# The sub layer property defines as a list which can reflect a node tree, though
# in schema template it always has only one child.
sublayer:
-
cost: 1
prefix: dc
defaultName: datacenter
type: INNER_NODE
sublayer:
-
cost: 1
prefix: rack
defaultName: rack
type: INNER_NODE
sublayer:
-
cost: 1
prefix: ng
defaultName: nodegroup
type: INNER_NODE
sublayer:
-
defaultName: node
type: LEAF_NODE
prefix: node
...
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public TestNodeSchemaLoader(String schemaFile, String errMsg) {
try {
String filePath = classLoader.getResource(
"./networkTopologyTestFiles/" + schemaFile).getPath();
NodeSchemaLoader.getInstance().loadSchemaFromFile(filePath);
NodeSchemaLoader.getInstance().loadSchemaFromXml(filePath);
fail("expect exceptions");
} catch (Throwable e) {
assertTrue(e.getMessage().contains(errMsg));
Expand Down Expand Up @@ -83,7 +83,7 @@ public void testGood() {
try {
String filePath = classLoader.getResource(
"./networkTopologyTestFiles/good.xml").getPath();
NodeSchemaLoader.getInstance().loadSchemaFromFile(filePath);
NodeSchemaLoader.getInstance().loadSchemaFromXml(filePath);
} catch (Throwable e) {
fail("should succeed");
}
Expand All @@ -94,7 +94,7 @@ public void testNotExist() {
String filePath = classLoader.getResource(
"./networkTopologyTestFiles/good.xml").getPath() + ".backup";
try {
NodeSchemaLoader.getInstance().loadSchemaFromFile(filePath);
NodeSchemaLoader.getInstance().loadSchemaFromXml(filePath);
fail("should fail");
} catch (Throwable e) {
assertTrue(e.getMessage().contains("file " + filePath + " is not found"));
Expand Down
Loading