You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sk...@apache.org on 2021/06/07 12:29:46 UTC
[ignite-3] branch main updated: IGNITE-14413 Added start of new
node from cli interface. Fixes #157
This is an automated email from the ASF dual-hosted git repository.
sk0x50 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new 44d69d3 IGNITE-14413 Added start of new node from cli interface. Fixes #157
44d69d3 is described below
commit 44d69d37013c81ce5055a262e7961c72b4ec3d7c
Author: Kirill Gusakov <kg...@gmail.com>
AuthorDate: Mon Jun 7 15:29:09 2021 +0300
IGNITE-14413 Added start of new node from cli interface. Fixes #157
Signed-off-by: Slava Koptilin <sl...@gmail.com>
---
.../main/java/org/apache/ignite/app/Ignition.java | 7 +-
.../org/apache/ignite/app/IgnitionManager.java | 12 +-
.../schemas/runner/NodeConfigurationSchema.java | 5 -
.../ignite/cli/builtins/node/NodeManager.java | 52 ++++----
.../apache/ignite/cli/spec/NodeCommandSpec.java | 19 ++-
.../apache/ignite/cli/IgniteCliInterfaceTest.java | 14 +--
.../internal/metastorage/MetaStorageManager.java | 18 ++-
.../runner/app/DynamicTableCreationTest.java | 30 +++--
.../ignite/internal/runner/app/IgnitionTest.java | 28 ++---
.../internal/runner/app/TableCreationTest.java | 25 ++--
.../org/apache/ignite/app/IgniteCliRunner.java | 134 +++++++++++++++++++++
.../java/org/apache/ignite/app/IgniteRunner.java | 25 ----
.../apache/ignite/internal/app/IgnitionImpl.java | 15 +--
.../internal/table/distributed/TableManager.java | 2 +-
.../ignite/internal/table/TableManagerTest.java | 3 +-
.../apache/ignite/internal/vault/VaultManager.java | 34 ++++++
16 files changed, 280 insertions(+), 143 deletions(-)
diff --git a/modules/api/src/main/java/org/apache/ignite/app/Ignition.java b/modules/api/src/main/java/org/apache/ignite/app/Ignition.java
index 9904f4c..4bacc4e 100644
--- a/modules/api/src/main/java/org/apache/ignite/app/Ignition.java
+++ b/modules/api/src/main/java/org/apache/ignite/app/Ignition.java
@@ -17,6 +17,7 @@
package org.apache.ignite.app;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
@@ -26,9 +27,11 @@ import org.jetbrains.annotations.Nullable;
public interface Ignition {
/**
* Starts Ignite node with optional bootstrap configuration in json format.
- * @param jsonStrBootstrapCfg Node configuration in json format.
+ *
+ * @param name Name of the node. Couldn't be {@code null}.
+ * @param jsonStrBootstrapCfg Node configuration in json format. Could be {@code null}.
* @return Started Ignite node.
*/
// TODO: IGNITE-14599 Add generic way to bootstrap configuration.
- public Ignite start(@Nullable String jsonStrBootstrapCfg);
+ public Ignite start(@NotNull String name, @Nullable String jsonStrBootstrapCfg);
}
diff --git a/modules/api/src/main/java/org/apache/ignite/app/IgnitionManager.java b/modules/api/src/main/java/org/apache/ignite/app/IgnitionManager.java
index 1d66c30..0ebc6f5 100644
--- a/modules/api/src/main/java/org/apache/ignite/app/IgnitionManager.java
+++ b/modules/api/src/main/java/org/apache/ignite/app/IgnitionManager.java
@@ -18,6 +18,7 @@
package org.apache.ignite.app;
import java.util.ServiceLoader;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
@@ -29,21 +30,24 @@ public class IgnitionManager {
/**
* Starts Ignite node with optional bootstrap configuration in json format.
+ *
+ * @param nodeName Name of the node.
* @param jsonStrBootstrapCfg Node configuration in json format.
* @return Started Ignite node.
*/
// TODO IGNITE-14580 Add exception handling logic to IgnitionProcessor.
- public static synchronized Ignite start(@Nullable String jsonStrBootstrapCfg) {
+ public static synchronized Ignite start(@NotNull String nodeName, @Nullable String jsonStrBootstrapCfg) {
if (ignition == null) {
ServiceLoader<Ignition> ldr = ServiceLoader.load(Ignition.class);
ignition = ldr.iterator().next();
}
- return ignition.start(jsonStrBootstrapCfg);
+ return ignition.start(nodeName, jsonStrBootstrapCfg);
}
/**
* Starts Ignite node with optional bootstrap configuration in json format.
+ * @param nodeName Name of the node.
* @param jsonStrBootstrapCfg Node configuration in json format.
* @param clsLdr The class loader to be used to load provider-configuration files
* and provider classes, or {@code null} if the system class
@@ -51,12 +55,12 @@ public class IgnitionManager {
* @return Started Ignite node.
*/
// TODO IGNITE-14580 Add exception handling logic to IgnitionProcessor.
- public static synchronized Ignite start(@Nullable String jsonStrBootstrapCfg, @Nullable ClassLoader clsLdr) {
+ public static synchronized Ignite start(@NotNull String nodeName, @Nullable String jsonStrBootstrapCfg, @Nullable ClassLoader clsLdr) {
if (ignition == null) {
ServiceLoader<Ignition> ldr = ServiceLoader.load(Ignition.class, clsLdr);
ignition = ldr.iterator().next();
}
- return ignition.start(jsonStrBootstrapCfg);
+ return ignition.start(nodeName, jsonStrBootstrapCfg);
}
}
diff --git a/modules/api/src/main/java/org/apache/ignite/configuration/schemas/runner/NodeConfigurationSchema.java b/modules/api/src/main/java/org/apache/ignite/configuration/schemas/runner/NodeConfigurationSchema.java
index 0d3d9f1..c0545c4 100644
--- a/modules/api/src/main/java/org/apache/ignite/configuration/schemas/runner/NodeConfigurationSchema.java
+++ b/modules/api/src/main/java/org/apache/ignite/configuration/schemas/runner/NodeConfigurationSchema.java
@@ -17,7 +17,6 @@
package org.apache.ignite.configuration.schemas.runner;
-import java.util.UUID;
import org.apache.ignite.configuration.annotation.ConfigurationRoot;
import org.apache.ignite.configuration.annotation.Value;
import org.apache.ignite.configuration.storage.ConfigurationType;
@@ -27,10 +26,6 @@ import org.apache.ignite.configuration.storage.ConfigurationType;
*/
@ConfigurationRoot(rootName = "node", type = ConfigurationType.LOCAL)
public class NodeConfigurationSchema {
- /** Uniq local node name. */
- @Value(hasDefault = true)
- public final String name = UUID.randomUUID().toString();
-
/** It is a copy of appropriate property from the cluster configuration. */
@Value(hasDefault = true)
public final String[] metastorageNodes = new String[0];
diff --git a/modules/cli/src/main/java/org/apache/ignite/cli/builtins/node/NodeManager.java b/modules/cli/src/main/java/org/apache/ignite/cli/builtins/node/NodeManager.java
index ec93d8d..5e4b1f2 100644
--- a/modules/cli/src/main/java/org/apache/ignite/cli/builtins/node/NodeManager.java
+++ b/modules/cli/src/main/java/org/apache/ignite/cli/builtins/node/NodeManager.java
@@ -43,7 +43,7 @@ import org.jline.terminal.Terminal;
@Singleton
public class NodeManager {
/** Entry point of core Ignite artifact for running new node. */
- private static final String MAIN_CLASS = "org.apache.ignite.app.IgniteRunner";
+ private static final String MAIN_CLASS = "org.apache.ignite.app.IgniteCliRunner";
/** Timeout for successful node start. */
private static final Duration NODE_START_TIMEOUT = Duration.ofSeconds(30);
@@ -70,19 +70,19 @@ public class NodeManager {
* It has very naive implementation of successful run check -
* just waiting for appropriate message in the node logs.
*
- * @param consistentId Node consistent id.
+ * @param nodeName Node name.
* @param logDir Log dir for receiving node state.
* @param pidsDir Dir where pid files of running nodes will be stored.
* @param srvCfg Config for Ignite node
* @param out PrintWriter for user messages.
* @return Information about successfully started node
*/
- public RunningNode start(String consistentId, Path logDir, Path pidsDir, Path srvCfg, PrintWriter out) {
- if (getRunningNodes(logDir, pidsDir).stream().anyMatch(n -> n.consistentId.equals(consistentId)))
- throw new IgniteCLIException("Node with consistentId " + consistentId + " is already exist");
+ public RunningNode start(String nodeName, Path logDir, Path pidsDir, Path srvCfg, PrintWriter out) {
+ if (getRunningNodes(logDir, pidsDir).stream().anyMatch(n -> n.name.equals(nodeName)))
+ throw new IgniteCLIException("Node with nodeName " + nodeName + " is already exist");
try {
- Path logFile = logFile(logDir, consistentId);
+ Path logFile = logFile(logDir, nodeName);
if (Files.exists(logFile))
Files.delete(logFile);
@@ -100,6 +100,8 @@ public class NodeManager {
cmdArgs.add(srvCfg.toAbsolutePath().toString());
}
+ cmdArgs.add(nodeName);
+
ProcessBuilder pb = new ProcessBuilder(
cmdArgs
)
@@ -121,9 +123,9 @@ public class NodeManager {
throw new IgniteCLIException("Waiting for node start was failed", e);
}
- createPidFile(consistentId, p.pid(), pidsDir);
+ createPidFile(nodeName, p.pid(), pidsDir);
- return new RunningNode(p.pid(), consistentId, logFile);
+ return new RunningNode(p.pid(), nodeName, logFile);
}
catch (IOException e) {
throw new IgniteCLIException("Can't load classpath", e);
@@ -188,17 +190,17 @@ public class NodeManager {
/**
* Creates pid file for Ignite node.
*
- * @param consistentId Node consistent id.
+ * @param nodeName Node name.
* @param pid Pid
* @param pidsDir Dir for storing pid files.
*/
- public void createPidFile(String consistentId, long pid, Path pidsDir) {
+ public void createPidFile(String nodeName, long pid, Path pidsDir) {
if (!Files.exists(pidsDir)) {
if (!pidsDir.toFile().mkdirs())
throw new IgniteCLIException("Can't create directory for storing the process pids: " + pidsDir);
}
- Path pidPath = pidsDir.resolve(consistentId + "_" + System.currentTimeMillis() + ".pid");
+ Path pidPath = pidsDir.resolve(nodeName + "_" + System.currentTimeMillis() + ".pid");
try (FileWriter fileWriter = new FileWriter(pidPath.toFile())) {
fileWriter.write(String.valueOf(pid));
@@ -235,9 +237,9 @@ public class NodeManager {
if (filename.lastIndexOf('_') == -1)
return Optional.<RunningNode>empty();
else {
- String consistentId = filename.substring(0, filename.lastIndexOf('_'));
+ String nodeName = filename.substring(0, filename.lastIndexOf('_'));
- return Optional.of(new RunningNode(pid, consistentId, logFile(logDir, consistentId)));
+ return Optional.of(new RunningNode(pid, nodeName, logFile(logDir, nodeName)));
}
})
@@ -253,18 +255,18 @@ public class NodeManager {
}
/**
- * Stops the node by consistent id and waits for success.
+ * Stops the node by name and waits for success.
*
- * @param consistentId Node consistent id.
+ * @param nodeName Node name.
* @param pidsDir Dir with running nodes pids.
* @return true if stopped, false otherwise.
*/
- public boolean stopWait(String consistentId, Path pidsDir) {
+ public boolean stopWait(String nodeName, Path pidsDir) {
if (Files.exists(pidsDir)) {
try {
List<Path> files = Files.find(pidsDir, 1,
(f, attrs) ->
- f.getFileName().toString().startsWith(consistentId + "_")).collect(Collectors.toList());
+ f.getFileName().toString().startsWith(nodeName + "_")).collect(Collectors.toList());
if (!files.isEmpty()) {
return files.stream().map(f -> {
@@ -283,7 +285,7 @@ public class NodeManager {
}).reduce((a, b) -> a && b).orElse(false);
}
else
- throw new IgniteCLIException("Can't find node with consistent id " + consistentId);
+ throw new IgniteCLIException("Can't find node with name" + nodeName);
}
catch (IOException e) {
throw new IgniteCLIException("Can't open directory with pid files " + pidsDir);
@@ -308,11 +310,11 @@ public class NodeManager {
/**
* @param logDir Ignite log dir.
- * @param consistentId Node consistent id.
+ * @param nodeName Node name.
* @return Path of node log file.
*/
- private static Path logFile(Path logDir, String consistentId) {
- return logDir.resolve(consistentId + ".log");
+ private static Path logFile(Path logDir, String nodeName) {
+ return logDir.resolve(nodeName + ".log");
}
/**
@@ -324,7 +326,7 @@ public class NodeManager {
public final long pid;
/** Consistent id. */
- public final String consistentId;
+ public final String name;
/** Path to log file. */
public final Path logFile;
@@ -333,12 +335,12 @@ public class NodeManager {
* Creates info about running node.
*
* @param pid Pid.
- * @param consistentId Consistent id.
+ * @param name Consistent id.
* @param logFile Log file.
*/
- public RunningNode(long pid, String consistentId, Path logFile) {
+ public RunningNode(long pid, String name, Path logFile) {
this.pid = pid;
- this.consistentId = consistentId;
+ this.name = name;
this.logFile = logFile;
}
}
diff --git a/modules/cli/src/main/java/org/apache/ignite/cli/spec/NodeCommandSpec.java b/modules/cli/src/main/java/org/apache/ignite/cli/spec/NodeCommandSpec.java
index fdcf9c2..e394626 100644
--- a/modules/cli/src/main/java/org/apache/ignite/cli/spec/NodeCommandSpec.java
+++ b/modules/cli/src/main/java/org/apache/ignite/cli/spec/NodeCommandSpec.java
@@ -60,8 +60,8 @@ public class NodeCommandSpec extends CategorySpec {
private NodeManager nodeMgr;
/** Consistent id, which will be used by new node. */
- @CommandLine.Parameters(paramLabel = "consistent-id", description = "Consistent ID of the new node")
- public String consistentId;
+ @CommandLine.Parameters(paramLabel = "name", description = "Name of the new node")
+ public String nodeName;
/** Path to node config. */
@CommandLine.Option(names = "--config", description = "Configuration file to start the node with")
@@ -74,19 +74,19 @@ public class NodeCommandSpec extends CategorySpec {
PrintWriter out = spec.commandLine().getOut();
ColorScheme cs = spec.commandLine().getColorScheme();
- NodeManager.RunningNode node = nodeMgr.start(consistentId, ignitePaths.logDir,
+ NodeManager.RunningNode node = nodeMgr.start(nodeName, ignitePaths.logDir,
ignitePaths.cliPidsDir(),
configPath,
out);
out.println();
out.println("Node is successfully started. To stop, type " +
- cs.commandText("ignite node stop ") + cs.parameterText(node.consistentId));
+ cs.commandText("ignite node stop ") + cs.parameterText(node.name));
out.println();
Table tbl = new Table(0, cs);
- tbl.addRow("@|bold Consistent ID|@", node.consistentId);
+ tbl.addRow("@|bold Node name|@", node.name);
tbl.addRow("@|bold PID|@", node.pid);
tbl.addRow("@|bold Log File|@", node.logFile);
@@ -170,9 +170,8 @@ public class NodeCommandSpec extends CategorySpec {
tbl.addRow("@|bold Consistent ID|@", "@|bold PID|@", "@|bold Log File|@");
- for (NodeManager.RunningNode node : nodes) {
- tbl.addRow(node.consistentId, node.pid, node.logFile);
- }
+ for (NodeManager.RunningNode node : nodes)
+ tbl.addRow(node.name, node.pid, node.logFile);
out.println(tbl);
}
@@ -197,14 +196,12 @@ public class NodeCommandSpec extends CategorySpec {
out.println(Ansi.AUTO.string("@|bold Current Ignite node classpath:|@"));
- for (String item : items) {
+ for (String item : items)
out.println(" " + item);
- }
}
catch (IOException e) {
throw new IgniteCLIException("Can't get current classpath", e);
}
}
}
-
}
diff --git a/modules/cli/src/test/java/org/apache/ignite/cli/IgniteCliInterfaceTest.java b/modules/cli/src/test/java/org/apache/ignite/cli/IgniteCliInterfaceTest.java
index 1946f2d..c24231d 100644
--- a/modules/cli/src/test/java/org/apache/ignite/cli/IgniteCliInterfaceTest.java
+++ b/modules/cli/src/test/java/org/apache/ignite/cli/IgniteCliInterfaceTest.java
@@ -336,13 +336,13 @@ public class IgniteCliInterfaceTest extends AbstractCliTest {
cli.getOut());
assertEquals("\nNode is successfully started. To stop, type ignite node stop " + nodeName + "\n\n" +
- "+---------------+---------+\n" +
- "| Consistent ID | node1 |\n" +
- "+---------------+---------+\n" +
- "| PID | 1 |\n" +
- "+---------------+---------+\n" +
- "| Log File | logfile |\n" +
- "+---------------+---------+\n",
+ "+-----------+---------+\n" +
+ "| Node name | node1 |\n" +
+ "+-----------+---------+\n" +
+ "| PID | 1 |\n" +
+ "+-----------+---------+\n" +
+ "| Log File | logfile |\n" +
+ "+-----------+---------+\n",
out.toString());
}
diff --git a/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/MetaStorageManager.java b/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/MetaStorageManager.java
index 6801c75..d56a550 100644
--- a/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/MetaStorageManager.java
+++ b/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/MetaStorageManager.java
@@ -122,9 +122,6 @@ public class MetaStorageManager {
watchAggregator = new WatchAggregator();
deployFut = new CompletableFuture<>();
- String locNodeName = locCfgMgr.configurationRegistry().getConfiguration(NodeConfiguration.KEY)
- .name().value();
-
String[] metastorageNodes = locCfgMgr.configurationRegistry().getConfiguration(NodeConfiguration.KEY)
.metastorageNodes().value();
@@ -503,20 +500,19 @@ public class MetaStorageManager {
* @param configurationMgr Configuration manager.
* @return {@code true} if the node has meta storage, {@code false} otherwise.
*/
- public static boolean hasMetastorageLocally(ConfigurationManager configurationMgr) {
- String locNodeName = configurationMgr
- .configurationRegistry()
- .getConfiguration(NodeConfiguration.KEY)
- .name()
- .value();
-
+ public boolean hasMetastorageLocally(ConfigurationManager configurationMgr) {
String[] metastorageMembers = configurationMgr
.configurationRegistry()
.getConfiguration(NodeConfiguration.KEY)
.metastorageNodes()
.value();
- return hasMetastorage(locNodeName, metastorageMembers);
+ try {
+ return hasMetastorage(vaultMgr.name(), metastorageMembers);
+ }
+ catch (IgniteInternalCheckedException e) {
+ throw new IgniteInternalException(e);
+ }
}
// TODO: IGNITE-14691 Temporally solution that should be removed after implementing reactive watches.
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/DynamicTableCreationTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/DynamicTableCreationTest.java
index fa2eb95..6c76f04 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/DynamicTableCreationTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/DynamicTableCreationTest.java
@@ -18,7 +18,9 @@
package org.apache.ignite.internal.runner.app;
import java.util.ArrayList;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
import java.util.UUID;
import org.apache.ignite.app.Ignite;
import org.apache.ignite.app.IgnitionManager;
@@ -47,41 +49,37 @@ class DynamicTableCreationTest {
private static final IgniteLogger LOG = IgniteLogger.forClass(SchemaManager.class);
/** Nodes bootstrap configuration. */
- private final String[] nodesBootstrapCfg =
- {
- "{\n" +
+ private final Map<String, String> nodesBootstrapCfg = new LinkedHashMap<>() {{
+ put("node0", "{\n" +
" \"node\": {\n" +
- " \"name\":node0,\n" +
" \"metastorageNodes\":[ \"node0\" ]\n" +
" },\n" +
" \"network\": {\n" +
" \"port\":3344,\n" +
" \"netClusterNodes\":[ \"localhost:3344\", \"localhost:3345\", \"localhost:3346\" ]\n" +
" }\n" +
- "}",
+ "}");
- "{\n" +
+ put("node1", "{\n" +
" \"node\": {\n" +
- " \"name\":node1,\n" +
" \"metastorageNodes\":[ \"node0\" ]\n" +
" },\n" +
" \"network\": {\n" +
" \"port\":3345,\n" +
" \"netClusterNodes\":[ \"localhost:3344\", \"localhost:3345\", \"localhost:3346\" ]\n" +
" }\n" +
- "}",
+ "}");
- "{\n" +
+ put("node2", "{\n" +
" \"node\": {\n" +
- " \"name\":node2,\n" +
" \"metastorageNodes\":[ \"node0\"]\n" +
" },\n" +
" \"network\": {\n" +
" \"port\":3346,\n" +
" \"netClusterNodes\":[ \"localhost:3344\", \"localhost:3345\", \"localhost:3346\" ]\n" +
" }\n" +
- "}",
- };
+ "}");
+ }};
/**
* Check dynamic table creation.
@@ -90,8 +88,8 @@ class DynamicTableCreationTest {
void testDynamicSimpleTableCreation() {
List<Ignite> clusterNodes = new ArrayList<>();
- for (String nodeBootstrapCfg : nodesBootstrapCfg)
- clusterNodes.add(IgnitionManager.start(nodeBootstrapCfg));
+ for (Map.Entry<String, String> nodeBootstrapCfg : nodesBootstrapCfg.entrySet())
+ clusterNodes.add(IgnitionManager.start(nodeBootstrapCfg.getKey(), nodeBootstrapCfg.getValue()));
assertEquals(3, clusterNodes.size());
@@ -159,8 +157,8 @@ class DynamicTableCreationTest {
void testDynamicTableCreation() {
List<Ignite> clusterNodes = new ArrayList<>();
- for (String nodeBootstrapCfg : nodesBootstrapCfg)
- clusterNodes.add(IgnitionManager.start(nodeBootstrapCfg));
+ for (Map.Entry<String, String> nodeBootstrapCfg : nodesBootstrapCfg.entrySet())
+ clusterNodes.add(IgnitionManager.start(nodeBootstrapCfg.getKey(), nodeBootstrapCfg.getValue()));
assertEquals(3, clusterNodes.size());
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/IgnitionTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/IgnitionTest.java
index f914c51..e5a25a8 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/IgnitionTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/IgnitionTest.java
@@ -18,7 +18,9 @@
package org.apache.ignite.internal.runner.app;
import java.util.ArrayList;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
import org.apache.ignite.app.Ignite;
import org.apache.ignite.app.IgnitionManager;
import org.junit.jupiter.api.Assertions;
@@ -30,41 +32,37 @@ import org.junit.jupiter.api.Test;
*/
class IgnitionTest {
/** Nodes bootstrap configuration. */
- private final String[] nodesBootstrapCfg =
- {
- "{\n" +
+ private final Map<String, String> nodesBootstrapCfg = new LinkedHashMap<>() {{
+ put("node0", "{\n" +
" \"node\": {\n" +
- " \"name\":node0,\n" +
" \"metastorageNodes\":[ \"node0\" ]\n" +
" },\n" +
" \"network\": {\n" +
" \"port\":3344,\n" +
" \"netClusterNodes\":[ \"localhost:3344\", \"localhost:3345\", \"localhost:3346\" ]\n" +
" }\n" +
- "}",
+ "}");
- "{\n" +
+ put("node1", "{\n" +
" \"node\": {\n" +
- " \"name\":node1,\n" +
" \"metastorageNodes\":[ \"node0\" ]\n" +
" },\n" +
" \"network\": {\n" +
" \"port\":3345,\n" +
" \"netClusterNodes\":[ \"localhost:3344\", \"localhost:3345\", \"localhost:3346\" ]\n" +
" }\n" +
- "}",
+ "}");
- "{\n" +
+ put("node2", "{\n" +
" \"node\": {\n" +
- " \"name\":node2,\n" +
" \"metastorageNodes\":[ \"node0\" ]\n" +
" },\n" +
" \"network\": {\n" +
" \"port\":3346,\n" +
" \"netClusterNodes\":[ \"localhost:3344\", \"localhost:3345\", \"localhost:3346\" ]\n" +
" }\n" +
- "}",
- };
+ "}");
+ }};
/**
* Check that Ignition.start() with bootstrap configuration returns Ignite instance.
@@ -73,8 +71,8 @@ class IgnitionTest {
void testNodesStartWithBootstrapConfiguration() {
List<Ignite> startedNodes = new ArrayList<>();
- for (String nodeBootstrapCfg : nodesBootstrapCfg)
- startedNodes.add(IgnitionManager.start(nodeBootstrapCfg));
+ for (Map.Entry<String, String> nodeBootstrapCfg : nodesBootstrapCfg.entrySet())
+ startedNodes.add(IgnitionManager.start(nodeBootstrapCfg.getKey(), nodeBootstrapCfg.getValue()));
Assertions.assertEquals(3, startedNodes.size());
@@ -87,7 +85,7 @@ class IgnitionTest {
@Test
@Disabled("https://issues.apache.org/jira/browse/IGNITE-14709")
void testNodeStartWithoutBootstrapConfiguration() {
- Ignite ignite = IgnitionManager.start(null);
+ Ignite ignite = IgnitionManager.start("node0", null);
Assertions.assertNotNull(ignite);
}
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/TableCreationTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/TableCreationTest.java
index e9834ae..90a5a39 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/TableCreationTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/TableCreationTest.java
@@ -18,7 +18,9 @@
package org.apache.ignite.internal.runner.app;
import java.util.ArrayList;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
import java.util.UUID;
import org.apache.ignite.app.Ignite;
import org.apache.ignite.app.IgnitionManager;
@@ -38,9 +40,8 @@ import static org.junit.jupiter.api.Assertions.assertNull;
@Disabled("https://issues.apache.org/jira/browse/IGNITE-14578")
class TableCreationTest {
/** Nodes bootstrap configuration with preconfigured tables. */
- private final String[] nodesBootstrapCfg =
- {
- "{\n" +
+ private final LinkedHashMap<String, String> nodesBootstrapCfg = new LinkedHashMap<>() {{
+ put("node0", "{\n" +
" \"node\": {\n" +
" \"name\":node0,\n" +
" \"metastorageNodes\":[ \"node0\", \"node1\" ]\n" +
@@ -124,30 +125,28 @@ class TableCreationTest {
" }\n" + /* Table. */
" }\n" + /* Tables. */
" }\n" + /* Root. */
- "}",
+ "}");
- "{\n" +
+ put("node1", "{\n" +
" \"node\": {\n" +
- " \"name\":node1,\n" +
" \"metastorageNodes\":[ \"node0\", \"node1\" ]\n" +
" },\n" +
" \"network\": {\n" +
" \"port\":3345,\n" +
" \"netClusterNodes\":[ \"localhost:3344\", \"localhost:3345\", \"localhost:3346\" ]\n" +
" }\n" +
- "}",
+ "}");
- "{\n" +
+ put("node2", "{\n" +
" \"node\": {\n" +
- " \"name\":node2,\n" +
" \"metastorageNodes\":[ \"node0\", \"node1\" ]\n" +
" },\n" +
" \"network\": {\n" +
" \"port\":3346,\n" +
" \"netClusterNodes\":[ \"localhost:3344\", \"localhost:3345\", \"localhost:3346\" ]\n" +
" }\n" +
- "}",
- };
+ "}");
+ }};
/**
* Check table creation via bootstrap configuration with pre-configured table.
@@ -156,8 +155,8 @@ class TableCreationTest {
void testInitialSimpleTableConfiguration() {
List<Ignite> clusterNodes = new ArrayList<>();
- for (String nodeBootstrapCfg : nodesBootstrapCfg)
- clusterNodes.add(IgnitionManager.start(nodeBootstrapCfg));
+ for (Map.Entry<String, String> nodeBootstrapCfg : nodesBootstrapCfg.entrySet())
+ clusterNodes.add(IgnitionManager.start(nodeBootstrapCfg.getKey(), nodeBootstrapCfg.getValue()));
assertEquals(3, clusterNodes.size());
diff --git a/modules/runner/src/main/java/org/apache/ignite/app/IgniteCliRunner.java b/modules/runner/src/main/java/org/apache/ignite/app/IgniteCliRunner.java
new file mode 100644
index 0000000..b99ada2
--- /dev/null
+++ b/modules/runner/src/main/java/org/apache/ignite/app/IgniteCliRunner.java
@@ -0,0 +1,134 @@
+/*
+ * 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.
+ */
+
+package org.apache.ignite.app;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.InvalidPathException;
+import java.nio.file.Path;
+import org.apache.ignite.internal.app.IgnitionImpl;
+import org.apache.ignite.lang.IgniteInternalCheckedException;
+
+/**
+ * The main entry point for run new Ignite node from CLI toolchain.
+ */
+public class IgniteCliRunner {
+ /** CLI usage message. */
+ private static String usage = "IgniteCliRunner [--config conf] nodeName";
+
+ /**
+ * Main method for run new Ignite node.
+ *
+ * For CLI args info see {@link IgniteCliRunner#usage}
+ *
+ * @param args CLI args to start new node.
+ * @throws IOException if any issues with reading config file.
+ */
+ public static void main(String[] args) throws IOException {
+ Args parsedArgs = null;
+
+ try {
+ parsedArgs = Args.parseArgs(args);
+ }
+ catch (Args.ParseException e) {
+ if (e.getMessage() != null)
+ System.out.println(e.getMessage() + "\n");
+
+ System.out.println(usage);
+
+ System.exit(1);
+ }
+
+ String jsonCfgStr = null;
+
+ if (parsedArgs.config != null)
+ jsonCfgStr = Files.readString(parsedArgs.config);
+
+ var ignition = new IgnitionImpl();
+
+ ignition.start(parsedArgs.nodeName, jsonCfgStr);
+ }
+
+ /**
+ * Simple value object with parsed CLI args of ignite runner.
+ */
+ private static class Args {
+ /** Name of the node. */
+ private final String nodeName;
+
+ /** Path to config file. */
+ private final Path config;
+
+ /**
+ * Creates new instance with parsed arguments.
+ *
+ * @param nodeName Name of the node.
+ * @param config Path to config file.
+ */
+ private Args(String nodeName, Path config) {
+ this.nodeName = nodeName;
+ this.config = config;
+ }
+
+ /**
+ * Simple CLI arguments parser.
+ *
+ * @param args CLI arguments.
+ * @return Parsed arguments.
+ * @throws ParseException if required args are absent.
+ */
+ private static Args parseArgs(String[] args) throws ParseException {
+ if (args.length == 1)
+ return new Args(args[0], null);
+ else if (args.length == 3) {
+ if ("--config".equals(args[0])) {
+ try {
+ return new Args(args[2], Path.of(args[1]));
+ }
+ catch (InvalidPathException e) {
+ throw new ParseException("Couldn't parse configuration path.");
+ }
+ }
+ else
+ throw new ParseException();
+ }
+ else
+ throw new ParseException();
+ }
+
+ /**
+ * Exception for indicate any problems with parsing CLI args.
+ */
+ private static class ParseException extends IgniteInternalCheckedException {
+ /**
+ * Creates new exception of parsing.
+ *
+ * @param msg Message.
+ */
+ private ParseException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Creates new exception of parsing.
+ */
+ private ParseException() {
+ }
+ }
+ }
+}
diff --git a/modules/runner/src/main/java/org/apache/ignite/app/IgniteRunner.java b/modules/runner/src/main/java/org/apache/ignite/app/IgniteRunner.java
deleted file mode 100644
index 61c5f9c..0000000
--- a/modules/runner/src/main/java/org/apache/ignite/app/IgniteRunner.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.
- */
-
-package org.apache.ignite.app;
-
-/**
- * Sample application integrating new configuration module and providing standard REST API to access and modify it.
- */
-public class IgniteRunner {
- // TODO: IGNITE-14413 Start of Ignite node should be supported by ignite-ctl tool
-}
diff --git a/modules/runner/src/main/java/org/apache/ignite/internal/app/IgnitionImpl.java b/modules/runner/src/main/java/org/apache/ignite/internal/app/IgnitionImpl.java
index 0631ce5..fbf8f37 100644
--- a/modules/runner/src/main/java/org/apache/ignite/internal/app/IgnitionImpl.java
+++ b/modules/runner/src/main/java/org/apache/ignite/internal/app/IgnitionImpl.java
@@ -50,6 +50,8 @@ import org.apache.ignite.network.MessageSerializationRegistryImpl;
import org.apache.ignite.network.scalecube.ScaleCubeClusterServiceFactory;
import org.apache.ignite.table.manager.IgniteTables;
import org.apache.ignite.utils.IgniteProperties;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
/**
* Implementation of an entry point for handling grid lifecycle.
@@ -79,12 +81,16 @@ public class IgnitionImpl implements Ignition {
private static final String VER_KEY = "version";
/** {@inheritDoc} */
- @Override public synchronized Ignite start(String jsonStrBootstrapCfg) {
+ @Override public synchronized Ignite start(@NotNull String nodeName, @Nullable String jsonStrBootstrapCfg) {
+ assert !StringUtil.isNullOrEmpty(nodeName) : "Node local name is empty";
+
ackBanner();
// Vault Component startup.
VaultManager vaultMgr = new VaultManager(new VaultServiceImpl());
+ vaultMgr.putName(nodeName).join();
+
boolean cfgBootstrappedFromPds = vaultMgr.bootstrapped();
List<RootKey<?, ?>> rootKeys = Arrays.asList(
@@ -117,15 +123,10 @@ public class IgnitionImpl implements Ignition {
var serializationRegistry = new MessageSerializationRegistryImpl();
- String localNodeName = locConfigurationMgr.configurationRegistry().getConfiguration(NodeConfiguration.KEY)
- .name().value();
-
- assert !StringUtil.isNullOrEmpty(localNodeName) : "Node local name is empty";
-
// Network startup.
ClusterService clusterNetSvc = new ScaleCubeClusterServiceFactory().createClusterService(
new ClusterLocalConfiguration(
- localNodeName,
+ nodeName,
netConfigurationView.port(),
Arrays.asList(netConfigurationView.netClusterNodes()),
serializationRegistry
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/TableManager.java b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/TableManager.java
index d4deb6d..4291047 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/TableManager.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/TableManager.java
@@ -205,7 +205,7 @@ public class TableManager extends Producer<TableEvent, TableEventParameters> imp
List<CompletableFuture<Boolean>> futs = new ArrayList<>();
- boolean hasMetastorageLocally = MetaStorageManager.hasMetastorageLocally(configurationMgr);
+ boolean hasMetastorageLocally = metaStorageMgr.hasMetastorageLocally(configurationMgr);
for (String tblName : tablesToStart) {
TableView tableView = ctx.newValue().get(tblName);
diff --git a/modules/table/src/test/java/org/apache/ignite/internal/table/TableManagerTest.java b/modules/table/src/test/java/org/apache/ignite/internal/table/TableManagerTest.java
index fc09474..24b6ea1 100644
--- a/modules/table/src/test/java/org/apache/ignite/internal/table/TableManagerTest.java
+++ b/modules/table/src/test/java/org/apache/ignite/internal/table/TableManagerTest.java
@@ -110,7 +110,6 @@ public class TableManagerTest {
cfrMgr.bootstrap("{\n" +
" \"node\":{\n" +
- " \"name\":\"node1\",\n" +
" \"metastorageNodes\":[\n" +
" \"" + NODE_NAME + "\"\n" +
" ]\n" +
@@ -285,6 +284,8 @@ public class TableManagerTest {
ClusterNode node,
CompletableFuture<UUID> tblIdFut
) {
+ when(mm.hasMetastorageLocally(any())).thenReturn(true);
+
when(mm.invoke((Condition)any(), (Operation)any(), (Operation)any())).thenAnswer(invokation -> {
Condition condition = (Condition)invokation.getArgument(0);
diff --git a/modules/vault/src/main/java/org/apache/ignite/internal/vault/VaultManager.java b/modules/vault/src/main/java/org/apache/ignite/internal/vault/VaultManager.java
index cbbc6f5..2686772 100644
--- a/modules/vault/src/main/java/org/apache/ignite/internal/vault/VaultManager.java
+++ b/modules/vault/src/main/java/org/apache/ignite/internal/vault/VaultManager.java
@@ -17,6 +17,7 @@
package org.apache.ignite.internal.vault;
+import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@@ -29,6 +30,7 @@ import org.apache.ignite.internal.vault.service.VaultService;
import org.apache.ignite.lang.ByteArray;
import org.apache.ignite.lang.IgniteInternalCheckedException;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
/**
* VaultManager is responsible for handling {@link VaultService} lifecycle
@@ -38,6 +40,9 @@ public class VaultManager {
/** Special key for vault where applied revision for {@code putAll} operation is stored. */
private static ByteArray APPLIED_REV = ByteArray.fromString("applied_revision");
+ /** Special key, which reserved for storing the name of the current node. */
+ private static final ByteArray NODE_NAME = ByteArray.fromString("node_name");
+
/** Mutex. */
private final Object mux = new Object();
@@ -172,6 +177,35 @@ public class VaultManager {
}
/**
+ * Persist node name to the vault.
+ *
+ * @param name Node name to persist. Couldn't be null.
+ * @return Future representing pending completion of the operation. Couldn't be {@code null}.
+ */
+ @NotNull public CompletableFuture<Void> putName(@NotNull String name) {
+ return put(NODE_NAME, name.getBytes(StandardCharsets.UTF_8));
+ }
+
+ /**
+ * @return Node name, if was stored earlier. Could be {@code null}.
+ * @throws IgniteInternalCheckedException If couldn't get node name from the vault.
+ */
+ @Nullable public String name() throws IgniteInternalCheckedException {
+ synchronized (mux) {
+ try {
+ byte[] nodeName = vaultService.get(NODE_NAME).get().value();
+ if (nodeName != null)
+ return new String(nodeName, StandardCharsets.UTF_8);
+ else
+ return null;
+ }
+ catch (InterruptedException | ExecutionException e) {
+ throw new IgniteInternalCheckedException("Error occurred when getting node name", e);
+ }
+ }
+ }
+
+ /**
* See {@link VaultService#watch(VaultWatch)}
*
* @param vaultWatch Watch which will notify for each update.