Repository: ignite
Updated Branches:
  refs/heads/master c1edb3009 -> 7c2ce4c74


IGNITE-9308 Add baseline topology command to REST API. - Fixes #5019.

Signed-off-by: Andrey Novikov <[email protected]>


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/7c2ce4c7
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/7c2ce4c7
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/7c2ce4c7

Branch: refs/heads/master
Commit: 7c2ce4c7488253590885f75335b6d9209771fa46
Parents: c1edb30
Author: Andrey Novikov <[email protected]>
Authored: Tue Dec 18 17:34:27 2018 +0700
Committer: Andrey Novikov <[email protected]>
Committed: Tue Dec 18 17:34:27 2018 +0700

----------------------------------------------------------------------
 .../client/suite/IgniteClientTestSuite.java     |   2 +
 .../JettyRestProcessorBaselineSelfTest.java     | 221 +++++++++++++++++++
 .../processors/rest/GridRestCommand.java        |  12 +
 .../processors/rest/GridRestProcessor.java      |   6 +
 .../cluster/GridBaselineCommandHandler.java     | 205 +++++++++++++++++
 .../cluster/GridBaselineCommandResponse.java    | 161 ++++++++++++++
 .../rest/request/GridRestBaselineRequest.java   |  65 ++++++
 .../http/jetty/GridJettyRestHandler.java        |  16 ++
 8 files changed, 688 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/7c2ce4c7/modules/clients/src/test/java/org/apache/ignite/internal/client/suite/IgniteClientTestSuite.java
----------------------------------------------------------------------
diff --git 
a/modules/clients/src/test/java/org/apache/ignite/internal/client/suite/IgniteClientTestSuite.java
 
b/modules/clients/src/test/java/org/apache/ignite/internal/client/suite/IgniteClientTestSuite.java
index ff27354..d20da01 100644
--- 
a/modules/clients/src/test/java/org/apache/ignite/internal/client/suite/IgniteClientTestSuite.java
+++ 
b/modules/clients/src/test/java/org/apache/ignite/internal/client/suite/IgniteClientTestSuite.java
@@ -55,6 +55,7 @@ import 
org.apache.ignite.internal.processors.rest.ChangeStateCommandHandlerTest;
 import 
org.apache.ignite.internal.processors.rest.ClientMemcachedProtocolSelfTest;
 import 
org.apache.ignite.internal.processors.rest.JettyRestProcessorAuthenticationWithCredsSelfTest;
 import 
org.apache.ignite.internal.processors.rest.JettyRestProcessorAuthenticationWithTokenSelfTest;
+import 
org.apache.ignite.internal.processors.rest.JettyRestProcessorBaselineSelfTest;
 import 
org.apache.ignite.internal.processors.rest.JettyRestProcessorGetAllAsArrayTest;
 import 
org.apache.ignite.internal.processors.rest.JettyRestProcessorSignedSelfTest;
 import 
org.apache.ignite.internal.processors.rest.JettyRestProcessorUnsignedSelfTest;
@@ -100,6 +101,7 @@ public class IgniteClientTestSuite extends TestSuite {
         suite.addTest(new 
JUnit4TestAdapter(JettyRestProcessorAuthenticationWithCredsSelfTest.class));
         suite.addTest(new 
JUnit4TestAdapter(JettyRestProcessorAuthenticationWithTokenSelfTest.class));
         suite.addTest(new 
JUnit4TestAdapter(JettyRestProcessorGetAllAsArrayTest.class));
+        suite.addTest(new 
JUnit4TestAdapter(JettyRestProcessorBaselineSelfTest.class));
 
         // Test TCP rest processor with original memcache client.
         suite.addTest(new 
JUnit4TestAdapter(ClientMemcachedProtocolSelfTest.class));

http://git-wip-us.apache.org/repos/asf/ignite/blob/7c2ce4c7/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorBaselineSelfTest.java
----------------------------------------------------------------------
diff --git 
a/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorBaselineSelfTest.java
 
b/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorBaselineSelfTest.java
new file mode 100644
index 0000000..d3bfce8
--- /dev/null
+++ 
b/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorBaselineSelfTest.java
@@ -0,0 +1,221 @@
+/*
+ * 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.processors.rest;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import org.apache.ignite.cluster.BaselineNode;
+import org.apache.ignite.configuration.DataRegionConfiguration;
+import org.apache.ignite.configuration.DataStorageConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import 
org.apache.ignite.internal.processors.rest.handlers.cluster.GridBaselineCommandResponse;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.jetbrains.annotations.Nullable;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import static org.apache.ignite.configuration.WALMode.NONE;
+import static 
org.apache.ignite.internal.processors.rest.GridRestResponse.STATUS_SUCCESS;
+
+/**
+ * Test REST with enabled authentication.
+ */
+@RunWith(JUnit4.class)
+public class JettyRestProcessorBaselineSelfTest extends 
JettyRestProcessorCommonSelfTest {
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        U.resolveWorkDirectory(U.defaultWorkDirectory(), "db", true);
+
+        super.beforeTestsStarted();
+
+        // We need to activate cluster.
+        grid(0).cluster().active(true);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        super.afterTest();
+
+        
grid(0).cluster().setBaselineTopology(grid(0).cluster().topologyVersion());
+    }
+
+    /** {@inheritDoc} */
+    @Override protected String signature() {
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String 
igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        DataStorageConfiguration dsCfg = new DataStorageConfiguration()
+            .setDefaultDataRegionConfiguration(new DataRegionConfiguration()
+                .setMaxSize(100 * 1024 * 1024)
+                .setPersistenceEnabled(true))
+            .setWalMode(NONE);
+
+        cfg.setDataStorageConfiguration(dsCfg);
+
+        return cfg;
+    }
+
+    /**
+     * @param nodes Collection of grid nodes.
+     * @return Collection of node consistent IDs for given collection of grid 
nodes.
+     */
+    private static Collection<String> nodeConsistentIds(@Nullable Collection<? 
extends BaselineNode> nodes) {
+        if (nodes == null || nodes.isEmpty())
+            return Collections.emptyList();
+
+        return F.viewReadOnly(nodes, n -> String.valueOf(n.consistentId()));
+    }
+
+    /**
+     * @param content Content to check.
+     * @param baselineSz Expected baseline size.
+     * @param srvsSz Expected server nodes count.
+     */
+    private void assertBaseline(String content, int baselineSz, int srvsSz) 
throws IOException {
+        assertNotNull(content);
+        assertFalse(content.isEmpty());
+
+        JsonNode node = JSON_MAPPER.readTree(content);
+
+        assertEquals(STATUS_SUCCESS, node.get("successStatus").asInt());
+        assertTrue(node.get("error").isNull());
+
+        assertNotSame(securityEnabled(), node.get("sessionToken").isNull());
+
+        JsonNode res = node.get("response");
+
+        assertFalse(res.isNull());
+
+        GridBaselineCommandResponse baseline = JSON_MAPPER.treeToValue(res, 
GridBaselineCommandResponse.class);
+
+        assertTrue(baseline.isActive());
+        assertEquals(grid(0).cluster().topologyVersion(), 
baseline.getTopologyVersion());
+        assertEquals(baselineSz, baseline.getBaseline().size());
+        
assertEqualsCollections(nodeConsistentIds(grid(0).cluster().currentBaselineTopology()),
 baseline.getBaseline());
+        assertEquals(srvsSz, baseline.getServers().size());
+        assertEqualsCollections(nodeConsistentIds(grid(0).cluster().nodes()), 
baseline.getServers());
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testBaseline() throws Exception {
+        int sz = gridCount();
+        
+        assertBaseline(content(null, GridRestCommand.BASELINE_CURRENT_STATE), 
sz, sz);
+
+        // Stop one node. It will stay in baseline.
+        stopGrid(sz - 1);
+        assertBaseline(content(null, GridRestCommand.BASELINE_CURRENT_STATE), 
sz, sz - 1);
+
+        // Start one node. Server node will be added, but baseline will not 
change.
+        startGrid(sz - 1);
+        assertBaseline(content(null, GridRestCommand.BASELINE_CURRENT_STATE), 
sz, sz);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testBaselineSet() throws Exception {
+        int sz = gridCount();
+        
+        assertBaseline(content(null, GridRestCommand.BASELINE_CURRENT_STATE), 
sz, sz);
+
+        startGrid(sz);
+        assertBaseline(content(null, GridRestCommand.BASELINE_CURRENT_STATE), 
sz, sz + 1);
+
+        assertBaseline(content(null, GridRestCommand.BASELINE_SET, "topVer",
+            String.valueOf(grid(0).cluster().topologyVersion())), sz + 1, sz + 
1);
+
+        stopGrid(sz);
+
+        assertBaseline(content(null, GridRestCommand.BASELINE_CURRENT_STATE), 
sz + 1, sz);
+
+        assertBaseline(content(null, GridRestCommand.BASELINE_SET, "topVer",
+            String.valueOf(grid(0).cluster().topologyVersion())), sz, sz);
+
+        startGrid(sz);
+        assertBaseline(content(null, GridRestCommand.BASELINE_CURRENT_STATE), 
sz, sz + 1);
+
+        ArrayList<String> params = new ArrayList<>();
+        int i = 1;
+
+        for (BaselineNode n : grid(0).cluster().nodes()) {
+            params.add("consistentId" + i++);
+            params.add(String.valueOf(n.consistentId()));
+        }
+
+        assertBaseline(content(null, GridRestCommand.BASELINE_SET, 
params.toArray(new String[0])),
+            sz + 1, sz + 1);
+
+        stopGrid(sz);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testBaselineAdd() throws Exception {
+        int sz = gridCount();
+        
+        assertBaseline(content(null, GridRestCommand.BASELINE_CURRENT_STATE), 
sz, sz);
+
+        startGrid(sz);
+        assertBaseline(content(null, GridRestCommand.BASELINE_CURRENT_STATE), 
sz, sz + 1);
+
+        assertBaseline(content(null, GridRestCommand.BASELINE_ADD, 
"consistentId1",
+            grid(sz).localNode().consistentId().toString()), sz + 1, sz + 1);
+        
+        stopGrid(sz);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testBaselineRemove() throws Exception {
+        int sz = gridCount();
+        
+        assertBaseline(content(null, GridRestCommand.BASELINE_CURRENT_STATE), 
sz, sz);
+
+        startGrid(sz);
+        assertBaseline(content(null, GridRestCommand.BASELINE_CURRENT_STATE), 
sz, sz + 1);
+
+        assertBaseline(content(null, GridRestCommand.BASELINE_SET, "topVer",
+            String.valueOf(grid(0).cluster().topologyVersion())), sz + 1, sz + 
1);
+
+        String consistentId = grid(sz).localNode().consistentId().toString();
+
+        stopGrid(sz);
+        assertBaseline(content(null, GridRestCommand.BASELINE_CURRENT_STATE), 
sz + 1, sz);
+
+        assertBaseline(content(null, GridRestCommand.BASELINE_REMOVE, 
"consistentId1",
+            consistentId), sz, sz);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/7c2ce4c7/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestCommand.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestCommand.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestCommand.java
index 587ed2e..4046b15 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestCommand.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestCommand.java
@@ -177,6 +177,18 @@ public enum GridRestCommand {
     CLUSTER_CURRENT_STATE("currentstate"),
 
     /** */
+    BASELINE_CURRENT_STATE("baseline"),
+
+    /** */
+    BASELINE_SET("setbaseline"),
+
+    /** */
+    BASELINE_ADD("addbaseline"),
+
+    /** */
+    BASELINE_REMOVE("removebaseline"),
+
+    /** */
     AUTHENTICATE("authenticate"),
 
     /** */

http://git-wip-us.apache.org/repos/asf/ignite/blob/7c2ce4c7/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestProcessor.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestProcessor.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestProcessor.java
index 7db0721..f24c4d3 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestProcessor.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestProcessor.java
@@ -49,6 +49,7 @@ import 
org.apache.ignite.internal.processors.rest.client.message.GridClientTaskR
 import 
org.apache.ignite.internal.processors.rest.handlers.GridRestCommandHandler;
 import 
org.apache.ignite.internal.processors.rest.handlers.auth.AuthenticationCommandHandler;
 import 
org.apache.ignite.internal.processors.rest.handlers.cache.GridCacheCommandHandler;
+import 
org.apache.ignite.internal.processors.rest.handlers.cluster.GridBaselineCommandHandler;
 import 
org.apache.ignite.internal.processors.rest.handlers.cluster.GridChangeStateCommandHandler;
 import 
org.apache.ignite.internal.processors.rest.handlers.datastructures.DataStructuresCommandHandler;
 import 
org.apache.ignite.internal.processors.rest.handlers.log.GridLogCommandHandler;
@@ -531,6 +532,7 @@ public class GridRestProcessor extends GridProcessorAdapter 
{
             addHandler(new GridChangeStateCommandHandler(ctx));
             addHandler(new AuthenticationCommandHandler(ctx));
             addHandler(new UserActionCommandHandler(ctx));
+            addHandler(new GridBaselineCommandHandler(ctx));
 
             // Start protocols.
             startTcpProtocol();
@@ -895,6 +897,9 @@ public class GridRestProcessor extends GridProcessorAdapter 
{
             case CLUSTER_INACTIVE:
             case CLUSTER_ACTIVATE:
             case CLUSTER_DEACTIVATE:
+            case BASELINE_SET:
+            case BASELINE_ADD:
+            case BASELINE_REMOVE:
                 perm = SecurityPermission.ADMIN_OPS;
 
                 break;
@@ -912,6 +917,7 @@ public class GridRestProcessor extends GridProcessorAdapter 
{
             case NAME:
             case LOG:
             case CLUSTER_CURRENT_STATE:
+            case BASELINE_CURRENT_STATE:
             case AUTHENTICATE:
             case ADD_USER:
             case REMOVE_USER:

http://git-wip-us.apache.org/repos/asf/ignite/blob/7c2ce4c7/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cluster/GridBaselineCommandHandler.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cluster/GridBaselineCommandHandler.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cluster/GridBaselineCommandHandler.java
new file mode 100644
index 0000000..88fde87
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cluster/GridBaselineCommandHandler.java
@@ -0,0 +1,205 @@
+/*
+ * 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.processors.rest.handlers.cluster;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.cluster.BaselineNode;
+import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.cluster.IgniteClusterEx;
+import org.apache.ignite.internal.processors.rest.GridRestCommand;
+import org.apache.ignite.internal.processors.rest.GridRestResponse;
+import 
org.apache.ignite.internal.processors.rest.handlers.GridRestCommandHandlerAdapter;
+import 
org.apache.ignite.internal.processors.rest.request.GridRestBaselineRequest;
+import org.apache.ignite.internal.processors.rest.request.GridRestRequest;
+import org.apache.ignite.internal.util.future.GridFinishedFuture;
+import org.apache.ignite.internal.util.typedef.internal.U;
+
+import static java.util.function.Function.identity;
+import static java.util.stream.Collectors.toMap;
+import static 
org.apache.ignite.internal.processors.rest.GridRestCommand.BASELINE_ADD;
+import static 
org.apache.ignite.internal.processors.rest.GridRestCommand.BASELINE_CURRENT_STATE;
+import static 
org.apache.ignite.internal.processors.rest.GridRestCommand.BASELINE_REMOVE;
+import static 
org.apache.ignite.internal.processors.rest.GridRestCommand.BASELINE_SET;
+
+/**
+ *
+ */
+public class GridBaselineCommandHandler extends GridRestCommandHandlerAdapter {
+    /** Supported commands. */
+    private static final Collection<GridRestCommand> SUPPORTED_COMMANDS = 
U.sealList(BASELINE_CURRENT_STATE,
+        BASELINE_SET, BASELINE_ADD, BASELINE_REMOVE);
+
+    /**
+     * @param ctx Context.
+     */
+    public GridBaselineCommandHandler(GridKernalContext ctx) {
+        super(ctx);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<GridRestCommand> supportedCommands() {
+        return SUPPORTED_COMMANDS;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<GridRestResponse> 
handleAsync(GridRestRequest req) {
+        assert req != null;
+
+        assert SUPPORTED_COMMANDS.contains(req.command());
+        assert req instanceof GridRestBaselineRequest : "Invalid type of 
baseline request.";
+
+
+        if (log.isDebugEnabled())
+            log.debug("Handling baseline REST request: " + req);
+
+        GridRestBaselineRequest req0 = (GridRestBaselineRequest)req;
+        
+        try {
+            IgniteClusterEx cluster = ctx.grid().cluster();
+
+            List<Object> consistentIds = req0.consistentIds();
+
+            switch (req0.command()) {
+                case BASELINE_CURRENT_STATE: {
+                    // No-op.
+
+                    break;
+                }
+
+                case BASELINE_SET: {
+                    Long topVer = req0.topologyVersion();
+
+                    if (topVer == null && consistentIds == null)
+                        throw new IgniteCheckedException("Failed to handle 
request (either topVer or consistentIds should be specified).");
+
+                    if (topVer != null)
+                        cluster.setBaselineTopology(topVer);
+                    else
+                        
cluster.setBaselineTopology(filterServerNodesByConsId(consistentIds));
+
+                    break;
+                }
+
+                case BASELINE_ADD: {
+                    if (consistentIds == null)
+                        throw new 
IgniteCheckedException(missingParameter("consistentIds"));
+
+                    Set<BaselineNode> baselineTop = new 
HashSet<>(currentBaseLine());
+
+                    
baselineTop.addAll(filterServerNodesByConsId(consistentIds));
+
+                    cluster.setBaselineTopology(baselineTop);
+
+                    break;
+                }
+
+                case BASELINE_REMOVE: {
+                    if (consistentIds == null)
+                        throw new 
IgniteCheckedException(missingParameter("consistentIds"));
+
+                    Collection<BaselineNode> baseline = currentBaseLine();
+
+                    Set<BaselineNode> baselineTop = new HashSet<>(baseline);
+
+                    baselineTop.removeAll(filterNodesByConsId(baseline, 
consistentIds));
+
+                    cluster.setBaselineTopology(baselineTop);
+
+                    break;
+                }
+
+                default:
+                    assert false : "Invalid command for baseline handler: " + 
req;
+            }
+
+            return new GridFinishedFuture<>(new 
GridRestResponse(currentState()));
+        }
+        catch (IgniteCheckedException e) {
+            return new GridFinishedFuture<>(e);
+        }
+        finally {
+            if (log.isDebugEnabled())
+                log.debug("Handled baseline REST request: " + req);
+        }
+    }
+
+    /**
+     * @return Current baseline.
+     */
+    private Collection<BaselineNode> currentBaseLine() {
+        Collection<BaselineNode> baselineNodes = 
ctx.grid().cluster().currentBaselineTopology();
+
+        return baselineNodes != null ? baselineNodes : Collections.emptyList();
+    }
+
+    /**
+     * Collect baseline topology command result.
+     *
+     * @return Baseline descriptor.
+     */
+    private GridBaselineCommandResponse currentState() {
+        IgniteClusterEx cluster = ctx.grid().cluster();
+
+        Collection<? extends BaselineNode> srvrs = 
cluster.forServers().nodes();
+
+        return new GridBaselineCommandResponse(cluster.active(), 
cluster.topologyVersion(), currentBaseLine(), srvrs);
+    }
+
+    /**
+     * Filter passed nodes by consistent IDs.
+     *
+     * @param nodes Collection of nodes.
+     * @param consistentIds Collection of consistent IDs.
+     * @throws IllegalStateException In case of some consistent ID not found 
in nodes collection.
+     */
+    private Collection<BaselineNode> filterNodesByConsId(Collection<? extends 
BaselineNode> nodes, List<Object> consistentIds) {
+        Map<Object, BaselineNode> nodeMap =
+            nodes.stream().collect(toMap(n -> n.consistentId().toString(), 
identity()));
+
+        Collection<BaselineNode> filtered = new 
ArrayList<>(consistentIds.size());
+
+        for (Object consistentId : consistentIds) {
+            BaselineNode node = nodeMap.get(consistentId);
+
+            if (node == null)
+                throw new IllegalStateException("Node not found for consistent 
ID: " + consistentId);
+
+            filtered.add(node);
+        }
+
+        return filtered;
+    }
+
+    /**
+     * Filter server nodes by consistent IDs.
+     *
+     * @param consistentIds Collection of consistent IDs to add.
+     * @throws IllegalStateException In case of some consistent ID not found 
in nodes collection.
+     */
+    private Collection<BaselineNode> filterServerNodesByConsId(List<Object> 
consistentIds) {
+        return filterNodesByConsId(ctx.grid().cluster().forServers().nodes(), 
consistentIds);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/7c2ce4c7/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cluster/GridBaselineCommandResponse.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cluster/GridBaselineCommandResponse.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cluster/GridBaselineCommandResponse.java
new file mode 100644
index 0000000..aae16c0
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cluster/GridBaselineCommandResponse.java
@@ -0,0 +1,161 @@
+/*
+ * 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.processors.rest.handlers.cluster;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.Collection;
+import org.apache.ignite.cluster.BaselineNode;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.internal.util.typedef.internal.U;
+
+import static java.util.stream.Collectors.toList;
+
+/**
+ * Result for baseline command.
+ */
+public class GridBaselineCommandResponse implements Externalizable {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** Cluster state. */
+    private boolean active;
+
+    /** Current topology version. */
+    private long topVer;
+
+    /** Current baseline nodes. */
+    private Collection<String> baseline;
+
+    /** Current server nodes. */
+    private Collection<String> srvs;
+
+    /**
+     * @param nodes Nodes to process.
+     * @return Collection of consistentIds.
+     */
+    private static Collection<String> consistentIds(Collection<? extends 
BaselineNode> nodes) {
+        return nodes.stream().map(n -> 
String.valueOf(n.consistentId())).collect(toList());
+    }
+
+    /**
+     * Default constructor.
+     */
+    public GridBaselineCommandResponse() {
+        // No-op.
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param active Cluster state.
+     * @param topVer Current topology version.
+     * @param baseline Current baseline nodes.
+     * @param srvs Current server nodes.
+     */
+    GridBaselineCommandResponse(
+        boolean active,
+        long topVer,
+        Collection<? extends BaselineNode> baseline,
+        Collection<? extends BaselineNode> srvs
+    ) {
+        this.active = active;
+        this.topVer = topVer;
+        this.baseline = consistentIds(baseline);
+        this.srvs = consistentIds(srvs);
+    }
+
+    /**
+     * @return Cluster state.
+     */
+    public boolean isActive() {
+        return active;
+    }
+
+    /**
+     * @param active Cluster active.
+     */
+    public void setActive(boolean active) {
+        this.active = active;
+    }
+
+    /**
+     * @return Current topology version.
+     */
+    public long getTopologyVersion() {
+        return topVer;
+    }
+
+    /**
+     * @param topVer Current topology version.
+     */
+    public void setTopologyVersion(long topVer) {
+        this.topVer = topVer;
+    }
+
+    /**
+     * @return Baseline nodes.
+     */
+    public Collection<String> getBaseline() {
+        return baseline;
+    }
+
+    /**
+     * @param baseline Baseline nodes.
+     */
+    public void setBaseline(Collection<String> baseline) {
+        this.baseline = baseline;
+    }
+
+    /**
+     * @return Server nodes.
+     */
+    public Collection<String> getServers() {
+        return srvs;
+    }
+
+    /**
+     * @param srvs Server nodes.
+     */
+    public void setServers(Collection<String> srvs) {
+        this.srvs = srvs;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        out.writeBoolean(active);
+        out.writeLong(topVer);
+        U.writeCollection(out, baseline);
+        U.writeCollection(out, srvs);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, 
ClassNotFoundException {
+        active = in.readBoolean();
+        topVer = in.readLong();
+        baseline = U.readCollection(in);
+        srvs = U.readCollection(in);
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(GridBaselineCommandResponse.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/7c2ce4c7/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/request/GridRestBaselineRequest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/request/GridRestBaselineRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/request/GridRestBaselineRequest.java
new file mode 100644
index 0000000..a3aa042
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/request/GridRestBaselineRequest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.processors.rest.request;
+
+import java.util.List;
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ * Grid command topology request.
+ */
+public class GridRestBaselineRequest extends GridRestRequest {
+    /** Topology version to set. */
+    private Long topVer;
+
+    /** Collection of consistent IDs to set. */
+    private List<Object> consistentIds;
+
+    /**
+     * @return Topology version to set.
+     */
+    public Long topologyVersion() {
+        return topVer;
+    }
+
+    /**
+     * @param topVer New topology version to set.
+     */
+    public void topologyVersion(Long topVer) {
+        this.topVer = topVer;
+    }
+
+    /**
+     * @return Collection of consistent IDs to set.
+     */
+    public List<Object> consistentIds() {
+        return consistentIds;
+    }
+
+    /**
+     * @param consistentIds New collection of consistent IDs to set.
+     */
+    public void consistentIds(List<Object> consistentIds) {
+        this.consistentIds = consistentIds;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(GridRestBaselineRequest.class, this, 
super.toString());
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/7c2ce4c7/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyRestHandler.java
----------------------------------------------------------------------
diff --git 
a/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyRestHandler.java
 
b/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyRestHandler.java
index 000f980..41642c3 100644
--- 
a/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyRestHandler.java
+++ 
b/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyRestHandler.java
@@ -51,6 +51,7 @@ import 
org.apache.ignite.internal.processors.rest.GridRestCommand;
 import org.apache.ignite.internal.processors.rest.GridRestProtocolHandler;
 import org.apache.ignite.internal.processors.rest.GridRestResponse;
 import 
org.apache.ignite.internal.processors.rest.request.DataStructuresRequest;
+import 
org.apache.ignite.internal.processors.rest.request.GridRestBaselineRequest;
 import org.apache.ignite.internal.processors.rest.request.GridRestCacheRequest;
 import 
org.apache.ignite.internal.processors.rest.request.GridRestChangeStateRequest;
 import org.apache.ignite.internal.processors.rest.request.GridRestLogRequest;
@@ -633,6 +634,7 @@ public class GridJettyRestHandler extends AbstractHandler {
             case CACHE_CAS:
             case CACHE_METRICS:
             case CACHE_SIZE:
+            case CACHE_UPDATE_TLL:
             case CACHE_METADATA:
             case CACHE_REPLACE:
             case CACHE_APPEND:
@@ -759,6 +761,20 @@ public class GridJettyRestHandler extends AbstractHandler {
                 break;
             }
 
+            case BASELINE_CURRENT_STATE:
+            case BASELINE_SET:
+            case BASELINE_ADD:
+            case BASELINE_REMOVE: {
+                GridRestBaselineRequest restReq0 = new 
GridRestBaselineRequest();
+
+                restReq0.topologyVersion(longValue("topVer", params, null));
+                restReq0.consistentIds(values(null, "consistentId", params));
+
+                restReq = restReq0;
+
+                break;
+            }
+
             case AUTHENTICATE: {
                 restReq = new GridRestRequest();
 

Reply via email to