ID | IEP-81 | |||||
Author | ||||||
Sponsor | ||||||
Created |
| |||||
Status |
|
|
|
Table of Contents |
---|
The IEP is intended to eliminate all the current limitations with cluster management and provide additional features which may be available out of the boxsimplify, standardise, unifies development of Ignite management commands by providing declarative API for arguments and unified command invokers via various protocols - CLI, JMX, REST.
All of Ignite Cluster management operations are presented as running compute tasks over the cluster. Depending on the management operation required to be executed some of the tasks are running on a single Ignite node only or performing full compute operation overall cluster nodes with reducing the computation result on the originating node.
...
Without handlers and abstractions mentioned above, a new management task won't be available for a user even if it persists in the node classpath (it's still possible to run it using the ignite thin client). Most of such handlers and abstractions look like a boilerplate code and must be covered by some internal command exposer.
There are no any sufficient abstractions in any protocol and each protocol has (or has no if you lucky) slightly different logic.
Moreover, format of arguments, help messages and other things are not standardized and have different logic from command to command.
Command Plugin Extension
Ignite plugins have no control over the cluster management operations. The built-in management tasks can't be extended by Ignite running with custom plugins and even more, they can't be available through the standard Ignite's REST, JMX, CLI APIs.
Ignite CLI uses under the hood its own internal communication protocol so-called Binary Rest Protocol which enables CLI tools to communicate with the existing Ignite cluster and run some compute tasks, perform cache operation, as well as has listeners of topology changes. An instance of the GridClient started each time a new management operation executes the same way as an instance of IgniteClient can do which in turn is a part of the official Ignite Binary Protocol. Taking into account that the Binary Rest Protocol which is used for the CLI tool fully undocumented looks like
Ignite has some management tasks that don't obey the role model controlled by SecurityManager and has different execution flow depending on which execution context is set. For instance:
All of the issues above require management tasks to be always being executed in the same manner with the same security context.
The following design issues bases on current management task implementation are present:
The following new features can be available out of the box with minimal additional source code changes:
The ComputeTask is a common way for building various cluster management tasks and execution via an Ignite thin client.
...
This IEP is primary focused on providing good abstraction for command invocation which includes:
Keeping in mind that command will be described in declarative way all newly created commands will be automatically available and used by all of the features above.
Flow of command execution:
The following design principles are proposed:
./control.sh --system-view ...
./control.sh --baseline-add ...
...
Management commands are always wrapped with the ProxyManagementTask. The management command may be executed on a single cluster node only or broadcasted to all nodes with reducing the execution results.
Code Block | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
/** */ public interface IgniteCommand<T> extends IgniteCallable<T>, IgniteReducer<T, T> { /** {@inheritDoc} */ @Override public default boolean collect(@Nullable T t)/ A - argument type. // R - result type. // T - task type. Task implements actual command logic. public interface Command<A extends IgniteDataTransferObject, R, T extends ComputeTask<VisorTaskArgument<A>, R>> { public String description(); return true; public Class<A> args(); public Class<T> }task(); /** {@inheritDoc} */ @Override public default T reduce() {public void printResult(IgniteDataTransferObject arg, Object res, Consumer<String> printer); boolean experimental(); boolean confirmable(); return null; }Collection<UUID> nodes(Collection<UUID> nodes, A arg); } |
Code Block | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
/** */ @Command(name@OneOf(value = {"addnodeIds", "nodeId", commandDescription"allNodes"}, optional = "Add nodes to baseline topology."true) public class BaselineAddCommandSystemViewCommandArg implementsextends IgniteCallable<String>IgniteDataTransferObject { /** Auto-injected Ignite instance. */@Positional @IgniteInstanceResource @Argument(description = "Name of privatethe IgniteEx ignite; /** Parameter willsystem view which content should be injected on command instantiation. Default comma separation. */ @Parameter(names = {"--nodes", "-n"}, description = "List of baseline nodes to add.")printed." + " Both \"SQL\" and \"Java\" styles of system view name are supported" + private List<String> consistentIds; " /** {@inheritDoc} */ @Override public String call() throws Exception {(e.g. SQL_TABLES and sql.tables will be handled similarly)") private String systemViewName; Collection<BaselineNode> baseline = ignite.cluster().currentBaselineTopology();@Argument( Collection<ClusterNode>description srvs= = ignite.cluster().forServers().nodes(); for (String consistentId : consistentIds) { "ID of the node to get the system view from (deprecated. Use --node-ids instead). If not set, random node will be chosen", ClusterNode node = F.find(srvs, null, new IgnitePredicate<ClusterNode>() { optional = true ) private UUID nodeId; @Override public boolean apply(ClusterNode node) {@Argument( description = "Comma-separated list of nodes IDs to get the system return node.consistentId().toString().equals(consistentId); view from. If not set, random node will be chosen", } optional = true ) private UUID[] })nodeIds; if (node == null)@Argument( description = "Get the system view from all thrownodes. new IllegalArgumentException("Node not found for consistent ID: " + consistentId); If not set, random node will be chosen", optional baseline.add(node);= true }) private ignite.cluster().setBaselineTopology(baseline);boolean allNodes; // The rest of returnthe consistentIdscode.toString(); } } |
Phase-3
...
// Links to discussions on the devlist, if applicable.
...