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

av pushed a commit to branch ignite-ducktape
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/ignite-ducktape by this push:
     new bb5453f  Ducktape parallel (#8192)
bb5453f is described below

commit bb5453ffcc2098ff389a1054e0926f4616670987
Author: Ivan Daschinskiy <ivanda...@gmail.com>
AuthorDate: Mon Aug 31 17:25:11 2020 +0300

    Ducktape parallel (#8192)
---
 modules/ducktests/tests/docker/run_tests.sh        |  18 +-
 .../ducktests/tests/ignitetest/services/ignite.py  |   9 +-
 .../tests/ignitetest/services/ignite_app.py        |  17 +-
 .../utils/{ignite_config.py => config_template.py} |  10 +-
 .../ignitetest/services/utils/ignite_aware.py      |  31 ++-
 .../utils/ignite_configuration/__init__.py         |  46 ++++
 .../services/utils/ignite_configuration/cache.py   |  29 +++
 .../utils/ignite_configuration/data_storage.py     |  38 ++++
 .../utils/ignite_configuration/discovery.py        | 141 ++++++++++++
 .../services/utils/ignite_persistence.py           |   4 +-
 .../tests/ignitetest/services/utils/ignite_spec.py |  59 +++--
 .../services/utils/templates/cache_macro.j2        |  34 +++
 .../services/utils/templates/datastorage_macro.j2  |  46 ++++
 .../services/utils/templates/discovery_macro.j2    |  57 +++++
 .../utils/{config => templates}/ignite.xml.j2      |  29 ++-
 .../utils/{config => templates}/log4j.xml.j2       |   0
 .../services/utils/templates/misc_macro.j2         |  24 ++
 .../ignitetest/tests/add_node_rebalance_test.py    |  18 +-
 .../ignitetest/tests/cellular_affinity_test.py     |  35 ++-
 .../tests/ignitetest/tests/control_utility_test.py |  85 +++----
 .../tests/ignitetest/tests/discovery_test.py       | 251 ++++++++++-----------
 .../tests/ignitetest/tests/pme_free_switch_test.py |  52 ++---
 .../ducktests/tests/ignitetest/tests/smoke_test.py |  31 ++-
 .../tests/suites/fast_suite.yml}                   |  28 +--
 .../tests/ignitetest/tests/suites/slow_suite.yml   |  17 ++
 modules/ducktests/tests/setup.py                   |   5 +-
 26 files changed, 753 insertions(+), 361 deletions(-)

diff --git a/modules/ducktests/tests/docker/run_tests.sh 
b/modules/ducktests/tests/docker/run_tests.sh
index e5dc561..b9ee488 100755
--- a/modules/ducktests/tests/docker/run_tests.sh
+++ b/modules/ducktests/tests/docker/run_tests.sh
@@ -52,13 +52,22 @@ Usage: ${0} [options]
 
 The options are as follows:
 -h|--help
-    Display this help message
+    Display this help message.
+
+-n|--num-nodes
+    Specify how many nodes to start. Default number of nodes to start: 11.
+
+-j|--max-parallel
+    Specify max number of tests that can be run in parallel.
 
 -p|--param
     Use specified param to inject in tests. Could be used multiple times.
 
     ./run_tests.sh --param version=2.8.1
 
+-pj|--params-json
+    Use specified json as parameters to inject in tests. Can be extended with 
-p|--param.
+
 -g|--global
     Use specified global param to pass to test context. Could be used multiple 
times.
 
@@ -108,8 +117,11 @@ while [[ $# -ge 1 ]]; do
     case "$1" in
         -h|--help) usage;;
         -p|--param) duck_add_param "$2"; shift 2;;
+        -pj|--params-json) PARAMETERS="$2"; shift 2;;
         -g|--global) duck_add_global "$2"; shift 2;;
         -t|--tc-paths) TC_PATHS="$2"; shift 2;;
+        -n|--num-nodes) IGNITE_NUM_CONTAINERS="$2"; shift 2;;
+        -j|--max-parallel) MAX_PARALLEL="$2"; shift 2;;
         -f|--force) FORCE=$1; shift;;
         *) break;;
     esac
@@ -139,5 +151,9 @@ if [[ "$PARAMETERS" != "{}" ]]; then
     DUCKTAPE_OPTIONS="$DUCKTAPE_OPTIONS --parameters '$PARAMETERS'"
 fi
 
+if [[ -n "$MAX_PARALLEL" ]]; then
+  DUCKTAPE_OPTIONS="$DUCKTAPE_OPTIONS --max-parallel $MAX_PARALLEL"
+fi
+
 "$SCRIPT_DIR"/ducker-ignite test "$TC_PATHS" "$DUCKTAPE_OPTIONS" \
   || die "ducker-ignite test failed"
diff --git a/modules/ducktests/tests/ignitetest/services/ignite.py 
b/modules/ducktests/tests/ignitetest/services/ignite.py
index 2fb64b3..f50365d 100644
--- a/modules/ducktests/tests/ignitetest/services/ignite.py
+++ b/modules/ducktests/tests/ignitetest/services/ignite.py
@@ -31,7 +31,6 @@ from ducktape.utils.util import wait_until
 
 from ignitetest.services.utils.concurrent import CountDownLatch, AtomicValue
 from ignitetest.services.utils.ignite_aware import IgniteAwareService
-from ignitetest.utils.version import DEV_BRANCH
 
 
 class IgniteService(IgniteAwareService):
@@ -42,10 +41,8 @@ class IgniteService(IgniteAwareService):
     HEAP_DUMP_FILE = os.path.join(IgniteAwareService.PERSISTENT_ROOT, 
"ignite-heap.bin")
 
     # pylint: disable=R0913
-    def __init__(self, context, num_nodes, jvm_opts=None, properties="", 
client_mode=False, modules=None,
-                 version=DEV_BRANCH):
-        super().__init__(context, num_nodes, properties, 
client_mode=client_mode, modules=modules, version=version,
-                         jvm_opts=jvm_opts)
+    def __init__(self, context, config, num_nodes, jvm_opts=None, 
modules=None):
+        super().__init__(context, config, num_nodes, modules=modules, 
jvm_opts=jvm_opts)
 
     # pylint: disable=W0221
     def start(self, timeout_sec=180):
@@ -125,7 +122,7 @@ class IgniteService(IgniteAwareService):
             start_waiter.wait()
 
         if delay_ms > 0:
-            time.sleep(delay_ms/1000.0)
+            time.sleep(delay_ms / 1000.0)
 
         if time_holder:
             mono = monotonic()
diff --git a/modules/ducktests/tests/ignitetest/services/ignite_app.py 
b/modules/ducktests/tests/ignitetest/services/ignite_app.py
index 84871d8..b40d01a 100644
--- a/modules/ducktests/tests/ignitetest/services/ignite_app.py
+++ b/modules/ducktests/tests/ignitetest/services/ignite_app.py
@@ -20,7 +20,6 @@ This module contains the base class to build Ignite aware 
application written on
 import re
 
 from ignitetest.services.utils.ignite_aware import IgniteAwareService
-from ignitetest.utils.version import DEV_BRANCH
 
 
 class IgniteApplicationService(IgniteAwareService):
@@ -31,18 +30,10 @@ class IgniteApplicationService(IgniteAwareService):
     SERVICE_JAVA_CLASS_NAME = 
"org.apache.ignite.internal.ducktest.utils.IgniteAwareApplicationService"
 
     # pylint: disable=R0913
-    def __init__(self, context, java_class_name, params="", properties="", 
timeout_sec=60, modules=None,
-                 client_mode=True, version=DEV_BRANCH, 
servicejava_class_name=SERVICE_JAVA_CLASS_NAME,
-                 jvm_opts=None, start_ignite=True):
-        super().__init__(context, 1, properties,
-                         client_mode=client_mode,
-                         version=version,
-                         modules=modules,
-                         servicejava_class_name=servicejava_class_name,
-                         java_class_name=java_class_name,
-                         params=params,
-                         jvm_opts=jvm_opts,
-                         start_ignite=start_ignite)
+    def __init__(self, context, config, java_class_name, params="", 
timeout_sec=60, modules=None,
+                 servicejava_class_name=SERVICE_JAVA_CLASS_NAME, 
jvm_opts=None, start_ignite=True):
+        super().__init__(context, config, 1, modules=modules, 
servicejava_class_name=servicejava_class_name,
+                         java_class_name=java_class_name, params=params, 
jvm_opts=jvm_opts, start_ignite=start_ignite)
 
         self.servicejava_class_name = servicejava_class_name
         self.java_class_name = java_class_name
diff --git a/modules/ducktests/tests/ignitetest/services/utils/ignite_config.py 
b/modules/ducktests/tests/ignitetest/services/utils/config_template.py
similarity index 91%
rename from modules/ducktests/tests/ignitetest/services/utils/ignite_config.py
rename to modules/ducktests/tests/ignitetest/services/utils/config_template.py
index 6123198..5170c4d 100644
--- a/modules/ducktests/tests/ignitetest/services/utils/ignite_config.py
+++ b/modules/ducktests/tests/ignitetest/services/utils/config_template.py
@@ -20,11 +20,11 @@ import os
 
 from jinja2 import FileSystemLoader, Environment
 
-DEFAULT_CONFIG_PATH = os.path.dirname(os.path.abspath(__file__)) + "/config"
+DEFAULT_CONFIG_PATH = os.path.dirname(os.path.abspath(__file__)) + "/templates"
 DEFAULT_IGNITE_CONF = DEFAULT_CONFIG_PATH + "/ignite.xml.j2"
 
 
-class Config:
+class ConfigTemplate:
     """
     Basic configuration.
     """
@@ -47,7 +47,7 @@ class Config:
         return res
 
 
-class IgniteServerConfig(Config):
+class IgniteServerConfigTemplate(ConfigTemplate):
     """
     Ignite server node configuration.
     """
@@ -55,7 +55,7 @@ class IgniteServerConfig(Config):
         super().__init__(path)
 
 
-class IgniteClientConfig(Config):
+class IgniteClientConfigTemplate(ConfigTemplate):
     """
     Ignite client node configuration.
     """
@@ -64,7 +64,7 @@ class IgniteClientConfig(Config):
         self.default_params.update(client_mode=True)
 
 
-class IgniteLoggerConfig(Config):
+class IgniteLoggerConfigTemplate(ConfigTemplate):
     """
     Ignite logger configuration.
     """
diff --git a/modules/ducktests/tests/ignitetest/services/utils/ignite_aware.py 
b/modules/ducktests/tests/ignitetest/services/utils/ignite_aware.py
index 9f374bb..fadbbe6 100644
--- a/modules/ducktests/tests/ignitetest/services/utils/ignite_aware.py
+++ b/modules/ducktests/tests/ignitetest/services/utils/ignite_aware.py
@@ -33,7 +33,7 @@ class IgniteAwareService(BackgroundThreadService, 
IgnitePersistenceAware, metacl
     """
 
     # pylint: disable=R0913
-    def __init__(self, context, num_nodes, properties, **kwargs):
+    def __init__(self, context, config, num_nodes, **kwargs):
         """
         **kwargs are params that passed to IgniteSpec
         """
@@ -43,9 +43,9 @@ class IgniteAwareService(BackgroundThreadService, 
IgnitePersistenceAware, metacl
         # IgniteAwareService uses IgnitePersistenceAware mixin to override 
default Service 'log' definition.
         self.log_level = "DEBUG"
 
-        self.properties = properties
+        self.config = config
 
-        self.spec = resolve_spec(self, context, **kwargs)
+        self.spec = resolve_spec(self, context, config, **kwargs)
 
     def start_node(self, node):
         self.init_persistent(node)
@@ -63,14 +63,27 @@ class IgniteAwareService(BackgroundThreadService, 
IgnitePersistenceAware, metacl
         """
         super().init_persistent(node)
 
-        node_config = 
self.spec.config().render(config_dir=self.PERSISTENT_ROOT,
-                                                work_dir=self.WORK_DIR,
-                                                properties=self.properties,
-                                                
consistent_id=node.account.externally_routable_ip)
+        node_config = self._prepare_config(node)
 
-        setattr(node, "consistent_id", node.account.externally_routable_ip)
         node.account.create_file(self.CONFIG_FILE, node_config)
 
+    def _prepare_config(self, node):
+        if not self.config.consistent_id:
+            config = 
self.config._replace(consistent_id=node.account.externally_routable_ip)
+        else:
+            config = self.config
+
+        config.discovery_spi.prepare_on_start(cluster=self)
+
+        node_config = 
self.spec.config_template.render(config_dir=self.PERSISTENT_ROOT, 
work_dir=self.WORK_DIR,
+                                                       config=config)
+
+        setattr(node, "consistent_id", node.account.externally_routable_ip)
+
+        self.logger.debug("Config for node %s: %s" % (node.account.hostname, 
node_config))
+
+        return node_config
+
     @abstractmethod
     def pids(self, node):
         """
@@ -81,7 +94,7 @@ class IgniteAwareService(BackgroundThreadService, 
IgnitePersistenceAware, metacl
 
     # pylint: disable=W0613
     def _worker(self, idx, node):
-        cmd = self.spec.command()
+        cmd = self.spec.command
 
         self.logger.debug("Attempting to start Application Service on %s with 
command: %s" % (str(node.account), cmd))
 
diff --git 
a/modules/ducktests/tests/ignitetest/services/utils/ignite_configuration/__init__.py
 
b/modules/ducktests/tests/ignitetest/services/utils/ignite_configuration/__init__.py
new file mode 100644
index 0000000..b9602e4
--- /dev/null
+++ 
b/modules/ducktests/tests/ignitetest/services/utils/ignite_configuration/__init__.py
@@ -0,0 +1,46 @@
+# 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.
+
+"""
+This module contains IgniteConfiguration classes and utilities.
+"""
+
+from typing import NamedTuple
+
+from ignitetest.services.utils.ignite_configuration.data_storage import 
DataStorageConfiguration
+from ignitetest.services.utils.ignite_configuration.discovery import 
DiscoverySpi, TcpDiscoverySpi
+from ignitetest.utils.version import IgniteVersion, DEV_BRANCH
+
+
+class IgniteConfiguration(NamedTuple):
+    """
+    Ignite configuration.
+    """
+    discovery_spi: DiscoverySpi = TcpDiscoverySpi()
+    version: IgniteVersion = DEV_BRANCH
+    cluster_state: str = 'ACTIVE'
+    client_mode: bool = False
+    consistent_id: str = None
+    failure_detection_timeout: int = 10000
+    properties: str = None
+    data_storage: DataStorageConfiguration = None
+    caches: list = []
+
+
+class IgniteClientConfiguration(IgniteConfiguration):
+    """
+    Ignite client configuration.
+    """
+    client_mode = True
diff --git 
a/modules/ducktests/tests/ignitetest/services/utils/ignite_configuration/cache.py
 
b/modules/ducktests/tests/ignitetest/services/utils/ignite_configuration/cache.py
new file mode 100644
index 0000000..cc58a69
--- /dev/null
+++ 
b/modules/ducktests/tests/ignitetest/services/utils/ignite_configuration/cache.py
@@ -0,0 +1,29 @@
+# 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
+
+"""
+This module contains classes and utilities for Ignite Cache configuration.
+"""
+from typing import NamedTuple
+
+
+class CacheConfiguration(NamedTuple):
+    """
+    Ignite Cache configuration.
+    """
+    name: str
+    cache_mode: str = 'PARTITIONED'
+    atomicity_mode: str = 'ATOMIC'
+    backups: int = 0
diff --git 
a/modules/ducktests/tests/ignitetest/services/utils/ignite_configuration/data_storage.py
 
b/modules/ducktests/tests/ignitetest/services/utils/ignite_configuration/data_storage.py
new file mode 100644
index 0000000..7b2999d
--- /dev/null
+++ 
b/modules/ducktests/tests/ignitetest/services/utils/ignite_configuration/data_storage.py
@@ -0,0 +1,38 @@
+# 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
+
+"""
+This module contains classes and utilities for Ignite DataStorage 
configuration.
+"""
+
+from typing import NamedTuple
+
+
+class DataRegionConfiguration(NamedTuple):
+    """
+    Ignite DataRegion Configuration
+    """
+    name: str = "default"
+    persistent: bool = False
+    init_size: int = 100 * 1024 * 1024
+    max_size: int = 512 * 1024 * 1024
+
+
+class DataStorageConfiguration(NamedTuple):
+    """
+    Ignite DataStorage configuration
+    """
+    default: DataRegionConfiguration = DataRegionConfiguration()
+    regions: list = []
diff --git 
a/modules/ducktests/tests/ignitetest/services/utils/ignite_configuration/discovery.py
 
b/modules/ducktests/tests/ignitetest/services/utils/ignite_configuration/discovery.py
new file mode 100644
index 0000000..9f38da5
--- /dev/null
+++ 
b/modules/ducktests/tests/ignitetest/services/utils/ignite_configuration/discovery.py
@@ -0,0 +1,141 @@
+# 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
+
+"""
+Module contains classes and utility methods to create discovery configuration 
for ignite nodes.
+"""
+
+from abc import ABCMeta, abstractmethod
+
+from ignitetest.services.utils.ignite_aware import IgniteAwareService
+from ignitetest.services.zk.zookeeper import ZookeeperService
+
+
+class DiscoverySpi(metaclass=ABCMeta):
+    """
+    Abstract class for DiscoverySpi.
+    """
+    @property
+    @abstractmethod
+    def type(self):
+        """
+        Type of DiscoverySPI.
+        """
+
+    @abstractmethod
+    def prepare_on_start(self, **kwargs):
+        """
+        Call if update before start is needed.
+        """
+
+
+class ZookeeperDiscoverySpi(DiscoverySpi):
+    """
+    ZookeeperDiscoverySpi.
+    """
+    def __init__(self, connection_string, root_path):
+        self.connection_string = connection_string
+        self.root_path = root_path
+
+    @property
+    def type(self):
+        return "ZOOKEEPER"
+
+    def prepare_on_start(self, **kwargs):
+        pass
+
+
+class TcpDiscoveryIpFinder(metaclass=ABCMeta):
+    """
+    Abstract class for TcpDiscoveryIpFinder.
+    """
+    @property
+    @abstractmethod
+    def type(self):
+        """
+        Type of TcpDiscoveryIpFinder.
+        """
+
+    @abstractmethod
+    def prepare_on_start(self, **kwargs):
+        """
+        Call if update before start is needed.
+        """
+
+
+class TcpDiscoveryVmIpFinder(TcpDiscoveryIpFinder):
+    """
+    IpFinder with static ips, obtained from cluster nodes.
+    """
+    def __init__(self, nodes=None):
+        self.addresses = TcpDiscoveryVmIpFinder.__get_addresses(nodes) if 
nodes else None
+
+    @property
+    def type(self):
+        return 'VM'
+
+    def prepare_on_start(self, **kwargs):
+        if not self.addresses:
+            cluster = kwargs.get('cluster')
+            self.addresses = 
TcpDiscoveryVmIpFinder.__get_addresses(cluster.nodes)
+
+    @staticmethod
+    def __get_addresses(nodes):
+        return [node.account.externally_routable_ip for node in nodes]
+
+
+class TcpDiscoverySpi(DiscoverySpi):
+    """
+    TcpDiscoverySpi.
+    """
+    def __init__(self, ip_finder=TcpDiscoveryVmIpFinder()):
+        self.ip_finder = ip_finder
+
+    @property
+    def type(self):
+        return 'TCP'
+
+    def prepare_on_start(self, **kwargs):
+        self.ip_finder.prepare_on_start(**kwargs)
+
+
+def from_ignite_cluster(cluster, subset=None):
+    """
+    Form TcpDiscoverySpi from cluster or its subset.
+    :param cluster: IgniteService cluster
+    :param subset: slice object (optional).
+    :return: TcpDiscoverySpi with static ip addresses.
+    """
+    assert isinstance(cluster, IgniteAwareService)
+
+    if subset:
+        assert isinstance(subset, slice)
+        nodes = cluster.nodes[subset]
+    else:
+        nodes = cluster.nodes
+
+    return TcpDiscoverySpi(ip_finder=TcpDiscoveryVmIpFinder(nodes))
+
+
+def from_zookeeper_cluster(cluster, root_path="/apacheIgnite"):
+    """
+    Form ZookeeperDiscoverySpi from zookeeper service cluster.
+    :param cluster: ZookeeperService cluster.
+    :param root_path: root ZNode path.
+    :return: ZookeeperDiscoverySpi.
+    """
+    assert isinstance(cluster, ZookeeperService)
+
+    return ZookeeperDiscoverySpi(cluster.connection_string(), 
root_path=root_path)
diff --git 
a/modules/ducktests/tests/ignitetest/services/utils/ignite_persistence.py 
b/modules/ducktests/tests/ignitetest/services/utils/ignite_persistence.py
index 27c3161..589b535 100644
--- a/modules/ducktests/tests/ignitetest/services/utils/ignite_persistence.py
+++ b/modules/ducktests/tests/ignitetest/services/utils/ignite_persistence.py
@@ -19,7 +19,7 @@ This module contains classes that represent persistent 
artifacts of tests
 
 import os
 
-from ignitetest.services.utils.ignite_config import IgniteLoggerConfig
+from ignitetest.services.utils.config_template import 
IgniteLoggerConfigTemplate
 
 
 class PersistenceAware:
@@ -66,5 +66,5 @@ class IgnitePersistenceAware(PersistenceAware):
         """
         super().init_persistent(node)
 
-        logger_config = IgniteLoggerConfig().render(work_dir=self.WORK_DIR)
+        logger_config = 
IgniteLoggerConfigTemplate().render(work_dir=self.WORK_DIR)
         node.account.create_file(self.LOG4J_CONFIG_FILE, logger_config)
diff --git a/modules/ducktests/tests/ignitetest/services/utils/ignite_spec.py 
b/modules/ducktests/tests/ignitetest/services/utils/ignite_spec.py
index 9cbfcc0..124fefb 100644
--- a/modules/ducktests/tests/ignitetest/services/utils/ignite_spec.py
+++ b/modules/ducktests/tests/ignitetest/services/utils/ignite_spec.py
@@ -20,16 +20,16 @@ This module contains Spec classes that describes config and 
command line to star
 import base64
 import importlib
 import json
+from abc import ABCMeta, abstractmethod
 
 from ignitetest.services.utils.ignite_path import IgnitePath
-from ignitetest.services.utils.ignite_config import IgniteClientConfig, 
IgniteServerConfig
-from ignitetest.utils.version import DEV_BRANCH, IgniteVersion
+from ignitetest.services.utils.config_template import 
IgniteClientConfigTemplate, IgniteServerConfigTemplate
+from ignitetest.utils.version import DEV_BRANCH
 
 from ignitetest.services.utils.ignite_persistence import IgnitePersistenceAware
 
 
-# pylint: disable=no-else-return
-def resolve_spec(service, context, **kwargs):
+def resolve_spec(service, context, config, **kwargs):
     """
     Resolve Spec classes for IgniteService and IgniteApplicationService
     """
@@ -47,41 +47,40 @@ def resolve_spec(service, context, **kwargs):
         return len(impl_filter) > 0
 
     if is_impl("IgniteService"):
-        return _resolve_spec("NodeSpec", ApacheIgniteNodeSpec)(**kwargs)
-    elif is_impl("IgniteApplicationService"):
-        return _resolve_spec("AppSpec", 
ApacheIgniteApplicationSpec)(context=context, **kwargs)
-    else:
-        raise Exception("There is no specification for class %s" % 
type(service))
+        return _resolve_spec("NodeSpec", ApacheIgniteNodeSpec)(config=config, 
**kwargs)
 
+    if is_impl("IgniteApplicationService"):
+        return _resolve_spec("AppSpec", 
ApacheIgniteApplicationSpec)(context=context, config=config, **kwargs)
 
-class IgniteSpec:
+    raise Exception("There is no specification for class %s" % type(service))
+
+
+class IgniteSpec(metaclass=ABCMeta):
     """
     This class is a basic Spec
     """
-    def __init__(self, version, project, client_mode, jvm_opts):
-        if isinstance(version, IgniteVersion):
-            self.version = version
-        else:
-            self.version = IgniteVersion(version)
-
+    def __init__(self, config, project, jvm_opts):
+        self.version = config.version
         self.path = IgnitePath(self.version, project)
         self.envs = {}
         self.jvm_opts = jvm_opts or []
-        self.client_mode = client_mode
+        self.config = config
 
-    def config(self):
+    @property
+    def config_template(self):
         """
         :return: config that service will use to start on a node
         """
-        if self.client_mode:
-            return IgniteClientConfig()
-        return IgniteServerConfig()
+        if self.config.client_mode:
+            return IgniteClientConfigTemplate()
+        return IgniteServerConfigTemplate()
 
+    @property
+    @abstractmethod
     def command(self):
         """
         :return: string that represents command to run service on a node
         """
-        raise NotImplementedError()
 
     def _envs(self):
         """
@@ -102,14 +101,13 @@ class IgniteNodeSpec(IgniteSpec, IgnitePersistenceAware):
     """
     Spec to run ignite node
     """
-
+    @property
     def command(self):
-        cmd = "%s %s %s %s 1>> %s 2>> %s &" % \
+        cmd = "%s %s %s %s 2>&1 | tee -a %s &" % \
               (self._envs(),
                self.path.script("ignite.sh"),
                self._jvm_opts(),
                self.CONFIG_FILE,
-               self.STDOUT_STDERR_CAPTURE,
                self.STDOUT_STDERR_CAPTURE)
 
         return cmd
@@ -126,21 +124,18 @@ class IgniteApplicationSpec(IgniteSpec, 
IgnitePersistenceAware):
     def _app_args(self):
         return ",".join(self.args)
 
+    @property
     def command(self):
-        cmd = "%s %s %s %s 1>> %s 2>> %s &" % \
+        cmd = "%s %s %s %s 2>&1 | tee -a %s &" % \
               (self._envs(),
                self.path.script("ignite.sh"),
                self._jvm_opts(),
                self._app_args(),
-               self.STDOUT_STDERR_CAPTURE,
                self.STDOUT_STDERR_CAPTURE)
 
         return cmd
 
 
-###
-
-
 class ApacheIgniteNodeSpec(IgniteNodeSpec, IgnitePersistenceAware):
     """
     Implementation IgniteNodeSpec for Apache Ignite project
@@ -208,5 +203,5 @@ class ApacheIgniteApplicationSpec(IgniteApplicationSpec, 
IgnitePersistenceAware)
             aws = self.path.module("aws")
             return self.context.cluster.nodes[0].account.ssh_capture(
                 "ls -d %s/* | grep jackson | tr '\n' ':' | sed 's/.$//'" % aws)
-        else:
-            return []
+
+        return []
diff --git 
a/modules/ducktests/tests/ignitetest/services/utils/templates/cache_macro.j2 
b/modules/ducktests/tests/ignitetest/services/utils/templates/cache_macro.j2
new file mode 100644
index 0000000..d227369
--- /dev/null
+++ b/modules/ducktests/tests/ignitetest/services/utils/templates/cache_macro.j2
@@ -0,0 +1,34 @@
+{#
+ 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.
+#}
+
+{% macro cache_configs(caches) %}
+    {% if caches %}
+        <property name="cacheConfiguration">
+            <list>
+                {% for cache in caches %}
+                <bean 
class="org.apache.ignite.configuration.CacheConfiguration">
+                    <property name="name" value="{{ cache.name }}"/>
+                    {% if cache.cache_mode == 'PARTITIONED' %}
+                        <property name="backups" value="{{ cache.backups or 0 
}}"/>
+                    {% endif %}
+                    <property name="atomicityMode" value="{{ 
cache.atomicity_mode or 'ATOMIC' }}"/>
+                </bean>
+                {% endfor %}
+            </list>
+        </property>
+    {% endif %}
+{% endmacro %}
diff --git 
a/modules/ducktests/tests/ignitetest/services/utils/templates/datastorage_macro.j2
 
b/modules/ducktests/tests/ignitetest/services/utils/templates/datastorage_macro.j2
new file mode 100644
index 0000000..1c2b462
--- /dev/null
+++ 
b/modules/ducktests/tests/ignitetest/services/utils/templates/datastorage_macro.j2
@@ -0,0 +1,46 @@
+{#
+ 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.
+#}
+
+{% macro data_storage(config) %}
+    {% if config %}
+        <property name="dataStorageConfiguration">
+            <bean 
class="org.apache.ignite.configuration.DataStorageConfiguration">
+                <property name="defaultDataRegionConfiguration">
+                    {{ data_region(config.default) }}
+                </property>
+                {% if config.regions %}
+                    <property name="dataRegionConfigurations">
+                        <list>
+                        {% for region in config.regions %}
+                            {{ data_region(region) }}
+                        {% endfor %}
+                        </list>
+                    </property>
+                {% endif %}
+            </bean>
+        </property>
+    {% endif %}
+{% endmacro %}
+
+{% macro data_region(config) %}
+    <bean class="org.apache.ignite.configuration.DataRegionConfiguration">
+        <property name="name" value="{{ config.name }}"/>
+        <property name="persistenceEnabled" value="{{ config.persistent }}"/>
+        <property name="initialSize" value="{{ config.init_size }}"/>
+        <property name="maxSize" value="{{ config.max_size }}"/>
+    </bean>
+{% endmacro %}
diff --git 
a/modules/ducktests/tests/ignitetest/services/utils/templates/discovery_macro.j2
 
b/modules/ducktests/tests/ignitetest/services/utils/templates/discovery_macro.j2
new file mode 100644
index 0000000..fdd632a
--- /dev/null
+++ 
b/modules/ducktests/tests/ignitetest/services/utils/templates/discovery_macro.j2
@@ -0,0 +1,57 @@
+{#
+ 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.
+#}
+
+{% macro ip_finder(finder) %}
+    {% if finder %}
+        <property name="ipFinder">
+            {% if finder.type == 'VM' %}
+                <bean 
class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">
+                    <property name="addresses">
+                        <list>
+                            {% for address in finder.addresses %}
+                                <value>{{ address }}</value>
+                            {% endfor %}
+                        </list>
+                    </property>
+                </bean>
+            {% endif %}
+        </property>
+    {% endif %}
+{% endmacro %}
+
+{% macro zookeeper_discovery_spi(spi) %}
+    <bean class="org.apache.ignite.spi.discovery.zk.ZookeeperDiscoverySpi">
+        <property name="zkConnectionString" value="{{ spi.connection_string 
}}"/>
+        <property name="zkRootPath" value="{{ spi.root_path }}"/>
+    </bean>
+{% endmacro %}
+
+{% macro tcp_discovery_spi(spi) %}
+    <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
+        {{ ip_finder(spi.ip_finder) }}
+    </bean>
+{% endmacro %}
+
+{% macro discovery_spi(spi) %}
+    <property name="discoverySpi">
+        {% if spi.type == 'TCP' %}
+            {{ tcp_discovery_spi(spi) }}
+        {% elif spi.type == 'ZOOKEEPER' %}
+            {{  zookeeper_discovery_spi(spi) }}
+        {% endif %}
+    </property>
+{% endmacro %}
diff --git 
a/modules/ducktests/tests/ignitetest/services/utils/config/ignite.xml.j2 
b/modules/ducktests/tests/ignitetest/services/utils/templates/ignite.xml.j2
similarity index 65%
rename from 
modules/ducktests/tests/ignitetest/services/utils/config/ignite.xml.j2
rename to 
modules/ducktests/tests/ignitetest/services/utils/templates/ignite.xml.j2
index f03ba17..86abd35 100644
--- a/modules/ducktests/tests/ignitetest/services/utils/config/ignite.xml.j2
+++ b/modules/ducktests/tests/ignitetest/services/utils/templates/ignite.xml.j2
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
-<!--
+{#
  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.
@@ -15,7 +15,12 @@
  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.
--->
+#}
+
+{% import 'discovery_macro.j2' as disco_utils %}
+{% import 'cache_macro.j2' as cache_utils %}
+{% import 'datastorage_macro.j2' as datastorage_utils %}
+{% import 'misc_macro.j2' as misc_utils %}
 
 <beans xmlns="http://www.springframework.org/schema/beans";
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
@@ -29,12 +34,20 @@
             </bean>
         </property>
 
-        <property name="clientMode" value="{{ client_mode or False | lower 
}}"/>
-        {% if consistent_id %}
-            <property name="consistentId" value="{{ consistent_id }}"/>
-        {% endif %}
-        {% if properties %}
-            {{ properties }}
+        <property name="clientMode" value="{{ config.client_mode or False | 
lower }}"/>
+        <property name="consistentId" value="{{ config.consistent_id }}"/>
+        <property name="failureDetectionTimeout" value="{{ 
config.failure_detection_timeout }}"/>
+
+        {{ misc_utils.cluster_state(config.cluster_state, config.version) }}
+
+        {{ disco_utils.discovery_spi(config.discovery_spi) }}
+
+        {{ datastorage_utils.data_storage(config.data_storage) }}
+
+        {{ cache_utils.cache_configs(config.caches) }}
+
+        {% if config.properties %}
+            {{ config.properties }}
         {% endif %}
     </bean>
 </beans>
diff --git 
a/modules/ducktests/tests/ignitetest/services/utils/config/log4j.xml.j2 
b/modules/ducktests/tests/ignitetest/services/utils/templates/log4j.xml.j2
similarity index 100%
rename from 
modules/ducktests/tests/ignitetest/services/utils/config/log4j.xml.j2
rename to 
modules/ducktests/tests/ignitetest/services/utils/templates/log4j.xml.j2
diff --git 
a/modules/ducktests/tests/ignitetest/services/utils/templates/misc_macro.j2 
b/modules/ducktests/tests/ignitetest/services/utils/templates/misc_macro.j2
new file mode 100644
index 0000000..892453b
--- /dev/null
+++ b/modules/ducktests/tests/ignitetest/services/utils/templates/misc_macro.j2
@@ -0,0 +1,24 @@
+{#
+ 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.
+#}
+
+{% macro cluster_state(state, version) %}
+    {% if version > "2.9.0" %}
+        <property name="clusterStateOnStart" value="{{ state }}"/>
+    {%  else %}
+        <property name="activeOnStart" value="{{ 'false' if state == 
'INACTIVE' else 'true'}}"/>
+    {% endif %}
+{% endmacro %}
diff --git 
a/modules/ducktests/tests/ignitetest/tests/add_node_rebalance_test.py 
b/modules/ducktests/tests/ignitetest/tests/add_node_rebalance_test.py
index a1d90b8..b162d2e 100644
--- a/modules/ducktests/tests/ignitetest/tests/add_node_rebalance_test.py
+++ b/modules/ducktests/tests/ignitetest/tests/add_node_rebalance_test.py
@@ -22,6 +22,8 @@ from ducktape.mark.resource import cluster
 
 from ignitetest.services.ignite import IgniteService
 from ignitetest.services.ignite_app import IgniteApplicationService
+from ignitetest.services.utils.ignite_configuration import IgniteConfiguration
+from ignitetest.services.utils.ignite_configuration.discovery import 
from_ignite_cluster
 from ignitetest.utils.ignite_test import IgniteTest
 from ignitetest.utils.version import DEV_BRANCH, IgniteVersion, LATEST
 
@@ -36,12 +38,6 @@ class AddNodeRebalanceTest(IgniteTest):
     DATA_AMOUNT = 1000000
     REBALANCE_TIMEOUT = 60
 
-    def setUp(self):
-        pass
-
-    def teardown(self):
-        pass
-
     @cluster(num_nodes=NUM_NODES + 1)
     @parametrize(version=str(DEV_BRANCH))
     @parametrize(version=str(LATEST))
@@ -56,20 +52,22 @@ class AddNodeRebalanceTest(IgniteTest):
 
         self.stage("Start Ignite nodes")
 
-        ignites = IgniteService(self.test_context, 
num_nodes=AddNodeRebalanceTest.NUM_NODES - 1, version=ignite_version)
+        node_config = IgniteConfiguration(version=ignite_version)
 
+        ignites = IgniteService(self.test_context, config=node_config, 
num_nodes=self.NUM_NODES - 1)
         ignites.start()
 
         self.stage("Starting DataGenerationApplication")
 
         # This client just put some data to the cache.
-        IgniteApplicationService(self.test_context,
+        app_config = node_config._replace(client_mode=True, 
discovery_spi=from_ignite_cluster(ignites))
+        IgniteApplicationService(self.test_context, config=app_config,
                                  
java_class_name="org.apache.ignite.internal.ducktest.tests.DataGenerationApplication",
-                                 version=ignite_version,
                                  params={"cacheName": "test-cache", "range": 
self.DATA_AMOUNT},
                                  timeout_sec=self.PRELOAD_TIMEOUT).run()
 
-        ignite = IgniteService(self.test_context, num_nodes=1, 
version=ignite_version)
+        ignite = IgniteService(self.test_context, 
node_config._replace(discovery_spi=from_ignite_cluster(ignites)),
+                               num_nodes=1)
 
         self.stage("Starting Ignite node")
 
diff --git a/modules/ducktests/tests/ignitetest/tests/cellular_affinity_test.py 
b/modules/ducktests/tests/ignitetest/tests/cellular_affinity_test.py
index 78d3eba..6b1e664 100644
--- a/modules/ducktests/tests/ignitetest/tests/cellular_affinity_test.py
+++ b/modules/ducktests/tests/ignitetest/tests/cellular_affinity_test.py
@@ -23,8 +23,10 @@ from jinja2 import Template
 
 from ignitetest.services.ignite import IgniteService
 from ignitetest.services.ignite_app import IgniteApplicationService
+from ignitetest.services.utils.ignite_configuration import 
IgniteConfiguration, IgniteClientConfiguration
+from ignitetest.services.utils.ignite_configuration.discovery import 
from_ignite_cluster
 from ignitetest.utils.ignite_test import IgniteTest
-from ignitetest.utils.version import DEV_BRANCH
+from ignitetest.utils.version import DEV_BRANCH, IgniteVersion
 
 
 # pylint: disable=W0223
@@ -68,41 +70,36 @@ class CellularAffinity(IgniteTest):
                     attr=CellularAffinity.ATTRIBUTE,
                     cacheName=CellularAffinity.CACHE_NAME)
 
-    def setUp(self):
-        pass
-
-    def teardown(self):
-        pass
-
     @cluster(num_nodes=NUM_NODES * 3 + 1)
     @parametrize(version=str(DEV_BRANCH))
     def test(self, version):
         """
         Test Cellular Affinity scenario (partition distribution).
         """
-        self.start_cell(version, ['-D' + CellularAffinity.ATTRIBUTE + '=1'])
-        self.start_cell(version, ['-D' + CellularAffinity.ATTRIBUTE + '=2'])
-        self.start_cell(version, ['-D' + CellularAffinity.ATTRIBUTE + '=XXX', 
'-DRANDOM=42'])
+        cell1 = self.start_cell(version, ['-D' + CellularAffinity.ATTRIBUTE + 
'=1'])
+        self.start_cell(version, ['-D' + CellularAffinity.ATTRIBUTE + '=2'], 
joined_cluster=cell1)
+        self.start_cell(version, ['-D' + CellularAffinity.ATTRIBUTE + '=XXX', 
'-DRANDOM=42'], joined_cluster=cell1)
 
         checker = IgniteApplicationService(
             self.test_context,
+            IgniteClientConfiguration(version=IgniteVersion(version), 
discovery_spi=from_ignite_cluster(cell1)),
             
java_class_name="org.apache.ignite.internal.ducktest.tests.cellular_affinity_test.DistributionChecker",
             params={"cacheName": CellularAffinity.CACHE_NAME,
                     "attr": CellularAffinity.ATTRIBUTE,
-                    "nodesPerCell": self.NUM_NODES},
-            version=version)
+                    "nodesPerCell": self.NUM_NODES})
 
         checker.run()
 
-    def start_cell(self, ignite_version, jvm_opts):
+    def start_cell(self, version, jvm_opts, joined_cluster=None):
         """
         Starts cell.
         """
-        ignites = IgniteService(
-            self.test_context,
-            num_nodes=CellularAffinity.NUM_NODES,
-            version=ignite_version,
-            properties=self.properties(),
-            jvm_opts=jvm_opts)
+        config = IgniteConfiguration(version=IgniteVersion(version), 
properties=self.properties())
+        if joined_cluster:
+            config = 
config._replace(discovery_spi=from_ignite_cluster(joined_cluster))
+
+        ignites = IgniteService(self.test_context, config, 
num_nodes=CellularAffinity.NUM_NODES, jvm_opts=jvm_opts)
 
         ignites.start()
+
+        return ignites
diff --git a/modules/ducktests/tests/ignitetest/tests/control_utility_test.py 
b/modules/ducktests/tests/ignitetest/tests/control_utility_test.py
index 63c87ac..a4afd09 100644
--- a/modules/ducktests/tests/ignitetest/tests/control_utility_test.py
+++ b/modules/ducktests/tests/ignitetest/tests/control_utility_test.py
@@ -19,10 +19,12 @@ This module contains control.sh utility tests.
 from ducktape.mark import parametrize
 from ducktape.mark.resource import cluster
 from ducktape.utils.util import wait_until
-from jinja2 import Template
 
 from ignitetest.services.ignite import IgniteService
 from ignitetest.services.utils.control_utility import ControlUtility, 
ControlUtilityError
+from ignitetest.services.utils.ignite_configuration import 
IgniteConfiguration, DataStorageConfiguration
+from ignitetest.services.utils.ignite_configuration.data_storage import 
DataRegionConfiguration
+from ignitetest.services.utils.ignite_configuration.discovery import 
from_ignite_cluster
 from ignitetest.utils import version_if
 from ignitetest.utils.ignite_test import IgniteTest
 from ignitetest.utils.version import DEV_BRANCH, LATEST_2_8, IgniteVersion, 
LATEST_2_7, V_2_8_0
@@ -35,36 +37,6 @@ class BaselineTests(IgniteTest):
     """
     NUM_NODES = 3
 
-    CONFIG_TEMPLATE = """
-        {% if version > "2.9.0" %}
-            <property name="clusterStateOnStart" value="INACTIVE"/>
-        {%  else %}
-            <property name="activeOnStart" value="false"/>
-        {% endif %}
-        <property name="dataStorageConfiguration">
-            <bean 
class="org.apache.ignite.configuration.DataStorageConfiguration">
-                <property name="defaultDataRegionConfiguration">
-                    <bean 
class="org.apache.ignite.configuration.DataRegionConfiguration">
-                        <property name="persistenceEnabled" value="true"/>
-                        <property name="maxSize" value="#{100L * 1024 * 
1024}"/>
-                    </bean>
-                </property>
-            </bean>
-        </property>
-    """
-
-    @staticmethod
-    def properties(version):
-        """
-        Render properties for ignite node configuration.
-        """
-        return Template(BaselineTests.CONFIG_TEMPLATE) \
-            .render(version=version)
-
-    def __init__(self, test_context):
-        super().__init__(test_context)
-        self.servers = None
-
     @cluster(num_nodes=NUM_NODES)
     @parametrize(version=str(DEV_BRANCH))
     @parametrize(version=str(LATEST_2_8))
@@ -74,19 +46,19 @@ class BaselineTests(IgniteTest):
         Test baseline set.
         """
         blt_size = self.NUM_NODES - 2
-        self.servers = self.__start_ignite_nodes(version, blt_size)
+        servers = self.__start_ignite_nodes(version, blt_size)
 
-        control_utility = ControlUtility(self.servers, self.test_context)
+        control_utility = ControlUtility(servers, self.test_context)
         control_utility.activate()
 
         # Check baseline of activated cluster.
         baseline = control_utility.baseline()
         self.__check_baseline_size(baseline, blt_size)
-        self.__check_nodes_in_baseline(self.servers.nodes, baseline)
+        self.__check_nodes_in_baseline(servers.nodes, baseline)
 
-        # Set baseline using list of conststent ids.
-        new_node = self.__start_ignite_nodes(version, 1)
-        control_utility.set_baseline(self.servers.nodes + new_node.nodes)
+        # Set baseline using list of consisttent ids.
+        new_node = self.__start_ignite_nodes(version, 1, join_cluster=servers)
+        control_utility.set_baseline(servers.nodes + new_node.nodes)
         blt_size += 1
 
         baseline = control_utility.baseline()
@@ -94,7 +66,7 @@ class BaselineTests(IgniteTest):
         self.__check_nodes_in_baseline(new_node.nodes, baseline)
 
         # Set baseline using topology version.
-        new_node = self.__start_ignite_nodes(version, 1)
+        new_node = self.__start_ignite_nodes(version, 1, join_cluster=servers)
         _, version, _ = control_utility.cluster_state()
         control_utility.set_baseline(version)
         blt_size += 1
@@ -112,14 +84,14 @@ class BaselineTests(IgniteTest):
         Test add and remove nodes from baseline.
         """
         blt_size = self.NUM_NODES - 1
-        self.servers = self.__start_ignite_nodes(version, blt_size)
+        servers = self.__start_ignite_nodes(version, blt_size)
 
-        control_utility = ControlUtility(self.servers, self.test_context)
+        control_utility = ControlUtility(servers, self.test_context)
 
         control_utility.activate()
 
         # Add node to baseline.
-        new_node = self.__start_ignite_nodes(version, 1)
+        new_node = self.__start_ignite_nodes(version, 1, join_cluster=servers)
         control_utility.add_to_baseline(new_node.nodes)
         blt_size += 1
 
@@ -138,7 +110,7 @@ class BaselineTests(IgniteTest):
         # Remove of offline node from baseline.
         new_node.stop()
 
-        self.servers.await_event("Node left topology", timeout_sec=30, 
from_the_beginning=True)
+        servers.await_event("Node left topology", timeout_sec=30, 
from_the_beginning=True)
 
         control_utility.remove_from_baseline(new_node.nodes)
         blt_size -= 1
@@ -155,9 +127,9 @@ class BaselineTests(IgniteTest):
         """
         Test activate and deactivate cluster.
         """
-        self.servers = self.__start_ignite_nodes(version, self.NUM_NODES)
+        servers = self.__start_ignite_nodes(version, self.NUM_NODES)
 
-        control_utility = ControlUtility(self.servers, self.test_context)
+        control_utility = ControlUtility(servers, self.test_context)
 
         control_utility.activate()
 
@@ -180,14 +152,14 @@ class BaselineTests(IgniteTest):
         Test activate and deactivate cluster.
         """
         blt_size = self.NUM_NODES - 2
-        self.servers = self.__start_ignite_nodes(version, blt_size)
+        servers = self.__start_ignite_nodes(version, blt_size)
 
-        control_utility = ControlUtility(self.servers, self.test_context)
+        control_utility = ControlUtility(servers, self.test_context)
         control_utility.activate()
 
         # Add node.
         control_utility.enable_baseline_auto_adjust(2000)
-        new_node = self.__start_ignite_nodes(version, 1)
+        new_node = self.__start_ignite_nodes(version, 1, join_cluster=servers)
         blt_size += 1
 
         wait_until(lambda: len(control_utility.baseline()) == blt_size, 
timeout_sec=5)
@@ -198,7 +170,7 @@ class BaselineTests(IgniteTest):
         # Add node when auto adjust disabled.
         control_utility.disable_baseline_auto_adjust()
         old_topology = control_utility.cluster_state().topology_version
-        new_node = self.__start_ignite_nodes(version, 1)
+        new_node = self.__start_ignite_nodes(version, 1, join_cluster=servers)
 
         wait_until(lambda: control_utility.cluster_state().topology_version != 
old_topology, timeout_sec=5)
         baseline = control_utility.baseline()
@@ -222,11 +194,20 @@ class BaselineTests(IgniteTest):
     def __check_baseline_size(baseline, size):
         assert len(baseline) == size, 'Unexpected size of baseline %d, %d 
expected' % (len(baseline), size)
 
-    def __start_ignite_nodes(self, version, num_nodes, timeout_sec=180):
-        ignite_version = IgniteVersion(version)
+    def __start_ignite_nodes(self, version, num_nodes, timeout_sec=60, 
join_cluster=None):
+        config = IgniteConfiguration(
+            cluster_state="INACTIVE",
+            version=IgniteVersion(version),
+            data_storage=DataStorageConfiguration(
+                default=DataRegionConfiguration(name='persistent', 
persistent=True),
+                regions=[DataRegionConfiguration(name='in-memory', 
persistent=False, max_size=100 * 1024 * 1024)]
+            )
+        )
+
+        if join_cluster:
+            config._replace(discovery_spi=from_ignite_cluster(join_cluster))
 
-        servers = IgniteService(self.test_context, num_nodes=num_nodes, 
version=ignite_version,
-                                properties=self.properties(ignite_version))
+        servers = IgniteService(self.test_context, config=config, 
num_nodes=num_nodes)
 
         servers.start(timeout_sec=timeout_sec)
 
diff --git a/modules/ducktests/tests/ignitetest/tests/discovery_test.py 
b/modules/ducktests/tests/ignitetest/tests/discovery_test.py
index 63f6ef8..6daaa2d 100644
--- a/modules/ducktests/tests/ignitetest/tests/discovery_test.py
+++ b/modules/ducktests/tests/ignitetest/tests/discovery_test.py
@@ -20,18 +20,33 @@ Module contains discovery tests.
 import random
 import re
 from datetime import datetime
+from time import monotonic
+from typing import NamedTuple
 
 from ducktape.mark import matrix
 from ducktape.mark.resource import cluster
-from jinja2 import Template
 
 from ignitetest.services.ignite import IgniteAwareService
 from ignitetest.services.ignite import IgniteService
 from ignitetest.services.ignite_app import IgniteApplicationService
+from ignitetest.services.utils.ignite_configuration import IgniteConfiguration
+from ignitetest.services.utils.ignite_configuration.discovery import 
from_zookeeper_cluster, from_ignite_cluster, \
+    TcpDiscoverySpi
 from ignitetest.services.utils.time_utils import epoch_mills
 from ignitetest.services.zk.zookeeper import ZookeeperService
 from ignitetest.utils.ignite_test import IgniteTest
-from ignitetest.utils.version import DEV_BRANCH, LATEST_2_8
+from ignitetest.utils.version import DEV_BRANCH, LATEST_2_8, IgniteVersion
+
+
+class DiscoveryTestConfig(NamedTuple):
+    """
+    Configuration for DiscoveryTest.
+    """
+    version: IgniteVersion
+    nodes_to_kill: int = 1
+    kill_coordinator: bool = False
+    with_load: bool = False
+    with_zk: bool = False
 
 
 # pylint: disable=W0223
@@ -42,191 +57,167 @@ class DiscoveryTest(IgniteTest):
     2. Kill random node.
     3. Wait that survived node detects node failure.
     """
-    class Config:
-        """
-        Configuration for DiscoveryTest.
-        """
-        def __init__(self, nodes_to_kill=1, kill_coordinator=False, 
with_load=False):
-            self.nodes_to_kill = nodes_to_kill
-            self.kill_coordinator = kill_coordinator
-            self.with_load = with_load
-
     NUM_NODES = 7
 
     FAILURE_DETECTION_TIMEOUT = 2000
 
     DATA_AMOUNT = 100000
 
-    CONFIG_TEMPLATE = """
-    <property name="failureDetectionTimeout" value="{{ 
failure_detection_timeout }}"/>
-    {% if zookeeper_settings %}
-        {% with zk = zookeeper_settings %}
-        <property name="discoverySpi">
-            <bean 
class="org.apache.ignite.spi.discovery.zk.ZookeeperDiscoverySpi">
-                <property name="zkConnectionString" value="{{ 
zk.connection_string }}"/>
-                <property name="zkRootPath" value="{{ zk.root_path or 
'/apacheIgnite' }}"/>
-            </bean>
-        </property>
-        {% endwith %}
-    {% endif %}
-    """
-
-    def __init__(self, test_context):
-        super().__init__(test_context=test_context)
-        self.zk_quorum = None
-        self.servers = None
-        self.loader = None
-
     @cluster(num_nodes=NUM_NODES)
-    @matrix(ignite_version=[str(DEV_BRANCH), str(LATEST_2_8)],
+    @matrix(version=[str(DEV_BRANCH), str(LATEST_2_8)],
             kill_coordinator=[False, True],
             nodes_to_kill=[1, 2],
             with_load=[False, True])
-    def test_tcp(self, ignite_version, kill_coordinator, nodes_to_kill, 
with_load):
+    def test_node_fail_tcp(self, version, kill_coordinator, nodes_to_kill, 
with_load):
         """
         Test nodes failure scenario with TcpDiscoverySpi.
         """
-        config = DiscoveryTest.Config(nodes_to_kill, kill_coordinator, 
with_load)
+        test_config = DiscoveryTestConfig(version=IgniteVersion(version), 
kill_coordinator=kill_coordinator,
+                                          nodes_to_kill=nodes_to_kill, 
with_load=with_load, with_zk=False)
 
-        return self.__simulate_nodes_failure(ignite_version, 
self.__properties(), None, config)
+        return self._perform_node_fail_scenario(test_config)
 
     @cluster(num_nodes=NUM_NODES + 3)
-    @matrix(ignite_version=[str(DEV_BRANCH), str(LATEST_2_8)],
+    @matrix(version=[str(DEV_BRANCH), str(LATEST_2_8)],
             kill_coordinator=[False, True],
             nodes_to_kill=[1, 2],
             with_load=[False, True])
-    def test_zk(self, ignite_version, kill_coordinator, nodes_to_kill, 
with_load):
+    def test_node_fail_zk(self, version, kill_coordinator, nodes_to_kill, 
with_load):
         """
         Test node failure scenario with ZooKeeperSpi.
         """
-        config = DiscoveryTest.Config(nodes_to_kill, kill_coordinator, 
with_load)
+        test_config = DiscoveryTestConfig(version=IgniteVersion(version), 
kill_coordinator=kill_coordinator,
+                                          nodes_to_kill=nodes_to_kill, 
with_load=with_load, with_zk=True)
 
-        self.__start_zk_quorum()
+        return self._perform_node_fail_scenario(test_config)
 
-        properties = self.__zk_properties(self.zk_quorum.connection_string())
-        modules = ["zookeeper"]
+    def _perform_node_fail_scenario(self, test_config):
+        modules = ['zookeeper'] if test_config.with_zk else None
 
-        return self.__simulate_nodes_failure(ignite_version, properties, 
modules, config)
+        if test_config.with_zk:
+            zk_quorum = start_zookeeper(self.test_context, 3)
 
-    def setUp(self):
-        pass
+            discovery_spi = from_zookeeper_cluster(zk_quorum)
+        else:
+            discovery_spi = TcpDiscoverySpi()
 
-    def teardown(self):
-        if self.loader:
-            self.loader.stop()
+        ignite_config = IgniteConfiguration(
+            version=test_config.version,
+            discovery_spi=discovery_spi,
+            failure_detection_timeout=self.FAILURE_DETECTION_TIMEOUT
+        )
 
-        if self.servers:
-            self.servers.stop()
+        servers, start_servers_sec = start_servers(self.test_context, 
self.NUM_NODES - 1, ignite_config, modules)
 
-        if self.zk_quorum:
-            self.zk_quorum.stop()
+        if test_config.with_load:
+            load_config = ignite_config._replace(client_mode=True) if 
test_config.with_zk else \
+                ignite_config._replace(client_mode=True, 
discovery_spi=from_ignite_cluster(servers))
 
-    def __simulate_nodes_failure(self, version, properties, modules, config):
-        if config.nodes_to_kill < 1:
-            return {"No nodes to kill": "Nothing to do"}
+            start_load_app(self.test_context, ignite_config=load_config, 
data_amount=self.DATA_AMOUNT, modules=modules)
 
-        self.servers = IgniteService(
-            self.test_context,
-            num_nodes=self.NUM_NODES - 1,
-            modules=modules,
-            properties=properties,
-            version=version)
-
-        time_holder = self.monotonic()
-
-        self.servers.start()
+        data = simulate_nodes_failure(servers, test_config.kill_coordinator, 
test_config.nodes_to_kill)
+        data['Ignite cluster start time (s)'] = start_servers_sec
+        return data
 
-        data = {'Ignite cluster start time (s)': round(self.monotonic() - 
time_holder, 1)}
 
-        failed_nodes, survived_node = 
self.__choose_node_to_kill(config.kill_coordinator, config.nodes_to_kill)
+def start_zookeeper(test_context, num_nodes):
+    """
+    Start zookeeper cluster.
+    """
+    zk_quorum = ZookeeperService(test_context, num_nodes)
+    zk_quorum.start()
+    return zk_quorum
 
-        ids_to_wait = [node.discovery_info().node_id for node in failed_nodes]
 
-        if config.with_load:
-            self.__start_loading(version, properties, modules)
+def start_servers(test_context, num_nodes, ignite_config, modules=None):
+    """
+    Start ignite servers.
+    """
+    servers = IgniteService(test_context, config=ignite_config, 
num_nodes=num_nodes, modules=modules,
+                            # mute spam in log.
+                            
jvm_opts=["-DIGNITE_DUMP_THREADS_ON_FAILURE=false"])
 
-        first_terminated = self.servers.stop_nodes_async(failed_nodes, 
clean_shutdown=False, wait_for_stop=False)
+    start = monotonic()
+    servers.start()
+    return servers, round(monotonic() - start, 1)
 
-        # Keeps dates of logged node failures.
-        logged_timestamps = []
 
-        for failed_id in ids_to_wait:
-            self.servers.await_event_on_node(self.__failed_pattern(failed_id), 
survived_node, 20,
-                                             from_the_beginning=True, 
backoff_sec=0.1)
+def start_load_app(test_context, ignite_config, data_amount, modules=None):
+    """
+    Start loader application.
+    """
+    loader = IgniteApplicationService(
+        test_context,
+        config=ignite_config,
+        
java_class_name="org.apache.ignite.internal.ducktest.tests.ContinuousDataLoadApplication",
+        modules=modules,
+        # mute spam in log.
+        jvm_opts=["-DIGNITE_DUMP_THREADS_ON_FAILURE=false"],
+        params={"cacheName": "test-cache", "range": data_amount})
 
-            _, stdout, _ = survived_node.account.ssh_client.exec_command(
-                "grep '%s' %s" % (self.__failed_pattern(failed_id), 
IgniteAwareService.STDOUT_STDERR_CAPTURE))
+    loader.start()
 
-            logged_timestamps.append(
-                datetime.strptime(re.match("^\\[[^\\[]+\\]", 
stdout.read().decode("utf-8")).group(),
-                                  "[%Y-%m-%d %H:%M:%S,%f]"))
 
-        logged_timestamps.sort(reverse=True)
+def failed_pattern(failed_node_id):
+    """
+    Failed node pattern in log
+    """
+    return "Node FAILED: .\\{1,\\}Node \\[id=" + failed_node_id
 
-        self.__store_results(data, logged_timestamps, first_terminated[1])
 
-        data['Nodes failed'] = len(failed_nodes)
+def choose_node_to_kill(servers, kill_coordinator, nodes_to_kill):
+    """Choose node to kill during test"""
+    assert nodes_to_kill > 0, "   No nodes to kill passed. Check the 
parameters."
 
-        return data
+    nodes = servers.nodes
+    coordinator = nodes[0].discovery_info().coordinator
+    to_kill = []
 
-    @staticmethod
-    def __store_results(data, logged_timestamps, first_kill_time):
-        first_kill_time = epoch_mills(first_kill_time)
+    if kill_coordinator:
+        to_kill.append(next(node for node in nodes if 
node.discovery_info().node_id == coordinator))
+        nodes_to_kill -= 1
 
-        detection_delay = epoch_mills(logged_timestamps[0]) - first_kill_time
+    if nodes_to_kill > 0:
+        choice = random.sample([n for n in nodes if n.discovery_info().node_id 
!= coordinator], nodes_to_kill)
+        to_kill.extend([choice] if not isinstance(choice, list) else choice)
 
-        data['Detection of node(s) failure (ms)'] = detection_delay
-        data['All detection delays (ms):'] = str([epoch_mills(ts) - 
first_kill_time for ts in logged_timestamps])
+    survive = random.choice([node for node in servers.nodes if node not in 
to_kill])
 
-    @staticmethod
-    def __failed_pattern(failed_node_id):
-        return "Node FAILED: .\\{1,\\}Node \\[id=" + failed_node_id
+    return to_kill, survive
 
-    def __choose_node_to_kill(self, kill_coordinator, nodes_to_kill):
-        assert nodes_to_kill > 0, "No nodes to kill passed. Check the 
parameters."
 
-        nodes = self.servers.nodes
-        coordinator = nodes[0].discovery_info().coordinator
-        to_kill = []
+def simulate_nodes_failure(servers, kill_coordinator, nodes_to_kill):
+    """
+    Perform node failure scenario
+    """
+    failed_nodes, survived_node = choose_node_to_kill(servers, 
kill_coordinator, nodes_to_kill)
 
-        if kill_coordinator:
-            to_kill.append(next(node for node in nodes if 
node.discovery_info().node_id == coordinator))
-            nodes_to_kill -= 1
+    ids_to_wait = [node.discovery_info().node_id for node in failed_nodes]
 
-        if nodes_to_kill > 0:
-            choice = random.sample([n for n in nodes if 
n.discovery_info().node_id != coordinator], nodes_to_kill)
-            to_kill.extend([choice] if not isinstance(choice, list) else 
choice)
+    _, first_terminated = servers.stop_nodes_async(failed_nodes, 
clean_shutdown=False, wait_for_stop=False)
 
-        survive = random.choice([node for node in self.servers.nodes if node 
not in to_kill])
+    # Keeps dates of logged node failures.
+    logged_timestamps = []
+    data = {}
 
-        return to_kill, survive
+    for failed_id in ids_to_wait:
+        servers.await_event_on_node(failed_pattern(failed_id), survived_node, 
20,
+                                    from_the_beginning=True, backoff_sec=0.1)
 
-    def __start_loading(self, ignite_version, properties, modules):
-        self.loader = IgniteApplicationService(
-            self.test_context,
-            
java_class_name="org.apache.ignite.internal.ducktest.tests.ContinuousDataLoadApplication",
-            version=ignite_version,
-            modules=modules,
-            properties=properties,
-            params={"cacheName": "test-cache", "range": self.DATA_AMOUNT})
+        _, stdout, _ = survived_node.account.ssh_client.exec_command(
+            "grep '%s' %s" % (failed_pattern(failed_id), 
IgniteAwareService.STDOUT_STDERR_CAPTURE))
 
-        self.loader.start()
+        logged_timestamps.append(
+            datetime.strptime(re.match("^\\[[^\\[]+\\]", 
stdout.read().decode("utf-8")).group(),
+                              "[%Y-%m-%d %H:%M:%S,%f]"))
 
-    def __start_zk_quorum(self):
-        self.zk_quorum = ZookeeperService(self.test_context, 3)
+    logged_timestamps.sort(reverse=True)
 
-        self.zk_quorum.start()
+    first_kill_time = epoch_mills(first_terminated)
+    detection_delay = epoch_mills(logged_timestamps[0]) - first_kill_time
 
-    @staticmethod
-    def __properties(zookeeper_settings=None):
-        """
-        :param zookeeper_settings: ZooKeeperDiscoverySpi settings. If None, 
TcpDiscoverySpi will be used.
-        :return: Rendered node's properties.
-        """
-        return Template(DiscoveryTest.CONFIG_TEMPLATE) \
-            
.render(failure_detection_timeout=DiscoveryTest.FAILURE_DETECTION_TIMEOUT,
-                    zookeeper_settings=zookeeper_settings)
+    data['Detection of node(s) failure (ms)'] = detection_delay
+    data['All detection delays (ms):'] = str([epoch_mills(ts) - 
first_kill_time for ts in logged_timestamps])
+    data['Nodes failed'] = len(failed_nodes)
 
-    @staticmethod
-    def __zk_properties(connection_string):
-        return 
DiscoveryTest.__properties(zookeeper_settings={'connection_string': 
connection_string})
+    return data
diff --git a/modules/ducktests/tests/ignitetest/tests/pme_free_switch_test.py 
b/modules/ducktests/tests/ignitetest/tests/pme_free_switch_test.py
index ea266c3..8ec2daa 100644
--- a/modules/ducktests/tests/ignitetest/tests/pme_free_switch_test.py
+++ b/modules/ducktests/tests/ignitetest/tests/pme_free_switch_test.py
@@ -25,6 +25,9 @@ from ducktape.mark.resource import cluster
 from ignitetest.services.ignite import IgniteService
 from ignitetest.services.ignite_app import IgniteApplicationService
 from ignitetest.services.utils.control_utility import ControlUtility
+from ignitetest.services.utils.ignite_configuration import IgniteConfiguration
+from ignitetest.services.utils.ignite_configuration.cache import 
CacheConfiguration
+from ignitetest.services.utils.ignite_configuration.discovery import 
from_ignite_cluster
 from ignitetest.utils.ignite_test import IgniteTest
 from ignitetest.utils.version import DEV_BRANCH, LATEST_2_7, V_2_8_0, 
IgniteVersion
 
@@ -36,29 +39,6 @@ class PmeFreeSwitchTest(IgniteTest):
     """
     NUM_NODES = 3
 
-    @staticmethod
-    def properties():
-        """
-        :return: Rendered configuration properties.
-        """
-        return """
-            <property name="cacheConfiguration">
-                <list>
-                    <bean 
class="org.apache.ignite.configuration.CacheConfiguration">
-                        <property name="name" value="test-cache"/>
-                        <property name="backups" value="2"/>
-                        <property name="atomicityMode" value="TRANSACTIONAL"/>
-                    </bean>
-                </list>
-            </property>
-        """
-
-    def setUp(self):
-        pass
-
-    def teardown(self):
-        pass
-
     @cluster(num_nodes=NUM_NODES + 2)
     @parametrize(version=str(DEV_BRANCH))
     @parametrize(version=str(LATEST_2_7))
@@ -72,22 +52,25 @@ class PmeFreeSwitchTest(IgniteTest):
 
         ignite_version = IgniteVersion(version)
 
-        ignites = IgniteService(
-            self.test_context,
-            num_nodes=self.NUM_NODES,
-            properties=self.properties(),
-            version=ignite_version)
+        config = IgniteConfiguration(
+            version=ignite_version,
+            caches=[CacheConfiguration(name='test-cache', backups=2, 
atomicity_mode='TRANSACTIONAL')]
+        )
+
+        ignites = IgniteService(self.test_context, config, 
num_nodes=self.NUM_NODES)
 
         ignites.start()
 
         self.stage("Starting long_tx_streamer")
 
+        client_config = config._replace(client_mode=True,
+                                        
discovery_spi=from_ignite_cluster(ignites, slice(0, self.NUM_NODES - 1)))
+
         long_tx_streamer = IgniteApplicationService(
             self.test_context,
+            client_config,
             
java_class_name="org.apache.ignite.internal.ducktest.tests.pme_free_switch_test.LongTxStreamerApplication",
-            properties=self.properties(),
-            params={"cacheName": "test-cache"},
-            version=ignite_version)
+            params={"cacheName": "test-cache"})
 
         long_tx_streamer.start()
 
@@ -95,11 +78,10 @@ class PmeFreeSwitchTest(IgniteTest):
 
         single_key_tx_streamer = IgniteApplicationService(
             self.test_context,
+            client_config,
             
java_class_name="org.apache.ignite.internal.ducktest.tests.pme_free_switch_test."
                             "SingleKeyTxStreamerApplication",
-            properties=self.properties(),
-            params={"cacheName": "test-cache", "warmup": 1000},
-            version=ignite_version)
+            params={"cacheName": "test-cache", "warmup": 1000})
 
         single_key_tx_streamer.start()
 
@@ -108,7 +90,7 @@ class PmeFreeSwitchTest(IgniteTest):
 
         self.stage("Stopping server node")
 
-        ignites.stop_node(ignites.nodes[1])
+        ignites.stop_node(ignites.nodes[self.NUM_NODES - 1])
 
         long_tx_streamer.await_event("Node left topology", 60, 
from_the_beginning=True)
 
diff --git a/modules/ducktests/tests/ignitetest/tests/smoke_test.py 
b/modules/ducktests/tests/ignitetest/tests/smoke_test.py
index 48965e3..d7207a2 100644
--- a/modules/ducktests/tests/ignitetest/tests/smoke_test.py
+++ b/modules/ducktests/tests/ignitetest/tests/smoke_test.py
@@ -18,13 +18,16 @@ This module contains smoke tests that checks that services 
work
 """
 
 from ducktape.mark import parametrize
+from ducktape.mark.resource import cluster
 
 from ignitetest.services.ignite import IgniteService
 from ignitetest.services.ignite_app import IgniteApplicationService
 from ignitetest.services.spark import SparkService
+from ignitetest.services.utils.ignite_configuration.discovery import 
from_ignite_cluster
+from ignitetest.services.utils.ignite_configuration import 
IgniteConfiguration, IgniteClientConfiguration
 from ignitetest.services.zk.zookeeper import ZookeeperService
 from ignitetest.utils.ignite_test import IgniteTest
-from ignitetest.utils.version import DEV_BRANCH
+from ignitetest.utils.version import DEV_BRANCH, IgniteVersion
 
 
 # pylint: disable=W0223
@@ -33,44 +36,35 @@ class SmokeServicesTest(IgniteTest):
     Tests services implementations
     """
 
-    def setUp(self):
-        pass
-
-    def teardown(self):
-        pass
-
+    @cluster(num_nodes=1)
     @parametrize(version=str(DEV_BRANCH))
     def test_ignite_start_stop(self, version):
         """
         Test that IgniteService correctly start and stop
         """
-        ignite = IgniteService(
-            self.test_context,
-            num_nodes=1,
-            version=version)
+        ignite = IgniteService(self.test_context, 
IgniteConfiguration(version=IgniteVersion(version)), num_nodes=1)
         ignite.start()
         ignite.stop()
 
+    @cluster(num_nodes=2)
     @parametrize(version=str(DEV_BRANCH))
     def test_ignite_app_start_stop(self, version):
         """
         Test that IgniteService and IgniteApplicationService correctly start 
and stop
         """
-        ignite = IgniteService(
-            self.test_context,
-            num_nodes=1,
-            version=version)
+        ignite = IgniteService(self.test_context, 
IgniteConfiguration(version=IgniteVersion(version)), num_nodes=1)
 
         app = IgniteApplicationService(
             self.test_context,
-            
java_class_name="org.apache.ignite.internal.ducktest.tests.smoke_test.SimpleApplication",
-            version=version)
+            IgniteClientConfiguration(version=IgniteVersion(version), 
discovery_spi=from_ignite_cluster(ignite)),
+            
java_class_name="org.apache.ignite.internal.ducktest.tests.smoke_test.SimpleApplication")
 
         ignite.start()
         app.start()
         app.stop()
         ignite.stop()
 
+    @cluster(num_nodes=2)
     def test_spark_start_stop(self):
         """
         Test that SparkService correctly start and stop
@@ -79,10 +73,11 @@ class SmokeServicesTest(IgniteTest):
         spark.start()
         spark.stop()
 
+    @cluster(num_nodes=3)
     def test_zk_start_stop(self):
         """
         Test that ZookeeperService correctly start and stop
         """
-        zookeeper = ZookeeperService(self.test_context, num_nodes=2)
+        zookeeper = ZookeeperService(self.test_context, num_nodes=3)
         zookeeper.start()
         zookeeper.stop()
diff --git a/modules/ducktests/tests/setup.py 
b/modules/ducktests/tests/ignitetest/tests/suites/fast_suite.yml
similarity index 51%
copy from modules/ducktests/tests/setup.py
copy to modules/ducktests/tests/ignitetest/tests/suites/fast_suite.yml
index 76dd815..4811574 100644
--- a/modules/ducktests/tests/setup.py
+++ b/modules/ducktests/tests/ignitetest/tests/suites/fast_suite.yml
@@ -13,25 +13,17 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import re
-from setuptools import find_packages, setup
+smoke:
+  - ../smoke_test.py
 
+control_utility:
+  - ../control_utility_test.py
 
-with open('ignitetest/__init__.py', 'r') as fd:
-    version = re.search(r'^__version__\s*=\s*[\'"]([^\'"]*)[\'"]', fd.read(), 
re.MULTILINE).group(1)
+pme_free_switch:
+  - ../pme_free_switch_test.py
 
+cellular_affinity:
+  - ../cellular_affinity_test.py
 
-# Note: when changing the version of ducktape, also revise 
tests/docker/Dockerfile
-setup(name="ignitetest",
-      version=version,
-      description="Apache Ignite System Tests",
-      author="Apache Ignite",
-      platforms=["any"],
-      license="apache2.0",
-      packages=find_packages(exclude=["ignitetest.tests", 
"ignitetest.tests.*"]),
-      include_package_data=True,
-      install_requires=['ducktape==0.8.0'],
-      dependency_links = [
-          
'https://github.com/confluentinc/ducktape/tarball/master#egg=ducktape-0.8.0'
-      ]
-)
+rebalance:
+  - ../add_node_rebalance_test.py
diff --git a/modules/ducktests/tests/ignitetest/tests/suites/slow_suite.yml 
b/modules/ducktests/tests/ignitetest/tests/suites/slow_suite.yml
new file mode 100644
index 0000000..6f066d5
--- /dev/null
+++ b/modules/ducktests/tests/ignitetest/tests/suites/slow_suite.yml
@@ -0,0 +1,17 @@
+# 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
+
+discovery:
+  - ../discovery_test.py
diff --git a/modules/ducktests/tests/setup.py b/modules/ducktests/tests/setup.py
index 76dd815..5b89d58 100644
--- a/modules/ducktests/tests/setup.py
+++ b/modules/ducktests/tests/setup.py
@@ -31,7 +31,6 @@ setup(name="ignitetest",
       packages=find_packages(exclude=["ignitetest.tests", 
"ignitetest.tests.*"]),
       include_package_data=True,
       install_requires=['ducktape==0.8.0'],
-      dependency_links = [
+      dependency_links=[
           
'https://github.com/confluentinc/ducktape/tarball/master#egg=ducktape-0.8.0'
-      ]
-)
+      ])

Reply via email to