You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by tl...@apache.org on 2020/09/23 07:23:32 UTC

[ignite] branch master updated: IGNITE-13186 Commands for control.sh to manage properties at the distributed metastore (#8208)

This is an automated email from the ASF dual-hosted git repository.

tledkov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new 0f208ca  IGNITE-13186 Commands for control.sh to manage properties at the distributed metastore (#8208)
0f208ca is described below

commit 0f208caf21247866117c33d1f085b7eb542c497a
Author: tledkov <tl...@gridgain.com>
AuthorDate: Wed Sep 23 10:23:10 2020 +0300

    IGNITE-13186 Commands for control.sh to manage properties at the distributed metastore
    (#8208)
---
 .../ignite/internal/commandline/CommandList.java   |   6 +-
 .../commandline/property/PropertyCommand.java      | 100 +++++++++++++++
 .../property/PropertySubCommandsList.java          |  73 +++++++++++
 .../subcommands/PropertyAbstractSubCommand.java    | 105 ++++++++++++++++
 .../property/subcommands/PropertyGetCommand.java   |  63 ++++++++++
 .../property/subcommands/PropertyHelpCommand.java  |  49 ++++++++
 .../property/subcommands/PropertyListCommand.java  |  50 ++++++++
 .../property/subcommands/PropertySetCommand.java   |  72 +++++++++++
 .../commandline/CommandHandlerParsingTest.java     |   3 +-
 .../testsuites/IgniteControlUtilityTestSuite.java  |   3 +
 .../util/GridCommandHandlerClusterByClassTest.java |   2 +-
 .../util/GridCommandHandlerPropertiesTest.java     | 138 +++++++++++++++++++++
 .../ignite/internal/cluster/IgniteClusterImpl.java |   9 +-
 .../commandline/property/PropertyArgs.java         | 117 +++++++++++++++++
 .../property/tasks/PropertiesListResult.java       |  73 +++++++++++
 .../property/tasks/PropertiesListTask.java         |  84 +++++++++++++
 .../property/tasks/PropertyOperationResult.java    |  71 +++++++++++
 .../commandline/property/tasks/PropertyTask.java   | 111 +++++++++++++++++
 .../distributed/DistributedBooleanProperty.java    |   3 +-
 .../distributed/DistributedChangeableProperty.java |   6 +
 .../distributed/DistributedComparableProperty.java |   6 +-
 .../DistributedConfigurationProcessor.java         |  25 ++++
 .../distributed/DistributedEnumProperty.java       |  46 ++++---
 .../distributed/DistributedLongProperty.java       |   3 +-
 .../distributed/SimpleDistributedProperty.java     |  69 ++++++++++-
 .../DistributedTracingConfiguration.java           |   8 +-
 .../ignite/plugin/security/SecurityPermission.java |   8 +-
 .../main/resources/META-INF/classnames.properties  |   5 +
 ...ridCommandHandlerClusterByClassTest_help.output |  12 ++
 ...andHandlerClusterByClassWithSSLTest_help.output |  12 ++
 .../query/h2/DistributedSqlConfiguration.java      |  12 +-
 31 files changed, 1301 insertions(+), 43 deletions(-)

diff --git a/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/CommandList.java b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/CommandList.java
index 4190604..b6a221b 100644
--- a/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/CommandList.java
+++ b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/CommandList.java
@@ -21,6 +21,7 @@ import org.apache.ignite.internal.commandline.cache.CacheCommands;
 import org.apache.ignite.internal.commandline.diagnostic.DiagnosticCommand;
 import org.apache.ignite.internal.commandline.encryption.EncryptionCommand;
 import org.apache.ignite.internal.commandline.meta.MetadataCommand;
+import org.apache.ignite.internal.commandline.property.PropertyCommand;
 import org.apache.ignite.internal.commandline.query.KillCommand;
 import org.apache.ignite.internal.commandline.snapshot.SnapshotCommand;
 
@@ -77,7 +78,10 @@ public enum CommandList {
     TRACING_CONFIGURATION("--tracing-configuration", new TracingConfigurationCommand()),
 
     /** Warm-up command. */
-    WARM_UP("--warm-up", new WarmUpCommand());
+    WARM_UP("--warm-up", new WarmUpCommand()),
+
+    /** Commands to manage distributed properties. */
+    PROPERTY("--property", new PropertyCommand());
 
     /** Private values copy so there's no need in cloning it every time. */
     private static final CommandList[] VALUES = CommandList.values();
diff --git a/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/property/PropertyCommand.java b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/property/PropertyCommand.java
new file mode 100644
index 0000000..bee355f
--- /dev/null
+++ b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/property/PropertyCommand.java
@@ -0,0 +1,100 @@
+/*
+ * 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.internal.commandline.property;
+
+import java.util.logging.Logger;
+import org.apache.ignite.internal.client.GridClientConfiguration;
+import org.apache.ignite.internal.commandline.Command;
+import org.apache.ignite.internal.commandline.CommandArgIterator;
+import org.apache.ignite.internal.processors.configuration.distributed.DistributedChangeableProperty;
+
+import static org.apache.ignite.internal.commandline.Command.usage;
+import static org.apache.ignite.internal.commandline.CommandList.PROPERTY;
+import static org.apache.ignite.internal.commandline.property.PropertySubCommandsList.GET;
+import static org.apache.ignite.internal.commandline.property.PropertySubCommandsList.HELP;
+import static org.apache.ignite.internal.commandline.property.PropertySubCommandsList.LIST;
+import static org.apache.ignite.internal.commandline.property.PropertySubCommandsList.SET;
+
+/**
+ * Command to manage distributed properties (see {@link DistributedChangeableProperty})
+ */
+public class PropertyCommand implements Command<Object> {
+    /**
+     *
+     */
+    private Command<?> delegate;
+
+    /** {@inheritDoc} */
+    @Override public void printUsage(Logger log) {
+        usage(log, "Print property command help:",
+            PROPERTY,
+            HELP.toString()
+        );
+
+        usage(log, "Print list of available properties:",
+            PROPERTY,
+            LIST.toString()
+        );
+
+        usage(log, "Get the property value",
+            PROPERTY,
+            GET.toString(),
+            PropertyArgs.NAME,
+            "<property_name>");
+
+        usage(log, "Set the property value",
+            PROPERTY,
+            SET.toString(),
+            PropertyArgs.NAME,
+            "<property_name>",
+            PropertyArgs.VAL,
+            "<property_value>");
+    }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return PROPERTY.toCommandName();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void parseArguments(CommandArgIterator argIter) {
+        PropertySubCommandsList subcommand = PropertySubCommandsList.parse(argIter.nextArg("Expected property action."));
+
+        if (subcommand == null)
+            throw new IllegalArgumentException("Expected correct property action.");
+
+        delegate = subcommand.command();
+
+        delegate.parseArguments(argIter);
+    }
+
+    /** {@inheritDoc} */
+    @Override public String confirmationPrompt() {
+        return delegate != null ? delegate.confirmationPrompt() : null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object execute(GridClientConfiguration clientCfg, Logger log) throws Exception {
+        return delegate.execute(clientCfg, log);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object arg() {
+        return delegate.arg();
+    }
+}
diff --git a/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/property/PropertySubCommandsList.java b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/property/PropertySubCommandsList.java
new file mode 100644
index 0000000..c24ec07
--- /dev/null
+++ b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/property/PropertySubCommandsList.java
@@ -0,0 +1,73 @@
+/*
+ * 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.internal.commandline.property;
+
+import org.apache.ignite.internal.commandline.Command;
+import org.apache.ignite.internal.commandline.property.subcommands.PropertyGetCommand;
+import org.apache.ignite.internal.commandline.property.subcommands.PropertyHelpCommand;
+import org.apache.ignite.internal.commandline.property.subcommands.PropertyListCommand;
+import org.apache.ignite.internal.commandline.property.subcommands.PropertySetCommand;
+
+/** */
+public enum PropertySubCommandsList {
+    /** */
+    HELP("help", new PropertyHelpCommand()),
+    /** */
+    LIST("list", new PropertyListCommand()),
+    /** */
+    GET("get", new PropertyGetCommand()),
+    /** */
+    SET("set", new PropertySetCommand());
+
+    /** */
+    private final String name;
+
+    /** */
+    private final Command<?> cmd;
+
+    /** */
+    PropertySubCommandsList(String name, Command<?> cmd) {
+        this.name = name;
+        this.cmd = cmd;
+    }
+
+    /** */
+    public String text() {
+        return name;
+    }
+
+    /** */
+    public Command<?> command() {
+        return cmd;
+    }
+
+    /** */
+    public static PropertySubCommandsList parse(String name) {
+        for (PropertySubCommandsList cmd : values()) {
+            if (cmd.name.equalsIgnoreCase(name))
+                return cmd;
+        }
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return name;
+    }
+}
diff --git a/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/property/subcommands/PropertyAbstractSubCommand.java b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/property/subcommands/PropertyAbstractSubCommand.java
new file mode 100644
index 0000000..251ae21
--- /dev/null
+++ b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/property/subcommands/PropertyAbstractSubCommand.java
@@ -0,0 +1,105 @@
+/*
+ * 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.internal.commandline.property.subcommands;
+
+import java.util.Collection;
+import java.util.logging.Logger;
+import org.apache.ignite.internal.client.GridClient;
+import org.apache.ignite.internal.client.GridClientCompute;
+import org.apache.ignite.internal.client.GridClientConfiguration;
+import org.apache.ignite.internal.client.GridClientDisconnectedException;
+import org.apache.ignite.internal.client.GridClientNode;
+import org.apache.ignite.internal.commandline.Command;
+import org.apache.ignite.internal.commandline.CommandArgIterator;
+import org.apache.ignite.internal.commandline.CommandLogger;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.visor.VisorTaskArgument;
+
+/** */
+public abstract class PropertyAbstractSubCommand<
+    MetadataArgsDto extends IgniteDataTransferObject,
+    MetadataResultDto extends IgniteDataTransferObject>
+    implements Command<MetadataArgsDto> {
+    /** */
+    private MetadataArgsDto args;
+
+    /** {@inheritDoc} */
+    @Override public final void printUsage(Logger log) {
+        throw new UnsupportedOperationException("printUsage");
+    }
+
+    /** {@inheritDoc} */
+    @Override public final void parseArguments(CommandArgIterator argIter) {
+        args = parseArguments0(argIter);
+    }
+
+    /** {@inheritDoc} */
+    @Override public final Object execute(GridClientConfiguration clientCfg, Logger log) throws Exception {
+        try (GridClient client = Command.startClient(clientCfg)) {
+            GridClientCompute compute = client.compute();
+
+            // Try to find connectable server nodes.
+            Collection<GridClientNode> nodes = compute.nodes((n) -> n.connectable() && !n.isClient());
+
+            if (F.isEmpty(nodes)) {
+                nodes = compute.nodes(GridClientNode::connectable);
+
+                if (F.isEmpty(nodes))
+                    throw new GridClientDisconnectedException("Connectable nodes not found", null);
+            }
+
+            GridClientNode node = nodes.stream()
+                .findAny().orElse(null);
+
+            if (node == null)
+                node = compute.balancer().balancedNode(nodes);
+
+            MetadataResultDto res = compute.projection(node).execute(
+                taskName(),
+                new VisorTaskArgument<>(node.nodeId(), arg(), false)
+            );
+
+            printResult(res, log);
+        }
+        catch (Throwable e) {
+            log.severe("Failed to execute metadata command='" + name() + "'");
+            log.severe(CommandLogger.errorMessage(e));
+
+            throw e;
+        }
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public final MetadataArgsDto arg() {
+        return args;
+    }
+
+    /** */
+    protected abstract String taskName();
+
+    /** */
+    protected MetadataArgsDto parseArguments0(CommandArgIterator argIter) {
+        return null;
+    }
+
+    /** */
+    protected abstract void printResult(MetadataResultDto res, Logger log);
+}
diff --git a/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/property/subcommands/PropertyGetCommand.java b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/property/subcommands/PropertyGetCommand.java
new file mode 100644
index 0000000..1390b89
--- /dev/null
+++ b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/property/subcommands/PropertyGetCommand.java
@@ -0,0 +1,63 @@
+/*
+ * 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.internal.commandline.property.subcommands;
+
+import java.util.logging.Logger;
+import org.apache.ignite.internal.commandline.CommandArgIterator;
+import org.apache.ignite.internal.commandline.property.PropertyArgs;
+import org.apache.ignite.internal.commandline.property.PropertySubCommandsList;
+import org.apache.ignite.internal.commandline.property.tasks.PropertyOperationResult;
+import org.apache.ignite.internal.commandline.property.tasks.PropertyTask;
+
+/** */
+public class PropertyGetCommand extends PropertyAbstractSubCommand<PropertyArgs, PropertyOperationResult>
+{
+    /** {@inheritDoc} */
+    @Override protected String taskName() {
+        return PropertyTask.class.getName();
+    }
+
+    /** {@inheritDoc} */
+    @Override public PropertyArgs parseArguments0(CommandArgIterator argIter) {
+        String name = null;
+
+        while (argIter.hasNextSubArg() && name == null) {
+            String optName = argIter.nextArg("Expecting " + PropertyArgs.NAME);
+
+            if (PropertyArgs.NAME.equals(optName))
+                name = argIter.nextArg("property name");
+        }
+
+        if (name == null) {
+            throw new IllegalArgumentException("Property name is not specified. " +
+                "Please use the option: --name <property_name>");
+        }
+
+        return new PropertyArgs(name, null, PropertyArgs.Action.GET);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void printResult(PropertyOperationResult res, Logger log) {
+        log.info(arg().name() + " = " + res.value());
+    }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return PropertySubCommandsList.GET.text();
+    }
+}
diff --git a/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/property/subcommands/PropertyHelpCommand.java b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/property/subcommands/PropertyHelpCommand.java
new file mode 100644
index 0000000..61f3080
--- /dev/null
+++ b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/property/subcommands/PropertyHelpCommand.java
@@ -0,0 +1,49 @@
+/*
+ * 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.internal.commandline.property.subcommands;
+
+import java.util.logging.Logger;
+import org.apache.ignite.internal.client.GridClientConfiguration;
+import org.apache.ignite.internal.commandline.Command;
+import org.apache.ignite.internal.commandline.meta.MetadataCommand;
+import org.apache.ignite.internal.commandline.meta.MetadataSubCommandsList;
+
+/** */
+public class PropertyHelpCommand implements Command<Void> {
+    /** {@inheritDoc} */
+    @Override public void printUsage(Logger log) {
+        throw new UnsupportedOperationException("printUsage");
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object execute(GridClientConfiguration clientCfg, Logger log) throws Exception {
+        new MetadataCommand().printUsage(log);
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Void arg() {
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return MetadataSubCommandsList.HELP.text();
+    }
+}
diff --git a/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/property/subcommands/PropertyListCommand.java b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/property/subcommands/PropertyListCommand.java
new file mode 100644
index 0000000..c63f32a
--- /dev/null
+++ b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/property/subcommands/PropertyListCommand.java
@@ -0,0 +1,50 @@
+/*
+ * 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.internal.commandline.property.subcommands;
+
+import java.util.logging.Logger;
+import org.apache.ignite.internal.commandline.CommandArgIterator;
+import org.apache.ignite.internal.commandline.meta.subcommands.VoidDto;
+import org.apache.ignite.internal.commandline.property.PropertySubCommandsList;
+import org.apache.ignite.internal.commandline.property.tasks.PropertiesListResult;
+import org.apache.ignite.internal.commandline.property.tasks.PropertiesListTask;
+
+/** */
+public class PropertyListCommand extends PropertyAbstractSubCommand<VoidDto, PropertiesListResult>
+{
+    /** {@inheritDoc} */
+    @Override protected String taskName() {
+        return PropertiesListTask.class.getName();
+    }
+
+    /** {@inheritDoc} */
+    @Override public VoidDto parseArguments0(CommandArgIterator argIter) {
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void printResult(PropertiesListResult res, Logger log) {
+        for (String prop : res.properties())
+            log.info(prop);
+    }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return PropertySubCommandsList.LIST.text();
+    }
+}
diff --git a/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/property/subcommands/PropertySetCommand.java b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/property/subcommands/PropertySetCommand.java
new file mode 100644
index 0000000..bb0ee3a
--- /dev/null
+++ b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/property/subcommands/PropertySetCommand.java
@@ -0,0 +1,72 @@
+/*
+ * 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.internal.commandline.property.subcommands;
+
+import java.util.logging.Logger;
+import org.apache.ignite.internal.commandline.CommandArgIterator;
+import org.apache.ignite.internal.commandline.property.PropertyArgs;
+import org.apache.ignite.internal.commandline.property.PropertySubCommandsList;
+import org.apache.ignite.internal.commandline.property.tasks.PropertyOperationResult;
+import org.apache.ignite.internal.commandline.property.tasks.PropertyTask;
+
+/** */
+public class PropertySetCommand extends PropertyAbstractSubCommand<PropertyArgs, PropertyOperationResult>
+{
+    /** {@inheritDoc} */
+    @Override protected String taskName() {
+        return PropertyTask.class.getName();
+    }
+
+    /** {@inheritDoc} */
+    @Override public PropertyArgs parseArguments0(CommandArgIterator argIter) {
+        String name = null;
+        String val = null;
+
+        while (argIter.hasNextSubArg() && (name == null || val == null)) {
+            String optName = argIter.nextArg("Expecting " + (name == null ? PropertyArgs.NAME : PropertyArgs.VAL));
+
+            if (PropertyArgs.NAME.equals(optName))
+                name = argIter.nextArg("property name");
+
+            if (PropertyArgs.VAL.equals(optName))
+                val = argIter.nextArg("property value");
+        }
+
+        if (name == null) {
+            throw new IllegalArgumentException("Property name is not specified. " +
+                "Please the option: --name <property_name>");
+        }
+
+        if (val == null) {
+            throw new IllegalArgumentException("Property name is not specified. " +
+                "Please the option: --name <property_name>");
+        }
+
+        return new PropertyArgs(name, val, PropertyArgs.Action.SET);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void printResult(PropertyOperationResult res, Logger log) {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return PropertySubCommandsList.SET.text();
+    }
+}
diff --git a/modules/control-utility/src/test/java/org/apache/ignite/internal/commandline/CommandHandlerParsingTest.java b/modules/control-utility/src/test/java/org/apache/ignite/internal/commandline/CommandHandlerParsingTest.java
index 1066ca7..2dade20 100644
--- a/modules/control-utility/src/test/java/org/apache/ignite/internal/commandline/CommandHandlerParsingTest.java
+++ b/modules/control-utility/src/test/java/org/apache/ignite/internal/commandline/CommandHandlerParsingTest.java
@@ -1030,6 +1030,7 @@ public class CommandHandlerParsingTest {
             cmd == CommandList.SNAPSHOT ||
             cmd == CommandList.CLUSTER_CHANGE_TAG ||
             cmd == CommandList.METADATA ||
-            cmd == CommandList.WARM_UP;
+            cmd == CommandList.WARM_UP ||
+            cmd == CommandList.PROPERTY;
     }
 }
diff --git a/modules/control-utility/src/test/java/org/apache/ignite/testsuites/IgniteControlUtilityTestSuite.java b/modules/control-utility/src/test/java/org/apache/ignite/testsuites/IgniteControlUtilityTestSuite.java
index e21f474..f4e8df4 100644
--- a/modules/control-utility/src/test/java/org/apache/ignite/testsuites/IgniteControlUtilityTestSuite.java
+++ b/modules/control-utility/src/test/java/org/apache/ignite/testsuites/IgniteControlUtilityTestSuite.java
@@ -34,6 +34,7 @@ import org.apache.ignite.util.GridCommandHandlerIndexingClusterByClassWithSSLTes
 import org.apache.ignite.util.GridCommandHandlerIndexingTest;
 import org.apache.ignite.util.GridCommandHandlerIndexingWithSSLTest;
 import org.apache.ignite.util.GridCommandHandlerMetadataTest;
+import org.apache.ignite.util.GridCommandHandlerPropertiesTest;
 import org.apache.ignite.util.GridCommandHandlerSslTest;
 import org.apache.ignite.util.GridCommandHandlerTest;
 import org.apache.ignite.util.GridCommandHandlerTracingConfigurationTest;
@@ -76,6 +77,8 @@ import org.junit.runners.Suite;
     GridCommandHandlerIndexRebuildStatusTest.class,
 
     GridCommandHandlerTracingConfigurationTest.class,
+
+    GridCommandHandlerPropertiesTest.class,
 })
 public class IgniteControlUtilityTestSuite {
 }
diff --git a/modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerClusterByClassTest.java b/modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerClusterByClassTest.java
index 2d854af..4403e38 100644
--- a/modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerClusterByClassTest.java
+++ b/modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerClusterByClassTest.java
@@ -128,7 +128,7 @@ public class GridCommandHandlerClusterByClassTest extends GridCommandHandlerClus
     protected static final String ERROR_STACK_TRACE_PREFIX = "Error stack trace:";
 
     /**
-     * Very basic tests for running the command in different enviroment which other command are running in.
+     * Very basic tests for running the command in different environment which other command are running in.
      */
     @Test
     public void testFindAndDeleteGarbage() {
diff --git a/modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerPropertiesTest.java b/modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerPropertiesTest.java
new file mode 100644
index 0000000..111b5c0
--- /dev/null
+++ b/modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerPropertiesTest.java
@@ -0,0 +1,138 @@
+/*
+ * 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.util;
+
+import java.io.Serializable;
+import java.util.Set;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.processors.configuration.distributed.DistributedChangeableProperty;
+import org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing;
+import org.apache.ignite.internal.util.typedef.G;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.apache.ignite.internal.commandline.CommandHandler.EXIT_CODE_INVALID_ARGUMENTS;
+import static org.apache.ignite.internal.commandline.CommandHandler.EXIT_CODE_OK;
+import static org.apache.ignite.testframework.GridTestUtils.assertContains;
+
+/**
+ * Checks command line property commands.
+ */
+public class GridCommandHandlerPropertiesTest extends GridCommandHandlerClusterByClassAbstractTest {
+    /** */
+    @Before
+    public void init() {
+        injectTestSystemOut();
+    }
+
+    /** */
+    @After
+    public void clear() {
+    }
+
+    /**
+     * Check the command '--property list'.
+     * Steps:
+     */
+    @Test
+    public void testList() {
+        assertEquals(EXIT_CODE_OK, execute("--property", "list"));
+
+        String out = testOut.toString();
+
+        for (DistributedChangeableProperty<Serializable> pd : crd.context()
+            .distributedConfiguration().properties())
+            assertContains(log, out, pd.getName());
+    }
+
+    /**
+     * Check the command '--property get'.
+     * Steps:
+     */
+    @Test
+    public void testGet() {
+        for (DistributedChangeableProperty<Serializable> pd : crd.context()
+            .distributedConfiguration().properties()) {
+            assertEquals(EXIT_CODE_OK, execute("--property", "get", "--name", pd.getName()));
+            String out = testOut.toString();
+
+            assertContains(log, out, pd.getName() + " = " + pd.get());
+        }
+    }
+
+    /**
+     * Check the set command fro property 'sql.disabledFunctions'.
+     * Steps:
+     */
+    @Test
+    public void testPropertyDisabledSqlFunctions() {
+        assertEquals(
+            EXIT_CODE_OK,
+            execute(
+                "--property", "set",
+                "--name", "sql.disabledFunctions",
+                "--val", "LENGTH, SESSION_ID"
+            )
+        );
+
+        for (Ignite ign : G.allGrids()) {
+            Set<String> disabledFuncs = ((IgniteH2Indexing)((IgniteEx)ign).context().query().getIndexing())
+                .distributedConfiguration().disabledFunctions();
+
+            assertEquals(2, disabledFuncs.size());
+
+            assertTrue(disabledFuncs.contains("LENGTH"));
+            assertTrue(disabledFuncs.contains("SESSION_ID"));
+        }
+    }
+
+    /**
+     * Check the set command fro property 'sql.defaultQueryTimeout'.
+     * Steps:
+     */
+    @Test
+    public void testPropertyDefaultQueryTimeout() {
+        int dfltVal = ((IgniteH2Indexing)crd.context().query().getIndexing())
+            .distributedConfiguration().defaultQueryTimeout();
+
+        int newVal = dfltVal + 1000;
+
+        assertEquals(EXIT_CODE_OK, execute("--property", "set", "--name", "sql.defaultQueryTimeout", "--val",
+            Integer.toString(newVal)));
+
+        for (Ignite ign : G.allGrids()) {
+            assertEquals(
+                "Invalid default query timeout on node: " + ign.name(),
+                newVal,
+                ((IgniteH2Indexing)((IgniteEx)ign).context().query().getIndexing())
+                    .distributedConfiguration().defaultQueryTimeout()
+            );
+        }
+
+        assertEquals(
+            EXIT_CODE_INVALID_ARGUMENTS,
+            execute(
+                "--property", "set",
+                "--name", "sql.defaultQueryTimeout",
+                "--val", "invalidVal"
+            )
+        );
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/cluster/IgniteClusterImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/cluster/IgniteClusterImpl.java
index df1ad33..6ee7da9 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/cluster/IgniteClusterImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/cluster/IgniteClusterImpl.java
@@ -116,12 +116,9 @@ public class IgniteClusterImpl extends ClusterGroupAdapter implements IgniteClus
     /** Property for update policy of shutdown. */
     private DistributedEnumProperty<ShutdownPolicy> shutdown = new DistributedEnumProperty<>(
         "shutdown.policy",
-        (ordinal) -> {
-            return ordinal == null ? null : ShutdownPolicy.fromOrdinal(ordinal);
-        },
-        (policy) -> {
-            return policy == null ? null : policy.index();
-        }
+        (ordinal) -> ordinal == null ? null : ShutdownPolicy.fromOrdinal(ordinal),
+        (policy) -> policy == null ? null : policy.index(),
+        ShutdownPolicy.class
     );
 
     /**
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/property/PropertyArgs.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/property/PropertyArgs.java
new file mode 100644
index 0000000..d998369
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/property/PropertyArgs.java
@@ -0,0 +1,117 @@
+/*
+ * 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.internal.commandline.property;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.jetbrains.annotations.Nullable;
+
+/** */
+public class PropertyArgs extends IgniteDataTransferObject {
+    /** Serial version uid. */
+    private static final long serialVersionUID = 0L;
+
+    /** Property name argument name. */
+    public static final String NAME = "--name";
+
+    /** Type value argument name . */
+    public static final String VAL = "--val";
+
+    /** Property name . */
+    private String name;
+
+    /** Property's value. */
+    private String val;
+
+    /** Action. */
+    private Action action;
+
+    /**
+     * Default constructor.
+     */
+    public PropertyArgs() {
+        // No-op.
+    }
+
+    /** */
+    public PropertyArgs(String name, String val, Action action) {
+        assert name != null;
+
+        this.name = name;
+        this.val = val;
+        this.action = action;
+    }
+
+    /** */
+    public String name() {
+        return name;
+    }
+
+    /** */
+    public String value() {
+        return val;
+    }
+
+    /** */
+    public Action action() {
+        return action;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void writeExternalData(ObjectOutput out) throws IOException {
+        U.writeString(out, name);
+        U.writeString(out, val);
+        out.writeByte(action.ordinal());
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void readExternalData(byte protoVer, ObjectInput in) throws IOException, ClassNotFoundException {
+        name = U.readString(in);
+        val = U.readString(in);
+        action = Action.fromOrdinal(in.readByte());
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return name + "=" + val;
+    }
+
+    /**
+     *
+     */
+    public enum Action {
+        /** */
+        GET,
+
+        /** */
+        SET;
+
+        /** Enumerated values. */
+        private static final Action[] VALS = values();
+
+        /**
+         * Efficiently gets enumerated value from its ordinal.
+         */
+        @Nullable public static Action fromOrdinal(int ord) {
+            return ord >= 0 && ord < VALS.length ? VALS[ord] : null;
+        }
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/property/tasks/PropertiesListResult.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/property/tasks/PropertiesListResult.java
new file mode 100644
index 0000000..7c35077
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/property/tasks/PropertiesListResult.java
@@ -0,0 +1,73 @@
+/*
+ * 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.internal.commandline.property.tasks;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.Collection;
+import java.util.Collections;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+import org.apache.ignite.internal.processors.task.GridInternal;
+import org.apache.ignite.internal.util.typedef.internal.U;
+
+/**
+ * List of the distributed properties names.
+ */
+@GridInternal
+public class PropertiesListResult extends IgniteDataTransferObject {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** Properties names. */
+    private Collection<String> props = Collections.emptyList();
+
+    /**
+     * Constructor for optimized marshaller.
+     */
+    public PropertiesListResult() {
+        // No-op.
+    }
+
+    /**
+     * @param props Properties.
+     */
+    public PropertiesListResult(Collection<String> props) {
+        this.props = props;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void writeExternalData(ObjectOutput out) throws IOException {
+        U.writeCollection(out, props);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void readExternalData(
+        byte protoVer,
+        ObjectInput in
+    ) throws IOException, ClassNotFoundException {
+        props = U.readCollection(in);
+    }
+
+    /**
+     * @return Properties (name, description) collection.
+     */
+    public Collection<String> properties() {
+        return props;
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/property/tasks/PropertiesListTask.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/property/tasks/PropertiesListTask.java
new file mode 100644
index 0000000..a23f734
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/property/tasks/PropertiesListTask.java
@@ -0,0 +1,84 @@
+/*
+ * 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.internal.commandline.property.tasks;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.compute.ComputeJobResult;
+import org.apache.ignite.internal.commandline.meta.subcommands.VoidDto;
+import org.apache.ignite.internal.processors.task.GridInternal;
+import org.apache.ignite.internal.visor.VisorJob;
+import org.apache.ignite.internal.visor.VisorMultiNodeTask;
+import org.jetbrains.annotations.Nullable;
+
+import static org.apache.ignite.plugin.security.SecurityPermission.ADMIN_READ_DISTRIBUTED_PROPERTY;
+
+/**
+ * Task for property operations.
+ */
+@GridInternal
+public class PropertiesListTask extends VisorMultiNodeTask<VoidDto, PropertiesListResult, PropertiesListResult> {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** {@inheritDoc} */
+    @Override protected VisorJob<VoidDto, PropertiesListResult> job(VoidDto arg) {
+        return new PropertiesListJob(debug);
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override protected PropertiesListResult reduce0(List<ComputeJobResult> results) {
+        if (results.isEmpty())
+            throw new IgniteException("Empty job results");
+
+        if (results.size() > 1)
+            throw new IgniteException("Invalid job results: " + results);
+
+        if (results.get(0).getException() != null)
+            throw results.get(0).getException();
+        else
+            return results.get(0).getData();
+    }
+
+    /**
+     * Job for property operations (get/set).
+     */
+    private static class PropertiesListJob extends VisorJob<VoidDto, PropertiesListResult> {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /**
+         * @param debug Debug.
+         */
+        protected PropertiesListJob(boolean debug) {
+            super(null, debug);
+        }
+
+        /** {@inheritDoc} */
+        @Override protected PropertiesListResult run(@Nullable VoidDto arg) {
+            ignite.context().security().authorize(ADMIN_READ_DISTRIBUTED_PROPERTY);
+
+            return new PropertiesListResult(
+                ignite.context().distributedConfiguration().properties().stream()
+                    .map(pd -> pd.getName())
+                    .collect(Collectors.toList())
+            );
+        }
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/property/tasks/PropertyOperationResult.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/property/tasks/PropertyOperationResult.java
new file mode 100644
index 0000000..9f5a899
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/property/tasks/PropertyOperationResult.java
@@ -0,0 +1,71 @@
+/*
+ * 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.internal.commandline.property.tasks;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+import org.apache.ignite.internal.processors.task.GridInternal;
+import org.apache.ignite.internal.util.typedef.internal.U;
+
+/**
+ * Result of an operation with property.
+ */
+@GridInternal
+public class PropertyOperationResult extends IgniteDataTransferObject {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** Property value. */
+    private String val;
+
+    /**
+     * Constructor for optimized marshaller.
+     */
+    public PropertyOperationResult() {
+        // No-op.
+    }
+
+    /**
+     * @param val Value.
+     */
+    public PropertyOperationResult(String val) {
+        this.val = val;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void writeExternalData(ObjectOutput out) throws IOException {
+        U.writeString(out, val);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void readExternalData(
+        byte protoVer,
+        ObjectInput in
+    ) throws IOException, ClassNotFoundException {
+        val = U.readString(in);
+    }
+
+    /**
+     * @return Property value.
+     */
+    public String value() {
+        return val;
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/property/tasks/PropertyTask.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/property/tasks/PropertyTask.java
new file mode 100644
index 0000000..aa2ade7
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/property/tasks/PropertyTask.java
@@ -0,0 +1,111 @@
+/*
+ * 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.internal.commandline.property.tasks;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Objects;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.compute.ComputeJobResult;
+import org.apache.ignite.internal.commandline.property.PropertyArgs;
+import org.apache.ignite.internal.processors.configuration.distributed.DistributedChangeableProperty;
+import org.apache.ignite.internal.processors.task.GridInternal;
+import org.apache.ignite.internal.visor.VisorJob;
+import org.apache.ignite.internal.visor.VisorMultiNodeTask;
+import org.jetbrains.annotations.Nullable;
+
+import static org.apache.ignite.plugin.security.SecurityPermission.ADMIN_READ_DISTRIBUTED_PROPERTY;
+import static org.apache.ignite.plugin.security.SecurityPermission.ADMIN_WRITE_DISTRIBUTED_PROPERTY;
+
+/**
+ * Task for property operations.
+ */
+@GridInternal
+public class PropertyTask extends VisorMultiNodeTask<PropertyArgs, PropertyOperationResult, PropertyOperationResult> {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** {@inheritDoc} */
+    @Override protected VisorJob<PropertyArgs, PropertyOperationResult> job(PropertyArgs arg) {
+        return new PropertyJob(arg, debug);
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override protected PropertyOperationResult reduce0(List<ComputeJobResult> results) {
+        if (results.isEmpty())
+            throw new IgniteException("Empty job results");
+
+        if (results.size() > 1)
+            throw new IgniteException("Invalid job results: " + results);
+
+        if (results.get(0).getException() != null)
+            throw results.get(0).getException();
+        else
+            return results.get(0).getData();
+    }
+
+    /**
+     * Job for getting binary metadata.
+     */
+    private static class PropertyJob extends VisorJob<PropertyArgs, PropertyOperationResult> {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /**
+         * @param arg Argument.
+         * @param debug Debug.
+         */
+        protected PropertyJob(@Nullable PropertyArgs arg, boolean debug) {
+            super(arg, debug);
+        }
+
+        /** {@inheritDoc} */
+        @Override protected PropertyOperationResult run(@Nullable PropertyArgs arg) {
+            DistributedChangeableProperty<Serializable> prop =
+                ignite.context().distributedConfiguration().property(arg.name());
+
+            if (prop == null)
+                throw new IllegalArgumentException("Property doesn't not exist [name=" + arg.name() + ']');
+
+            switch (arg.action()) {
+                case GET:
+                    ignite.context().security().authorize(ADMIN_READ_DISTRIBUTED_PROPERTY);
+
+                    return new PropertyOperationResult(Objects.toString(prop.get()));
+
+                case SET:
+                    ignite.context().security().authorize(ADMIN_WRITE_DISTRIBUTED_PROPERTY);
+
+                    try {
+                        prop.propagate(prop.parse(arg.value()));
+                    }
+                    catch (IgniteCheckedException e) {
+                        throw new IgniteException(e);
+                    }
+
+                    return new PropertyOperationResult(null);
+
+                default:
+                    assert false : "unexpected state";
+
+                    return null;
+            }
+        }
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/configuration/distributed/DistributedBooleanProperty.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/configuration/distributed/DistributedBooleanProperty.java
index 878ebb0..934a32a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/configuration/distributed/DistributedBooleanProperty.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/configuration/distributed/DistributedBooleanProperty.java
@@ -21,10 +21,9 @@ package org.apache.ignite.internal.processors.configuration.distributed;
  * Implementation of {@link DistributedProperty} for {@link Boolean}.
  */
 public class DistributedBooleanProperty extends SimpleDistributedProperty<Boolean> {
-
     /** {@inheritDoc} */
     DistributedBooleanProperty(String name) {
-        super(name);
+        super(name, Boolean::parseBoolean);
     }
 
     /**
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/configuration/distributed/DistributedChangeableProperty.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/configuration/distributed/DistributedChangeableProperty.java
index dfd4a25..36c89f0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/configuration/distributed/DistributedChangeableProperty.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/configuration/distributed/DistributedChangeableProperty.java
@@ -42,4 +42,10 @@ public interface DistributedChangeableProperty<T extends Serializable> extends D
      * @param newVal New value.
      */
     void localUpdate(Serializable newVal);
+
+    /**
+     * @param str String representation of the property value.
+     * @return Property value.
+     */
+    T parse(String str);
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/configuration/distributed/DistributedComparableProperty.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/configuration/distributed/DistributedComparableProperty.java
index 2e646d7..7ec38a3 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/configuration/distributed/DistributedComparableProperty.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/configuration/distributed/DistributedComparableProperty.java
@@ -19,15 +19,15 @@ package org.apache.ignite.internal.processors.configuration.distributed;
 
 import java.io.Serializable;
 import java.util.Objects;
+import java.util.function.Function;
 
 /**
  * Implementation of {@link DistributedProperty} for {@link Comparable}.
  */
 public class DistributedComparableProperty<T extends Comparable<T> & Serializable> extends SimpleDistributedProperty<T> {
-
     /** {@inheritDoc} */
-    DistributedComparableProperty(String name) {
-        super(name);
+    DistributedComparableProperty(String name, Function<String, T> parser) {
+        super(name, parser);
     }
 
     /** */
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/configuration/distributed/DistributedConfigurationProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/configuration/distributed/DistributedConfigurationProcessor.java
index e89de39..5316f62 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/configuration/distributed/DistributedConfigurationProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/configuration/distributed/DistributedConfigurationProcessor.java
@@ -19,8 +19,10 @@ package org.apache.ignite.internal.processors.configuration.distributed;
 
 import java.io.Serializable;
 import java.util.Arrays;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.processors.GridProcessorAdapter;
@@ -154,6 +156,29 @@ public class DistributedConfigurationProcessor extends GridProcessorAdapter impl
     }
 
     /**
+     * @return Public properties.
+     */
+    public List<DistributedChangeableProperty<Serializable>> properties() {
+        return props.values().stream()
+            .filter(p -> p instanceof DistributedChangeableProperty)
+            .map(p -> (DistributedChangeableProperty<Serializable>)p)
+            .collect(Collectors.toList());
+    }
+
+    /**
+     * @param name Property name.
+     * @return Public property.
+     */
+    public DistributedChangeableProperty<Serializable> property(String name) {
+        DistributedChangeableProperty<?> p = props.get(name);
+
+        if (!(p instanceof DistributedChangeableProperty))
+            return null;
+        else
+            return (DistributedChangeableProperty<Serializable>)p;
+    }
+
+    /**
      * Execute all allowable actions until current action on given property.
      *
      * @param prop Property which action should be executed on.
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/configuration/distributed/DistributedEnumProperty.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/configuration/distributed/DistributedEnumProperty.java
index 10741dc..7632554 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/configuration/distributed/DistributedEnumProperty.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/configuration/distributed/DistributedEnumProperty.java
@@ -18,6 +18,9 @@
 package org.apache.ignite.internal.processors.configuration.distributed;
 
 import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.stream.Collectors;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.util.future.GridFutureAdapter;
 import org.apache.ignite.internal.util.typedef.internal.S;
@@ -38,38 +41,29 @@ public class DistributedEnumProperty<T extends Enum> implements DistributedChang
     private final IgniteClosure<Integer, T> fromOrdinalFunc;
 
     /** Function converts an enumeration value to an integer for stored in meta storage. */
-    private final IgniteClosure<T, Integer> toOredinalFunc;
+    private final IgniteClosure<T, Integer> toOrdinalFunc;
 
-    /**
-     * Property constructor.
-     *
-     * @param name Name of property.
-     * @param fromOrdinalFunc Function reflects an integer to an enumiration value.
-     */
-    public DistributedEnumProperty(
-        String name,
-        IgniteClosure<Integer, T> fromOrdinalFunc
-    ) {
-        this(name, fromOrdinalFunc, (T value) -> {
-            return value == null ? null : value.ordinal();
-        });
-    }
+    /** Enum name-values map to parse string representation. */
+    private final Map<String, T> values;
 
     /**
      * Property constructor.
      *
      * @param name Name of property.
      * @param fromOrdinalFunc Function reflects an integer to an enumiration value.
-     * @param toOredinalFunc Function converts an enumeration value to an integer.
+     * @param toOrdinalFunc Function converts an enumeration value to an integer.
      */
     public DistributedEnumProperty(
         String name,
         IgniteClosure<Integer, T> fromOrdinalFunc,
-        IgniteClosure<T, Integer> toOredinalFunc
+        IgniteClosure<T, Integer> toOrdinalFunc,
+        Class<T> enumCls
     ) {
-        this.internal = new SimpleDistributedProperty<>(name);
+        this.internal = new SimpleDistributedProperty<>(name, null);
         this.fromOrdinalFunc = fromOrdinalFunc;
-        this.toOredinalFunc = toOredinalFunc;
+        this.toOrdinalFunc = toOrdinalFunc;
+        this.values = Arrays.stream(enumCls.getEnumConstants())
+            .collect(Collectors.toMap(e -> e.name().toLowerCase(), e -> e));
     }
 
     /** {@inheritDoc} */
@@ -140,7 +134,7 @@ public class DistributedEnumProperty<T extends Enum> implements DistributedChang
      * @return Ordinal or {@code null}.
      */
     private Integer ordinalOrNull(T val) {
-        return val == null ? null : toOredinalFunc.apply(val);
+        return val == null ? null : toOrdinalFunc.apply(val);
     }
 
     /**
@@ -154,6 +148,18 @@ public class DistributedEnumProperty<T extends Enum> implements DistributedChang
     }
 
     /** {@inheritDoc} */
+    @Override public T parse(String str) {
+        T t = values.get(str.toLowerCase());
+
+        if (t == null) {
+            throw new IllegalArgumentException("Unknown value for enum property " +
+                "[value=" + str + ", name=" + internal.getName());
+        }
+
+        return t;
+    }
+
+    /** {@inheritDoc} */
     @Override public String toString() {
         return S.toString(DistributedEnumProperty.class, this);
     }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/configuration/distributed/DistributedLongProperty.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/configuration/distributed/DistributedLongProperty.java
index 38b1ad0..fbfd316 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/configuration/distributed/DistributedLongProperty.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/configuration/distributed/DistributedLongProperty.java
@@ -21,10 +21,9 @@ package org.apache.ignite.internal.processors.configuration.distributed;
  * Implementation of {@link DistributedProperty} for {@link Long}.
  */
 public class DistributedLongProperty extends DistributedComparableProperty<Long> {
-
     /** {@inheritDoc} */
     DistributedLongProperty(String name) {
-        super(name);
+        super(name, Long::parseLong);
     }
 
     /**
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/configuration/distributed/SimpleDistributedProperty.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/configuration/distributed/SimpleDistributedProperty.java
index 9819197..5753d30 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/configuration/distributed/SimpleDistributedProperty.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/configuration/distributed/SimpleDistributedProperty.java
@@ -18,8 +18,12 @@
 package org.apache.ignite.internal.processors.configuration.distributed;
 
 import java.io.Serializable;
+import java.util.Arrays;
+import java.util.HashSet;
 import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.function.Function;
 import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
 import org.apache.ignite.internal.util.future.GridFutureAdapter;
 import org.apache.ignite.internal.util.tostring.GridToStringExclude;
 import org.apache.ignite.internal.util.typedef.internal.S;
@@ -48,11 +52,17 @@ public class SimpleDistributedProperty<T extends Serializable> implements Distri
     @GridToStringExclude
     private volatile PropertyUpdateClosure clusterWideUpdater;
 
+    /** Property value parser. */
+    @GridToStringExclude
+    private final Function<String, T> parser;
+
     /**
      * @param name Name of property.
+     * @param parser Property value parser.
      */
-    public SimpleDistributedProperty(String name) {
+    public SimpleDistributedProperty(String name, Function<String, T> parser) {
         this.name = name;
+        this.parser = parser;
     }
 
     /** {@inheritDoc} */
@@ -132,7 +142,64 @@ public class SimpleDistributedProperty<T extends Serializable> implements Distri
     }
 
     /** {@inheritDoc} */
+    @Override public T parse(String str) {
+        if (parser == null)
+            throw new IgniteException("The parser is not specified for property [name=" + name + ']');
+
+        return parser.apply(str);
+    }
+
+    /** {@inheritDoc} */
     @Override public String toString() {
         return S.toString(SimpleDistributedProperty.class, this);
     }
+
+    /**
+     * @param val String to parse.
+     * @return Integer value.
+     */
+    public static Integer parseNonNegativeInteger(String val) {
+        if (val == null || val.trim().isEmpty())
+            return null;
+
+        int intVal = Integer.parseInt(val);
+
+        if (intVal < 0)
+            throw new IllegalArgumentException("The value must not be negative");
+
+        return intVal;
+    }
+
+    /**
+     * @param val String to parse.
+     * @return Long value.
+     */
+    public static Long parseNonNegativeLong(String val) {
+        if (val == null || val.trim().isEmpty())
+            return null;
+
+        long intVal = Long.parseLong(val);
+
+        if (intVal < 0)
+            throw new IllegalArgumentException("The value must not be negative");
+
+        return intVal;
+    }
+
+    /**
+     * @param val String value.
+     * @return String set.
+     */
+    public static HashSet<String> parseStringSet(String val) {
+        HashSet<String> set = new HashSet<>();
+
+        if (val == null || val.trim().isEmpty())
+            return set;
+
+        String[] vals = val.split("\\W+");
+
+        set.addAll(Arrays.asList(vals));
+
+        return set;
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/tracing/configuration/DistributedTracingConfiguration.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/tracing/configuration/DistributedTracingConfiguration.java
index 8624778..690d145 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/tracing/configuration/DistributedTracingConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/tracing/configuration/DistributedTracingConfiguration.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.internal.processors.tracing.configuration;
 
 import java.util.HashMap;
+import org.apache.ignite.IgniteException;
 import org.apache.ignite.internal.processors.configuration.distributed.DistributedConfigurationProcessor;
 import org.apache.ignite.internal.processors.configuration.distributed.SimpleDistributedProperty;
 import org.apache.ignite.spi.tracing.TracingConfigurationCoordinates;
@@ -36,7 +37,7 @@ public class DistributedTracingConfiguration
      * Constructor.
      */
     public DistributedTracingConfiguration() {
-        super(TRACING_CONFIGURATION_DISTRIBUTED_METASTORE_KEY);
+        super(TRACING_CONFIGURATION_DISTRIBUTED_METASTORE_KEY, null);
     }
 
     /**
@@ -46,4 +47,9 @@ public class DistributedTracingConfiguration
     public static DistributedTracingConfiguration detachedProperty() {
         return new DistributedTracingConfiguration();
     }
+
+    /** {@inheritDoc} */
+    @Override public HashMap<TracingConfigurationCoordinates, TracingConfigurationParameters> parse(String str) {
+        throw new IgniteException("Please use the '--tracing-configuration' command to modify the tracing configuration");
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/plugin/security/SecurityPermission.java b/modules/core/src/main/java/org/apache/ignite/plugin/security/SecurityPermission.java
index e062bc3..d6fe810 100644
--- a/modules/core/src/main/java/org/apache/ignite/plugin/security/SecurityPermission.java
+++ b/modules/core/src/main/java/org/apache/ignite/plugin/security/SecurityPermission.java
@@ -76,7 +76,13 @@ public enum SecurityPermission {
     JOIN_AS_SERVER,
 
     /** Administration operation with cluster metadata (REMOVE, UPDATE). */
-    ADMIN_METADATA_OPS;
+    ADMIN_METADATA_OPS,
+
+    /** Administration operation: read distributed properties values. */
+    ADMIN_READ_DISTRIBUTED_PROPERTY,
+
+    /** Administration operation: write distributed properties values. */
+    ADMIN_WRITE_DISTRIBUTED_PROPERTY;
 
     /** Enumerated values. */
     private static final SecurityPermission[] VALS = values();
diff --git a/modules/core/src/main/resources/META-INF/classnames.properties b/modules/core/src/main/resources/META-INF/classnames.properties
index 9815054..a7fc780 100644
--- a/modules/core/src/main/resources/META-INF/classnames.properties
+++ b/modules/core/src/main/resources/META-INF/classnames.properties
@@ -383,6 +383,11 @@ org.apache.ignite.internal.commandline.meta.tasks.MetadataRemoveTask$DropAllThin
 org.apache.ignite.internal.commandline.meta.tasks.MetadataTypeArgs
 org.apache.ignite.internal.commandline.meta.tasks.MetadataUpdateTask
 org.apache.ignite.internal.commandline.meta.tasks.MetadataUpdateTask.MetadataUpdateJob
+org.apache.ignite.internal.commandline.property.tasks.PropertiesListResult
+org.apache.ignite.internal.commandline.property.tasks.PropertiesListTask
+org.apache.ignite.internal.commandline.property.tasks.PropertyOperationResult
+org.apache.ignite.internal.commandline.property.tasks.PropertyTask
+org.apache.ignite.internal.commandline.property.PropertyArgs
 org.apache.ignite.internal.commandline.ru.RollingUpgradeCommandArg
 org.apache.ignite.internal.commandline.ru.RollingUpgradeSubCommands
 org.apache.ignite.internal.compute.ComputeTaskCancelledCheckedException
diff --git a/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassTest_help.output b/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassTest_help.output
index e8727aa..ca726a5 100644
--- a/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassTest_help.output
+++ b/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassTest_help.output
@@ -168,6 +168,18 @@ If the file name isn't specified the output file name is: '<typeId>.bin'
   Stop warm-up:
     control.(sh|bat) --warm-up --stop
 
+  Print property command help:
+    control.(sh|bat) --property help
+
+  Print list of available properties:
+    control.(sh|bat) --property list
+
+  Get the property value
+    control.(sh|bat) --property get --name <property_name>
+
+  Set the property value
+    control.(sh|bat) --property set --name <property_name> --val <property_value>
+
 By default commands affecting the cluster require interactive confirmation.
 Use --yes option to disable it.
 
diff --git a/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassWithSSLTest_help.output b/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassWithSSLTest_help.output
index e8727aa..ca726a5 100644
--- a/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassWithSSLTest_help.output
+++ b/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassWithSSLTest_help.output
@@ -168,6 +168,18 @@ If the file name isn't specified the output file name is: '<typeId>.bin'
   Stop warm-up:
     control.(sh|bat) --warm-up --stop
 
+  Print property command help:
+    control.(sh|bat) --property help
+
+  Print list of available properties:
+    control.(sh|bat) --property list
+
+  Get the property value
+    control.(sh|bat) --property get --name <property_name>
+
+  Set the property value
+    control.(sh|bat) --property set --name <property_name> --val <property_value>
+
 By default commands affecting the cluster require interactive confirmation.
 Use --yes option to disable it.
 
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DistributedSqlConfiguration.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DistributedSqlConfiguration.java
index c7b47eb..9636ae4 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DistributedSqlConfiguration.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DistributedSqlConfiguration.java
@@ -61,12 +61,16 @@ public class DistributedSqlConfiguration {
     public static final int DFLT_QRY_TIMEOUT = 0;
 
     /** Disabled SQL functions. */
-    private final SimpleDistributedProperty<HashSet<String>> disabledSqlFuncs
-        = new SimpleDistributedProperty<>("sql.disabledFunctions");
+    private final SimpleDistributedProperty<HashSet<String>> disabledSqlFuncs = new SimpleDistributedProperty<>(
+        "sql.disabledFunctions",
+        SimpleDistributedProperty::parseStringSet
+    );
 
     /** Query timeout. */
-    private final SimpleDistributedProperty<Integer> dfltQueryTimeout
-        = new SimpleDistributedProperty<>("sql.defaultQueryTimeout");
+    private final SimpleDistributedProperty<Integer> dfltQueryTimeout = new SimpleDistributedProperty<>(
+        "sql.defaultQueryTimeout",
+        SimpleDistributedProperty::parseNonNegativeInteger
+    );
 
     /**
      * @param ctx Kernal context