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

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


The following commit(s) were added to refs/heads/master by this push:
     new 0af4fdf  IGNITE-11182 Web console: Actualized cluster configuration.
0af4fdf is described below

commit 0af4fdf839fb1fb58e34a81bba473ec86792062b
Author: Vasiliy Sisko <vsi...@gridgain.com>
AuthorDate: Fri Apr 5 13:15:57 2019 +0700

    IGNITE-11182 Web console: Actualized cluster configuration.
---
 .../eviction/lru/LruEvictionPolicyFactory.java     |   1 -
 modules/web-console/backend/app/schemas.js         |  71 +++++-
 .../components/cache-edit-form/template.tpl.pug    |   2 +
 .../cache-edit-form/templates/general.pug          |  42 ++--
 .../cache-edit-form/templates/key-cfg.pug          |  66 ++++++
 .../cache-edit-form/templates/memory.pug           |  21 ++
 .../components/cache-edit-form/templates/misc.pug  |  95 ++++++++
 .../components/cache-edit-form/templates/query.pug |  45 +++-
 .../components/cache-edit-form/templates/store.pug |   9 +
 .../components/cluster-edit-form/templates/ssl.pug |  28 +++
 .../igfs-edit-form/templates/secondary.pug         | 252 ++++++++++++++++++++-
 .../generator/generator/AbstractTransformer.js     |  14 +-
 .../app/configuration/generator/generator/Beans.js |   7 +
 .../generator/generator/ConfigurationGenerator.js  | 163 ++++++++++++-
 .../generator/generator/JavaTransformer.service.js |   8 +
 .../generator/generator/Maven.service.js           |   2 +-
 .../generator/SpringTransformer.service.js         |   2 +
 .../generator/generator/defaults/Cache.service.js  |   9 +-
 .../generator/generator/defaults/IGFS.service.js   |  15 +-
 .../frontend/app/configuration/services/Caches.ts  |   3 +-
 .../frontend/app/configuration/services/IGFSs.ts   |  16 +-
 .../WebConsoleConfigurationSelfTest.java           |  69 +++++-
 22 files changed, 878 insertions(+), 62 deletions(-)

diff --git 
a/modules/core/src/main/java/org/apache/ignite/cache/eviction/lru/LruEvictionPolicyFactory.java
 
b/modules/core/src/main/java/org/apache/ignite/cache/eviction/lru/LruEvictionPolicyFactory.java
index 8f7fbc5..ff873ac 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/cache/eviction/lru/LruEvictionPolicyFactory.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/cache/eviction/lru/LruEvictionPolicyFactory.java
@@ -68,5 +68,4 @@ public class LruEvictionPolicyFactory<K, V> extends 
AbstractEvictionPolicyFactor
 
         return policy;
     }
-
 }
diff --git a/modules/web-console/backend/app/schemas.js 
b/modules/web-console/backend/app/schemas.js
index 29ec9b4..ce48932 100644
--- a/modules/web-console/backend/app/schemas.js
+++ b/modules/web-console/backend/app/schemas.js
@@ -185,6 +185,21 @@ module.exports.factory = function(mongoose) {
         offHeapMaxMemory: Number,
         startSize: Number,
         swapEnabled: Boolean,
+        cacheWriterFactory: String,
+        cacheLoaderFactory: String,
+        expiryPolicyFactory: String,
+        interceptor: String,
+        storeByValue: Boolean,
+        eagerTtl: {type: Boolean, default: true},
+        encryptionEnabled: Boolean,
+        eventsDisabled: Boolean,
+
+        keyConfiguration: [{
+            typeName: String,
+            affinityKeyFieldName: String
+        }],
+
+        cacheStoreSessionListenerFactories: [String],
 
         onheapCacheEnabled: Boolean,
 
@@ -255,6 +270,8 @@ module.exports.factory = function(mongoose) {
                 hibernateProperties: [{name: String, value: String}]
             }
         },
+        storeConcurrentLoadAllThreshold: Number,
+        maxQueryIteratorsCount: Number,
         storeKeepBinary: Boolean,
         loadPreviousValue: Boolean,
         readThrough: Boolean,
@@ -377,9 +394,57 @@ module.exports.factory = function(mongoose) {
         trashPurgeTimeout: Number,
         secondaryFileSystemEnabled: Boolean,
         secondaryFileSystem: {
+            userName: String,
+            kind: {type: String, enum: ['Caching', 'Kerberos', 'Custom'], 
default: 'Caching'},
             uri: String,
             cfgPath: String,
-            userName: String
+            cfgPaths: [String],
+            userNameMapper: {
+                kind: {type: String, enum: ['Chained', 'Basic', 'Kerberos', 
'Custom']},
+                Chained: {
+                    mappers: [{
+                        kind: {type: String, enum: ['Basic', 'Kerberos', 
'Custom']},
+                        Basic: {
+                            defaultUserName: String,
+                            useDefaultUserName: Boolean,
+                            mappings: [{
+                                name: String,
+                                value: String
+                            }]
+                        },
+                        Kerberos: {
+                            instance: String,
+                            realm: String
+                        },
+                        Custom: {
+                            className: String,
+                        }
+                    }]
+                },
+                Basic: {
+                    defaultUserName: String,
+                    useDefaultUserName: Boolean,
+                    mappings: [{
+                        name: String,
+                        value: String
+                    }]
+                },
+                Kerberos: {
+                    instance: String,
+                    realm: String
+                },
+                Custom: {
+                    className: String,
+                }
+            },
+            Kerberos: {
+                keyTab: String,
+                keyTabPrincipal: String,
+                reloginInterval: Number
+            },
+            Custom: {
+                className: String
+            }
         },
         colocateMetadata: Boolean,
         relaxedConsistency: Boolean,
@@ -714,7 +779,9 @@ module.exports.factory = function(mongoose) {
             protocol: String,
             trustStoreFilePath: String,
             trustStoreType: String,
-            trustManagers: [String]
+            trustManagers: [String],
+            cipherSuites: [String],
+            protocols: [String]
         },
         rebalanceThreadPoolSize: Number,
         odbc: {
diff --git 
a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/template.tpl.pug
 
b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/template.tpl.pug
index 7305a39..5d98d77 100644
--- 
a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/template.tpl.pug
+++ 
b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/template.tpl.pug
@@ -26,6 +26,8 @@ form(
 
     include ./templates/affinity
     include ./templates/concurrency
+    include ./templates/key-cfg
+    include ./templates/misc
     include ./templates/near-cache-client
     include ./templates/near-cache-server
     include ./templates/node-filter
diff --git 
a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/general.pug
 
b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/general.pug
index 00a544f..9b875ab 100644
--- 
a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/general.pug
+++ 
b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/general.pug
@@ -103,28 +103,28 @@ panel-collapsible(opened=`::true` ng-form=form)
                     name: '"partitionLossPolicy"',
                     placeholder: 'IGNORE',
                     options: '[\
-                                        {value: "READ_ONLY_SAFE", label: 
"READ_ONLY_SAFE"},\
-                                        {value: "READ_ONLY_ALL", label: 
"READ_ONLY_ALL"},\
-                                        {value: "READ_WRITE_SAFE", label: 
"READ_WRITE_SAFE"},\
-                                        {value: "READ_WRITE_ALL", label: 
"READ_WRITE_ALL"},\
-                                        {value: "IGNORE", label: "IGNORE"}\
-                                    ]',
+                        {value: "READ_ONLY_SAFE", label: "READ_ONLY_SAFE"},\
+                        {value: "READ_ONLY_ALL", label: "READ_ONLY_ALL"},\
+                        {value: "READ_WRITE_SAFE", label: "READ_WRITE_SAFE"},\
+                        {value: "READ_WRITE_ALL", label: "READ_WRITE_ALL"},\
+                        {value: "IGNORE", label: "IGNORE"}\
+                    ]',
                     tip: 'Partition loss policies:\
-                                    <ul>\
-                                        <li>READ_ONLY_SAFE - in this mode all 
writes to the cache will be failed with an exception,\
-                                            reads will only be allowed for 
keys in  non-lost partitions.\
-                                            Reads from lost partitions will be 
failed with an exception.</li>\
-                                        <li>READ_ONLY_ALL - in this mode all 
writes to the cache will be failed with an exception.\
-                                            All reads will proceed as if all 
partitions were in a consistent state.\
-                                            The result of reading from a lost 
partition is undefined and may be different on different nodes in the 
cluster.</li>\
-                                        <li>READ_WRITE_SAFE - in this mode all 
reads and writes will be allowed for keys in valid partitions.\
-                                            All reads and writes for keys in 
lost partitions will be failed with an exception.</li>\
-                                        <li>READ_WRITE_ALL - in this mode all 
reads and writes will proceed as if all partitions were in a consistent state.\
-                                            The result of reading from a lost 
partition is undefined and may be different on different nodes in the 
cluster.</li>\
-                                        <li>IGNORE - in this mode if partition 
is lost, reset it state and do not clear intermediate data.\
-                                            The result of reading from a 
previously lost and not cleared partition is undefined and may be different\
-                                            on different nodes in the 
cluster.</li>\
-                                    </ul>'
+                        <ul>\
+                            <li>READ_ONLY_SAFE - in this mode all writes to 
the cache will be failed with an exception,\
+                                reads will only be allowed for keys in  
non-lost partitions.\
+                                Reads from lost partitions will be failed with 
an exception.</li>\
+                            <li>READ_ONLY_ALL - in this mode all writes to the 
cache will be failed with an exception.\
+                                All reads will proceed as if all partitions 
were in a consistent state.\
+                                The result of reading from a lost partition is 
undefined and may be different on different nodes in the cluster.</li>\
+                            <li>READ_WRITE_SAFE - in this mode all reads and 
writes will be allowed for keys in valid partitions.\
+                                All reads and writes for keys in lost 
partitions will be failed with an exception.</li>\
+                            <li>READ_WRITE_ALL - in this mode all reads and 
writes will proceed as if all partitions were in a consistent state.\
+                                The result of reading from a lost partition is 
undefined and may be different on different nodes in the cluster.</li>\
+                            <li>IGNORE - in this mode if partition is lost, 
reset it state and do not clear intermediate data.\
+                                The result of reading from a previously lost 
and not cleared partition is undefined and may be different\
+                                on different nodes in the cluster.</li>\
+                        </ul>'
                 })
             .pc-form-grid-col-60(ng-show=`${model}.cacheMode === 'PARTITIONED' 
&& ${model}.backups`)
                 +form-field__checkbox({
diff --git 
a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/key-cfg.pug
 
b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/key-cfg.pug
new file mode 100644
index 0000000..4527906
--- /dev/null
+++ 
b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/key-cfg.pug
@@ -0,0 +1,66 @@
+//-
+    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.
+
+include /app/helpers/jade/mixins
+include /app/configuration/mixins
+
+-var form = 'cacheKeyCfg'
+-var model = '$ctrl.clonedCache.keyConfiguration'
+
+panel-collapsible(ng-show='$ctrl.available("2.1.0")' ng-form=form 
on-open=`ui.loadPanel('${form}')`)
+    panel-title Key configuration
+    panel-description
+        | Configuration defining various aspects of cache keys without 
explicit usage of annotations on user classes.
+    panel-content.pca-form-row(ng-if=`ui.isPanelLoaded('${form}')`)
+        .pca-form-column-6
+            .ignite-form-field
+                +form-field__label({ label: 'Key configuration:', name: 
'"KeyConfiguration"' })
+
+                list-editable.pc-list-editable-with-form-grid(ng-model=model 
name='keyConfiguration')
+                    list-editable-item-edit.pc-form-grid-row
+                        - form = '$parent.form'
+                        .pc-form-grid-col-60
+                            +form-field__java-class({
+                                label: 'Type name:',
+                                model: '$item.typeName',
+                                name: '"keyTypeName"',
+                                required: 'true',
+                                tip: 'Type name'
+                            })(
+                                ignite-form-field-input-autofocus='true'
+                                ignite-unique=model
+                                ignite-unique-property='typeName'
+                            )
+                                +form-field__error({ error: 'igniteUnique', 
message: 'Type name should be unique.' })
+                        .pc-form-grid-col-60
+                            +form-field__text({
+                                label: 'Affinity key field name:',
+                                model: '$item.affinityKeyFieldName',
+                                name: '"affinityKeyFieldName"',
+                                placeholder: 'Enter field name',
+                                tip: 'Affinity key field name',
+                                required: true
+                            })
+
+                    list-editable-no-items
+                        list-editable-add-item-button(
+                            add-item=`(${model} = ${model} || []).push({})`
+                            label-single='configuration'
+                            label-multiple='configurations'
+                        )
+
+        .pca-form-column-6
+            +preview-xml-java(model, 'cacheKeyConfiguration')
diff --git 
a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/memory.pug
 
b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/memory.pug
index f4403a7..cf69d65 100644
--- 
a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/memory.pug
+++ 
b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/memory.pug
@@ -226,6 +226,27 @@ panel-collapsible(ng-form=form 
on-open=`ui.loadPanel('${form}')`)
                     name: '"swapEnabled"',
                     tip: 'Flag indicating whether swap storage is enabled or 
not for this cache'
                 })
+            .pc-form-grid-col-60
+                +form-field__java-class({
+                    label: 'Cache writer factory:',
+                    model: `${model}.cacheWriterFactory`,
+                    name: `"CacheWriterFactory"`,
+                    tip: 'Factory for writer that is used for write-through to 
an external resource'
+                })
+            .pc-form-grid-col-60
+                +form-field__java-class({
+                    label: 'Cache loader factory:',
+                    model: `${model}.cacheLoaderFactory`,
+                    name: `"CacheLoaderFactory"`,
+                    tip: 'Factory for loader that is used for a cache is 
read-through or when loading data into a cache via the 
Cache.loadAll(java.util.Set, boolean, CompletionListener) method'
+                })
+            .pc-form-grid-col-60
+                +form-field__java-class({
+                    label: 'Expiry policy factory:',
+                    model: `${model}.expiryPolicyFactory`,
+                    name: `"ExpiryPolicyFactory"`,
+                    tip: 'Factory for functions that determine when cache 
entries will expire based on creation, access and modification operations'
+                })
 
         .pca-form-column-6
             +preview-xml-java(model, 'cacheMemory')
diff --git 
a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/misc.pug
 
b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/misc.pug
new file mode 100644
index 0000000..8267f1c
--- /dev/null
+++ 
b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/misc.pug
@@ -0,0 +1,95 @@
+//-
+    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.
+
+include /app/helpers/jade/mixins
+include /app/configuration/mixins
+
+-var form = 'misc'
+-var model = '$ctrl.clonedCache'
+
+panel-collapsible(ng-form=form on-open=`ui.loadPanel('${form}')`)
+    panel-title Miscellaneous
+    panel-description Various miscellaneous cache settings.
+    panel-content.pca-form-row(ng-if=`ui.isPanelLoaded('${form}')`)
+        .pca-form-column-6.pc-form-grid-row
+            .pc-form-grid-col-60
+                +form-field__java-class({
+                    label: 'Interceptor:',
+                    model: `${model}.interceptor`,
+                    name: '"interceptor"',
+                    tip: 'Cache interceptor can be used for getting callbacks 
before and after cache get, put, and remove operations'
+                })
+            .pc-form-grid-col-60(ng-if='$ctrl.available("2.0.0")')
+                +form-field__checkbox({
+                    label: 'Store by value',
+                    model: `${model}.storeByValue`,
+                    name: '"storeByValue"',
+                    tip: 'Use store-by-value or store-by-reference semantics'
+                })
+            .pc-form-grid-col-60
+                +form-field__checkbox({
+                    label: 'Eager TTL',
+                    model: `${model}.eagerTtl`,
+                    name: '"eagerTtl"',
+                    tip: 'Eagerly remove expired cache entries'
+                })
+            .pc-form-grid-col-60(ng-if='$ctrl.available("2.7.0")')
+                +form-field__checkbox({
+                    label: 'Enable encryption',
+                    model: `${model}.encryptionEnabled`,
+                    name: '"encryptionEnabled"',
+                    tip: 'Enable encription of data on the disk'
+                })
+            .pc-form-grid-col-60(ng-if='$ctrl.available("2.5.0")')
+                +form-field__checkbox({
+                    label: 'Disable events',
+                    model: `${model}.eventsDisabled`,
+                    name: '"eventsDisabled"',
+                    tip: 'Disable events on this cache'
+                })
+            .pc-form-grid-col-60
+                mixin store-session-listener-factories()
+                    .ignite-form-field
+                        -let items = 
`${model}.cacheStoreSessionListenerFactories`;
+
+                        list-editable(
+                        ng-model=items
+                        list-editable-cols=`::[{
+                            name: 'Store session listener factories:',
+                            tip: 'Cache store session listener factories'
+                        }]`)
+                            list-editable-item-view {{ $item }}
+
+                            list-editable-item-edit
+                                +list-java-class-field('Listener', '$item', 
'"Listener"', items)
+                                    +form-field__error({
+                                        error: 'igniteUnique',
+                                        message: 'Listener with such class 
name already exists!'
+                                    })
+
+                            list-editable-no-items
+                                list-editable-add-item-button(
+                                    add-item=`$editLast((${items} = ${items} 
|| []).push(""))`
+                                    label-single='listener'
+                                    label-multiple='listeners'
+                                )
+
+                - var form = '$parent.form'
+                +store-session-listener-factories
+                - var form = 'misc'
+
+        .pca-form-column-6
+            +preview-xml-java(model, 'cacheMisc')
diff --git 
a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/query.pug
 
b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/query.pug
index b0fe00b..edbcb25 100644
--- 
a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/query.pug
+++ 
b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/query.pug
@@ -118,16 +118,6 @@ panel-collapsible(ng-form=form 
on-open=`ui.loadPanel('${form}')`)
                     tip: 'Flag indicating whether SQL indexes should support 
snapshots'
                 })
 
-            .pc-form-grid-col-60
-                +form-field__checkbox({
-                    label: 'Escape table and filed names',
-                    model: `${model}.sqlEscapeAll`,
-                    name: '"sqlEscapeAll"',
-                    tip: 'If enabled than all schema, table and field names 
will be escaped with double quotes (for example: "tableName"."fieldName").<br/>\
-                         This enforces case sensitivity for field names and 
also allows having special characters in table and field names.<br/>\
-                         Escaped names will be used for creation internal 
structures in Ignite SQL engine.'
-                })
-
             //- Since ignite 2.0
             .pc-form-grid-col-30(ng-if-start='$ctrl.available("2.0.0")')
                 +form-field__number({
@@ -147,6 +137,41 @@ panel-collapsible(ng-form=form 
on-open=`ui.loadPanel('${form}')`)
                     min: '-1',
                     tip: 'Maximum inline size for sql indexes'
                 })
+            .pc-form-grid-col-60(ng-if-start='$ctrl.available("2.4.0")')
+                +form-field__checkbox({
+                    label: 'Onheap cache enabled',
+                    model: `${model}.sqlOnheapCacheEnabled`,
+                    name: '"sqlOnheapCacheEnabled"',
+                    tip: 'When enabled, Ignite will cache SQL rows as they are 
accessed by query engine'
+                })
+            .pc-form-grid-col-60(ng-if-end)
+                +form-field__number({
+                    label: 'Onheap cache max size:',
+                    model: `${model}.sqlOnheapCacheMaxSize`,
+                    name: '"SqlOnheapCacheMaxSize"',
+                    disabled: `!${model}.sqlOnheapCacheEnabled`,
+                    placeholder: '0',
+                    min: '0',
+                    tip: 'Maximum SQL on-heap cache'
+                })
+            .pc-form-grid-col-60
+                +form-field__number({
+                    label: 'Max query iterators count:',
+                    model: `${model}.maxQueryIteratorsCount`,
+                    name: '"MaxQueryIteratorsCount"',
+                    placeholder: '1024',
+                    min: '1',
+                    tip: 'Maximum number of query iterators that can be stored'
+                })
+            .pc-form-grid-col-60
+                +form-field__checkbox({
+                    label: 'Escape table and filed names',
+                    model: `${model}.sqlEscapeAll`,
+                    name: '"sqlEscapeAll"',
+                    tip: 'If enabled than all schema, table and field names 
will be escaped with double quotes (for example: "tableName"."fieldName").<br/>\
+                         This enforces case sensitivity for field names and 
also allows having special characters in table and field names.<br/>\
+                         Escaped names will be used for creation internal 
structures in Ignite SQL engine.'
+                })
 
         .pca-form-column-6
             +preview-xml-java(model, 'cacheQuery', 'domains')
diff --git 
a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/store.pug
 
b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/store.pug
index 96ce5a4..b4baac5 100644
--- 
a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/store.pug
+++ 
b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/store.pug
@@ -297,6 +297,15 @@ panel-collapsible(ng-form=form 
on-open=`ui.loadPanel('${form}')`)
 
             - form = 'store'
             .pc-form-grid-col-60
+                +form-field__number({
+                    label: 'Concurrent load all threshold:',
+                    model: `${model}.storeConcurrentLoadAllThreshold`,
+                    name: '"storeConcurrentLoadAllThreshold"',
+                    placeholder: '5',
+                    min: '1',
+                    tip: 'Threshold used in cases when values for multiple 
keys are being loaded from an underlying cache store in parallel'
+                })
+            .pc-form-grid-col-60
                 +form-field__checkbox({
                     label: 'Keep binary in store',
                     model: `${model}.storeKeepBinary`,
diff --git 
a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cluster-edit-form/templates/ssl.pug
 
b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cluster-edit-form/templates/ssl.pug
index a062425..dea087e 100644
--- 
a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cluster-edit-form/templates/ssl.pug
+++ 
b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cluster-edit-form/templates/ssl.pug
@@ -128,5 +128,33 @@ panel-collapsible(ng-form=form 
on-open=`ui.loadPanel('${form}')`)
                     options: '["JKS", "PCKS11", "PCKS12"]',
                     tip: 'Trust store type used in context initialization'
                 })
+            .pc-form-grid-col-60(ng-if-start='$ctrl.available("2.7.0")')
+                .ignite-form-field
+                    +list-text-field({
+                        items: `${model}.cipherSuites`,
+                        lbl: 'Cipher suite',
+                        name: 'cipherSuite',
+                        itemName: 'cipher suite',
+                        itemsName: 'cipher suites'
+
+                    })(
+                        list-editable-cols=`::[{name: 'Suites:'}]`
+                        ng-disabled=`!(${enabled})`
+                    )
+                        +form-field__error({error: 'igniteUnique', message: 
'Such suite is already configured!'})
+            .pc-form-grid-col-60(ng-if-end)
+                .ignite-form-field
+                    +list-text-field({
+                        items: `${model}.protocols`,
+                        lbl: 'Protocol',
+                        name: 'protocols',
+                        itemName: 'protocol',
+                        itemsName: 'protocols'
+
+                    })(
+                        list-editable-cols=`::[{name: 'Protocols:'}]`
+                        ng-disabled=`!(${enabled})`
+                    )
+                        +form-field__error({error: 'igniteUnique', message: 
'Such protocol already exists!'})
         .pca-form-column-6
             +preview-xml-java(cluster, 'clusterSsl')
diff --git 
a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/igfs-edit-form/templates/secondary.pug
 
b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/igfs-edit-form/templates/secondary.pug
index 7d42a04..ac91770 100644
--- 
a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/igfs-edit-form/templates/secondary.pug
+++ 
b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/igfs-edit-form/templates/secondary.pug
@@ -19,6 +19,76 @@ include /app/configuration/mixins
 
 -var form = 'secondaryFileSystem'
 -var model = 'backupItem'
+-var enabled = `${model}.secondaryFileSystemEnabled`
+
+mixin basic-name-mapper(basicModel, prefix)
+    .pc-form-grid-col-60
+        +form-field__text({
+            label: 'Default user name:',
+            model: `${basicModel}.defaultUserName`,
+            name: `"${prefix}BasicDefaultUserName"`,
+            required: `${basicModel}.useDefaultUserName`,
+            disabled: `!(${enabled})`,
+            placeholder: 'Input default user name',
+            tip: 'Default user name'
+        })
+    .pc-form-grid-col-60
+        +form-field__checkbox({
+            label: 'Use default user name',
+            model: `${basicModel}.useDefaultUserName`,
+            name: `"${prefix}BasicUseDefaultUserName"`,
+            required: `!${basicModel}.mappings`,
+            disabled: `!(${enabled})`,
+            tip: 'Whether to use default user name'
+        })
+    .pc-form-grid-col-60
+        .ignite-form-field
+            +form-field__label({label: 'Name mappings:', name: 
`"${prefix}BasicNameMappings"`})
+                +form-field__tooltip({title: `Maps one user name to another`})
+
+            +list-pair-edit({
+                items: `${basicModel}.mappings`,
+                keyLbl: 'Old name',
+                valLbl: 'New name',
+                itemName: 'name',
+                itemsName: 'names'
+            })
+
+        .form-field__errors(
+            ng-messages=`receiverAddresses.$error`
+            ng-show=`receiverAddresses.$invalid`
+        )
+            +form-field__error({error: 'required', message: 'Name mappings 
should be configured'})
+
+mixin kerberos-name-mapper(kerberosModel, prefix)
+    .pc-form-grid-col-60
+        +form-field__text({
+            label: 'Instance:',
+            model: `${kerberosModel}.instance`,
+            name: `"${prefix}KerberosInstance"`,
+            disabled: `!(${enabled})`,
+            placeholder: 'Input instance',
+            tip: 'Kerberos instance'
+        })
+    .pc-form-grid-col-60
+        +form-field__text({
+            label: 'Realm:',
+            model: `${kerberosModel}.realm`,
+            name: `"${prefix}KerberosRealm"`,
+            disabled: `!(${enabled})`,
+            placeholder: 'Input realm',
+            tip: 'Kerberos realm'
+        })
+
+mixin custom-name-mapper(customModel, prefix)
+    .pc-form-grid-col-60
+        +form-field__java-class({
+            label: 'Class:',
+            model: `${customModel}.className`,
+            name: `"${prefix}CustomClassName"`,
+            required: true,
+            tip: 'User name mapper implementation class name'
+        })
 
 panel-collapsible(ng-form=form on-open=`ui.loadPanel('${form}')`)
     panel-title Secondary file system
@@ -27,8 +97,8 @@ panel-collapsible(ng-form=form 
on-open=`ui.loadPanel('${form}')`)
         
a.link-success(href="https://apacheignite-fs.readme.io/docs/secondary-file-system";
 target="_blank") More info
     panel-content.pca-form-row(ng-if=`ui.isPanelLoaded('${form}')`)
         .pca-form-column-6.pc-form-grid-row
-            -var enabled = `${model}.secondaryFileSystemEnabled`
             -var secondaryFileSystem = `${model}.secondaryFileSystem`
+            -var nameMapperModel = `${secondaryFileSystem}.userNameMapper`
 
             .pc-form-grid-col-60
                 +form-field__checkbox({
@@ -48,6 +118,35 @@ panel-collapsible(ng-form=form 
on-open=`ui.loadPanel('${form}')`)
                     +form-field__error({ error: 
'requiredWhenPathModeProxyMode', message: 'Secondary file system should be 
configured for "PROXY" path mode' })
             .pc-form-grid-col-60
                 +form-field__text({
+                    label: 'User name:',
+                    model: `${secondaryFileSystem}.userName`,
+                    name: '"userName"',
+                    disabled: `!(${enabled})`,
+                    placeholder: 'Input user name',
+                    tip: 'User name'
+                })
+            .pc-form-grid-col-60
+                +form-field__dropdown({
+                    label: 'File system factory:',
+                    model: `${secondaryFileSystem}.kind`,
+                    name: '"FileSystemFactory"',
+                    disabled: `!(${enabled})`,
+                    placeholder: 'Default',
+                    options: '[\
+                        {value: "Caching", label: "Caching"},\
+                        {value: "Kerberos", label: "Kerberos"},\
+                        {value: "Custom", label: "Custom"},\
+                        {value: null, label: "Default"}\
+                    ]',
+                    tip: 'File system factory:\
+                        <ul>\
+                            <li>Caching - Caches File system instances on 
per-user basis</li>\
+                            <li>Kerberos - Secure Hadoop file system factory 
that can work with underlying file system protected with Kerberos</li>\
+                            <li>Custom - Custom file system factory</li>\
+                        </ul>'
+                })
+            .pc-form-grid-col-60(ng-if-start=`${secondaryFileSystem}.kind !== 
"Custom"`)
+                +form-field__text({
                     label: 'URI:',
                     model: `${secondaryFileSystem}.uri`,
                     name: '"hadoopURI"',
@@ -56,22 +155,153 @@ panel-collapsible(ng-form=form 
on-open=`ui.loadPanel('${form}')`)
                     tip: 'URI of file system'
                 })
             .pc-form-grid-col-60
+                mixin secondary-fs-cfg-paths()
+                    .ignite-form-field
+                        -let items = `${secondaryFileSystem}.cfgPaths`;
+
+                        list-editable(
+                            ng-model=items
+                            list-editable-cols=`::[{
+                                name: 'Config paths:',
+                                tip: 'Additional pathes to Hadoop 
configurations'
+                            }]`
+                            ng-disabled=`!(${enabled})`
+                        )
+                            list-editable-item-view {{ $item }}
+
+                            list-editable-item-edit
+                                .pc-form-grid-row
+                                    .pc-form-grid-col-60
+                                        +form-field__text({
+                                            label: 'Path:',
+                                            model: '$item',
+                                            name: '"path"',
+                                            required: true,
+                                            placeholder: 'Enter path'
+                                        })(ignite-auto-focus)
+
+                            list-editable-no-items
+                                list-editable-add-item-button(
+                                    add-item=`$editLast((${items} = ${items} 
|| []).push(""))`
+                                    label-single='Config path'
+                                    label-multiple='Config paths'
+                                )
+
+                - var form = '$parent.form'
+                +secondary-fs-cfg-paths
+                - var form = 'secondaryFileSystem'
+            .pc-form-grid-col-60(ng-if-start=`${secondaryFileSystem}.kind === 
"Kerberos"`)
                 +form-field__text({
-                    label: 'Config path:',
-                    model: `${secondaryFileSystem}.cfgPath`,
-                    name: '"cfgPath"',
+                    label: 'Keytab file:',
+                    model: `${secondaryFileSystem}.Kerberos.keyTab`,
+                    name: '"KerberosKeyTab"',
+                    required: true,
                     disabled: `!(${enabled})`,
-                    placeholder: 'Path to additional config',
-                    tip: 'Additional path to Hadoop configuration'
+                    placeholder: 'Input keytab full file name',
+                    tip: 'Keytab full file name'
                 })
             .pc-form-grid-col-60
                 +form-field__text({
-                    label: 'User name:',
-                    model: `${secondaryFileSystem}.userName`,
-                    name: '"userName"',
+                    label: 'Keytab principal:',
+                    model: `${secondaryFileSystem}.Kerberos.keyTabPrincipal`,
+                    name: '"KerberosKeyTabPrincipals"',
+                    required: true,
                     disabled: `!(${enabled})`,
-                    placeholder: 'Input user name',
-                    tip: 'User name'
+                    placeholder: 'Input keytab principals',
+                    tip: 'Keytab principals short name'
+                })
+            .pc-form-grid-col-60(ng-if-end)
+                +form-field__number({
+                    label: 'Relogin interval:',
+                    model: `${secondaryFileSystem}.Kerberos.reloginInterval`,
+                    name: '"KerberosReloginInterval"',
+                    placeholder: '600000',
+                    min: '0',
+                    tip: 'Total time in ms for execution of retry attempt'
                 })
+            .pc-form-grid-col-60(ng-if-end)
+                +form-field__dropdown({
+                    label: 'User name mapper:',
+                    model: `${nameMapperModel}.kind`,
+                    name: '"NameMapperKind"',
+                    disabled: `!(${enabled})`,
+                    placeholder: 'Not set',
+                    options: '[\
+                        {value: "Chained", label: "Chained"},\
+                        {value: "Basic", label: "Basic"},\
+                        {value: "Kerberos", label: "Kerberos"},\
+                        {value: "Custom", label: "Custom"},\
+                        {value: null, label: "Not set"}\
+                    ]',
+                    tip: 'File system factory:\
+                        <ul>\
+                            <li>Chained - Delegate name conversion to child 
mappers</li>\
+                            <li>Basic - Maps one user name to another based on 
predefined dictionary</li>\
+                            <li>Kerberos - Map simple user name to Kerberos 
principal</li>\
+                            <li>Custom - Custom user name mapper</li>\
+                        </ul>'
+                })
+            .pc-form-group.pc-form-grid-row(ng-if=`${secondaryFileSystem}.kind 
!== "Custom" && ${nameMapperModel}.kind === "Chained"`)
+                .pc-form-grid-col-60
+                    .ignite-form-field
+                        -var chainedMapperModel = `${nameMapperModel}.Chained`
+
+                        +form-field__label({label: 'Chained name mappers:', 
name: '"ChainedNameMappers"'})
+                            +form-field__tooltip({title: `Chained name 
mappers`})
+
+                        -var items = `${chainedMapperModel}.mappers`
+                        
list-editable.pc-list-editable-with-form-grid(ng-model=items 
name='chainedNameMappers')
+                            list-editable-item-edit.pc-form-grid-row
+                                - form = '$parent.form'
+                                .pc-form-grid-col-60
+                                    +form-field__dropdown({
+                                        label: 'Name mapper:',
+                                        model: '$item.kind',
+                                        name: '"ChainedNameMapperKind"',
+                                        disabled: `!(${enabled})`,
+                                        placeholder: 'Custom',
+                                        options: '[\
+                                            {value: "Basic", label: "Basic"},\
+                                            {value: "Kerberos", label: 
"Kerberos"},\
+                                            {value: "Custom", label: "Custom"}\
+                                        ]',
+                                        tip: 'File system factory:\
+                                            <ul>\
+                                                <li>Basic - Maps one user name 
to another based on predefined dictionary</li>\
+                                                <li>Kerberos - Map simple user 
name to Kerberos principal</li>\
+                                                <li>Custom - Custom user name 
mapper</li>\
+                                            </ul>'
+                                    })
+                                
.pc-form-group.pc-form-grid-row(ng-if=`$item.kind === "Basic"`)
+                                    +basic-name-mapper(`$item.Basic`)
+                                
.pc-form-group.pc-form-grid-row(ng-if=`$item.kind === "Kerberos"`)
+                                    +kerberos-name-mapper(`$item.Kerberos`)
+                                
.pc-form-group.pc-form-grid-row(ng-if=`$item.kind === "Custom"`)
+                                    +custom-name-mapper(`$item.Custom`, '')
+
+                            list-editable-no-items
+                                list-editable-add-item-button(
+                                    
add-item=`$ctrl.IGFSs.addSecondaryFsNameMapper(${model})`
+                                    label-single='name mapper'
+                                    label-multiple='name mappers'
+                                )
+
+            - form = 'secondaryFileSystem'
+            .pc-form-group.pc-form-grid-row(ng-if=`${secondaryFileSystem}.kind 
!== "Custom" && ${nameMapperModel}.kind === "Basic"`)
+                +basic-name-mapper(`${nameMapperModel}.Basic`)
+            .pc-form-group.pc-form-grid-row(ng-if=`${secondaryFileSystem}.kind 
!== "Custom" && ${nameMapperModel}.kind === "Kerberos"`)
+                +kerberos-name-mapper(`${nameMapperModel}.Kerberos`)
+            .pc-form-group.pc-form-grid-row(ng-if=`${secondaryFileSystem}.kind 
!== "Custom" && ${nameMapperModel}.kind === "Custom"`)
+                +custom-name-mapper(`${nameMapperModel}.Custom`, '')
+            .pc-form-grid-col-60(ng-if=`${secondaryFileSystem}.kind === 
"Custom"`)
+                +form-field__java-class({
+                    label: 'Class:',
+                    model: `${secondaryFileSystem}.Custom.className`,
+                    name: '"customFilesystemFactory"',
+                    required: true,
+                    tip: 'File system factory implementation class name',
+                    validationActive: required
+                })
+
         .pca-form-column-6
             +preview-xml-java(model, 'igfsSecondFS')
diff --git 
a/modules/web-console/frontend/app/configuration/generator/generator/AbstractTransformer.js
 
b/modules/web-console/frontend/app/configuration/generator/generator/AbstractTransformer.js
index 73b0a08..2a81b4d 100644
--- 
a/modules/web-console/frontend/app/configuration/generator/generator/AbstractTransformer.js
+++ 
b/modules/web-console/frontend/app/configuration/generator/generator/AbstractTransformer.js
@@ -191,8 +191,8 @@ export default class AbstractTransformer {
     }
 
     // Generate ssl group.
-    static clusterSsl(cluster) {
-        return this.toSection(this.generator.clusterSsl(cluster));
+    static clusterSsl(cluster, available) {
+        return this.toSection(this.generator.clusterSsl(cluster, available));
     }
 
     // Generate swap group.
@@ -260,6 +260,11 @@ export default class AbstractTransformer {
         return this.toSection(this.generator.cacheAffinity(cache, available));
     }
 
+    // Generate cache key configuration.
+    static cacheKeyConfiguration(cache, available) {
+        return this.toSection(this.generator.cacheKeyConfiguration(cache, 
available));
+    }
+
     // Generate cache memory group.
     static cacheMemory(cache, available) {
         return this.toSection(this.generator.cacheMemory(cache, available));
@@ -280,6 +285,11 @@ export default class AbstractTransformer {
         return this.toSection(this.generator.cacheConcurrency(cache, 
available));
     }
 
+    // Generate cache misc group.
+    static cacheMisc(cache, available) {
+        return this.toSection(this.generator.cacheMisc(cache, available));
+    }
+
     // Generate cache node filter group.
     static cacheNodeFilter(cache, igfss) {
         return this.toSection(this.generator.cacheNodeFilter(cache, igfss));
diff --git 
a/modules/web-console/frontend/app/configuration/generator/generator/Beans.js 
b/modules/web-console/frontend/app/configuration/generator/generator/Beans.js
index 3bd0c0f..7eae6f9 100644
--- 
a/modules/web-console/frontend/app/configuration/generator/generator/Beans.js
+++ 
b/modules/web-console/frontend/app/configuration/generator/generator/Beans.js
@@ -260,6 +260,13 @@ export class Bean extends EmptyBean {
         return this._property(this.properties, 'PATH', model, name, nonEmpty);
     }
 
+    pathArrayProperty(id, name, items, varArg) {
+        if (items && items.length)
+            this.properties.push({clsName: 'PATH_ARRAY', id, name, items, 
varArg, typeClsName: 'PATH'});
+
+        return this;
+    }
+
     classProperty(model, name = model) {
         return this._property(this.properties, 'java.lang.Class', model, name, 
nonEmpty);
     }
diff --git 
a/modules/web-console/frontend/app/configuration/generator/generator/ConfigurationGenerator.js
 
b/modules/web-console/frontend/app/configuration/generator/generator/ConfigurationGenerator.js
index 973db07..26833be 100644
--- 
a/modules/web-console/frontend/app/configuration/generator/generator/ConfigurationGenerator.js
+++ 
b/modules/web-console/frontend/app/configuration/generator/generator/ConfigurationGenerator.js
@@ -123,7 +123,7 @@ export default class IgniteConfigurationGenerator {
             this.clusterQuery(cluster, available, cfg);
 
         this.clusterServiceConfiguration(cluster.serviceConfigurations, 
cluster.caches, cfg);
-        this.clusterSsl(cluster, cfg);
+        this.clusterSsl(cluster, available, cfg);
 
         // Deprecated in ignite 2.0
         if (available(['1.0.0', '2.0.0']))
@@ -1784,7 +1784,7 @@ export default class IgniteConfigurationGenerator {
     }
 
     // Java code generator for cluster's SSL configuration.
-    static clusterSsl(cluster, cfg = this.igniteConfigurationBean(cluster)) {
+    static clusterSsl(cluster, available, cfg = 
this.igniteConfigurationBean(cluster)) {
         if (cluster.sslEnabled && nonNil(cluster.sslContextFactory)) {
             const bean = new Bean('org.apache.ignite.ssl.SslContextFactory', 
'sslCtxFactory',
                 cluster.sslContextFactory);
@@ -1812,6 +1812,11 @@ export default class IgniteConfigurationGenerator {
                 bean.intProperty('trustStoreType');
             }
 
+            if (available('2.7.0')) {
+                bean.varArgProperty('cipherSuites', 'cipherSuites', 
cluster.sslContextFactory.cipherSuites)
+                    .varArgProperty('protocols', 'protocols', 
cluster.sslContextFactory.protocols);
+            }
+
             cfg.beanProperty('sslContextFactory', bean);
         }
 
@@ -2132,6 +2137,29 @@ export default class IgniteConfigurationGenerator {
         return ccfg;
     }
 
+    // Generate key configurations of cache.
+    static cacheKeyConfiguration(keyCfgs, available, cfg = 
this.igniteConfigurationBean()) {
+        if (available('2.1.0')) {
+            const items = _.reduce(keyCfgs, (acc, keyCfg) => {
+                if (keyCfg.typeName && keyCfg.affinityKeyFieldName) {
+                    acc.push(new 
Bean('org.apache.ignite.cache.CacheKeyConfiguration', null, keyCfg)
+                        .stringConstructorArgument('typeName')
+                        .stringConstructorArgument('affinityKeyFieldName'));
+                }
+
+                return acc;
+            }, []);
+
+            if (_.isEmpty(items))
+                return cfg;
+
+            cfg.arrayProperty('keyConfiguration', 'keyConfiguration', items,
+                'org.apache.ignite.cache.CacheKeyConfiguration');
+        }
+
+        return cfg;
+    }
+
     // Generate cache memory group.
     static cacheMemory(cache, available, ccfg = 
this.cacheConfigurationBean(cache)) {
         // Since ignite 2.0
@@ -2172,6 +2200,15 @@ export default class IgniteConfigurationGenerator {
                 .boolProperty('swapEnabled');
         }
 
+        if (cache.cacheWriterFactory)
+            ccfg.beanProperty('cacheWriterFactory', new 
EmptyBean(cache.cacheWriterFactory));
+
+        if (cache.cacheLoaderFactory)
+            ccfg.beanProperty('cacheLoaderFactory', new 
EmptyBean(cache.cacheLoaderFactory));
+
+        if (cache.expiryPolicyFactory)
+            ccfg.beanProperty('expiryPolicyFactory', new 
EmptyBean(cache.expiryPolicyFactory));
+
         return ccfg;
     }
 
@@ -2207,6 +2244,13 @@ export default class IgniteConfigurationGenerator {
                 .intProperty('sqlIndexMaxInlineSize');
         }
 
+        if (available('2.4.0') && cache.sqlOnheapCacheEnabled) {
+            ccfg.boolProperty('sqlOnheapCacheEnabled')
+                .intProperty('sqlOnheapCacheMaxSize');
+        }
+
+        ccfg.intProperty('maxQueryIteratorsCount');
+
         return ccfg;
     }
 
@@ -2301,7 +2345,8 @@ export default class IgniteConfigurationGenerator {
                 ccfg.beanProperty('cacheStoreFactory', bean);
         }
 
-        ccfg.boolProperty('storeKeepBinary')
+        ccfg.intProperty('storeConcurrentLoadAllThreshold')
+            .boolProperty('storeKeepBinary')
             .boolProperty('loadPreviousValue')
             .boolProperty('readThrough')
             .boolProperty('writeThrough');
@@ -2399,6 +2444,31 @@ export default class IgniteConfigurationGenerator {
         return ccfg;
     }
 
+    // Generate miscellaneous configuration.
+    static cacheMisc(cache, available, cfg = 
this.cacheConfigurationBean(cache)) {
+        if (cache.interceptor)
+            cfg.beanProperty('interceptor', new EmptyBean(cache.interceptor));
+
+        if (available('2.0.0'))
+            cfg.boolProperty('storeByValue');
+
+        cfg.boolProperty('eagerTtl');
+
+        if (available('2.7.0'))
+            cfg.boolProperty('encryptionEnabled');
+
+        if (available('2.5.0'))
+            cfg.boolProperty('eventsDisabled');
+
+        if (cache.cacheStoreSessionListenerFactories) {
+            const factories = _.map(cache.cacheStoreSessionListenerFactories, 
(factory) => new EmptyBean(factory));
+
+            cfg.varArgProperty('cacheStoreSessionListenerFactories', 
'cacheStoreSessionListenerFactories', factories, 
'javax.cache.configuration.Factory');
+        }
+
+        return cfg;
+    }
+
     // Generate server near cache group.
     static cacheNearServer(cache, available, ccfg = 
this.cacheConfigurationBean(cache)) {
         if (ccfg.valueOf('cacheMode') === 'PARTITIONED' && _.get(cache, 
'nearConfiguration.enabled')) {
@@ -2463,11 +2533,13 @@ export default class IgniteConfigurationGenerator {
         this.cacheMemory(cache, available, ccfg);
         this.cacheQuery(cache, cache.domains, available, ccfg);
         this.cacheStore(cache, cache.domains, available, deps, ccfg);
+        this.cacheKeyConfiguration(cache.keyConfiguration, available, ccfg);
 
         const igfs = _.get(cache, 'nodeFilter.IGFS.instance');
         this.cacheNodeFilter(cache, igfs ? [igfs] : [], ccfg);
         this.cacheConcurrency(cache, available, ccfg);
         this.cacheRebalance(cache, ccfg);
+        this.cacheMisc(cache, available, ccfg);
         this.cacheNearServer(cache, available, ccfg);
         this.cacheStatistics(cache, ccfg);
         this.cacheDomains(cache.domains, available, ccfg);
@@ -2493,6 +2565,48 @@ export default class IgniteConfigurationGenerator {
         return cfg;
     }
 
+    static _userNameMapperBean(mapper) {
+        let bean = null;
+
+        switch (mapper.kind) {
+            case 'Chained':
+                bean = new 
Bean('org.apache.ignite.hadoop.util.ChainedUserNameMapper', 'mameMapper', 
mapper.Chained);
+
+                bean.arrayProperty('mappers', 'mappers',
+                    _.map(_.get(mapper, 'Chained.mappers'), 
IgniteConfigurationGenerator._userNameMapperBean),
+                    'org.apache.ignite.hadoop.util.UserNameMapper');
+
+                break;
+
+            case 'Basic':
+                bean = new 
Bean('org.apache.ignite.hadoop.util.BasicUserNameMapper', 'mameMapper', 
mapper.Basic, igfsDflts.secondaryFileSystem.userNameMapper.Basic);
+
+                bean.stringProperty('defaultUserName')
+                    .boolProperty('useDefaultUserName')
+                    .mapProperty('mappings', 'mappings');
+
+                break;
+
+            case 'Kerberos':
+                bean = new 
Bean('org.apache.ignite.hadoop.util.KerberosUserNameMapper', 'nameMapper', 
mapper.Kerberos);
+
+                bean.stringProperty('instance')
+                    .stringProperty('realm');
+
+                break;
+
+            case 'Custom':
+                if (_.get(mapper, 'Custom.className'))
+                    bean = new EmptyBean(mapper.Custom.className);
+
+                break;
+
+            default:
+        }
+
+        return bean;
+    }
+
     // Generate IGFS secondary file system group.
     static igfsSecondFS(igfs, cfg = this.igfsConfigurationBean(igfs)) {
         if (igfs.secondaryFileSystemEnabled) {
@@ -2503,11 +2617,46 @@ export default class IgniteConfigurationGenerator {
 
             bean.stringProperty('userName', 'defaultUserName');
 
-            const factoryBean = new 
Bean('org.apache.ignite.hadoop.fs.CachingHadoopFileSystemFactory',
-                'fac', secondFs);
+            let factoryBean = null;
 
-            factoryBean.stringProperty('uri')
-                .pathProperty('cfgPath', 'configPaths');
+            switch (secondFs.kind || 'Caching') {
+                case 'Caching':
+                    factoryBean = new 
Bean('org.apache.ignite.hadoop.fs.CachingHadoopFileSystemFactory', 'fac', 
secondFs);
+                    break;
+
+                case 'Kerberos':
+                    factoryBean = new 
Bean('org.apache.ignite.hadoop.fs.KerberosHadoopFileSystemFactory', 'fac', 
secondFs, igfsDflts.secondaryFileSystem);
+                    break;
+
+                case 'Custom':
+                    if (_get(secondFs, 'Custom.className'))
+                        factoryBean = new Bean(secondFs.Custom.className, 
'fac', null);
+
+                    break;
+
+                default:
+            }
+
+            if (!factoryBean)
+                return cfg;
+
+            if (secondFs.kind !== 'Custom') {
+                factoryBean.stringProperty('uri')
+                    .pathArrayProperty('cfgPaths', 'configPaths', 
secondFs.cfgPaths, true);
+
+                if (secondFs.kind === 'Kerberos') {
+                    factoryBean.stringProperty('Kerberos.keyTab', 'keyTab')
+                        .stringProperty('Kerberos.keyTabPrincipal', 
'keyTabPrincipal')
+                        .longProperty('Kerberos.reloginInterval', 
'reloginInterval');
+                }
+
+                if (_.get(secondFs, 'userNameMapper.kind')) {
+                    const mapper = 
IgniteConfigurationGenerator._userNameMapperBean(secondFs.userNameMapper);
+
+                    if (mapper)
+                        factoryBean.beanProperty('userNameMapper', mapper);
+                }
+            }
 
             bean.beanProperty('fileSystemFactory', factoryBean);
 
diff --git 
a/modules/web-console/frontend/app/configuration/generator/generator/JavaTransformer.service.js
 
b/modules/web-console/frontend/app/configuration/generator/generator/JavaTransformer.service.js
index 9ea1e7f..fdaf829 100644
--- 
a/modules/web-console/frontend/app/configuration/generator/generator/JavaTransformer.service.js
+++ 
b/modules/web-console/frontend/app/configuration/generator/generator/JavaTransformer.service.js
@@ -400,6 +400,7 @@ export default class IgniteJavaTransformer extends 
AbstractTransformer {
                 case 'java.lang.String':
                     return `"${item.replace(/\\/g, '\\\\').replace(/"/g, 
'\\"')}"`;
                 case 'PATH':
+                case 'PATH_ARRAY':
                     return `"${item.replace(/\\/g, '\\\\')}"`;
                 case 'java.lang.Class':
                     return `${this.javaTypes.shortClassName(item)}.class`;
@@ -614,6 +615,13 @@ export default class IgniteJavaTransformer extends 
AbstractTransformer {
                         this._setArray(sb, id, prop, vars, limitLines);
 
                     break;
+                case 'PATH_ARRAY':
+                    if (prop.varArg)
+                        this._setVarArg(sb, id, prop, 
this._toObject(prop.clsName, prop.items), limitLines);
+                    else
+                        this._setArray(sb, id, prop, 
this._toObject(prop.clsName, prop.items), limitLines);
+
+                    break;
                 case 'COLLECTION':
                     const nonBean = !this._isBean(prop.typeClsName);
 
diff --git 
a/modules/web-console/frontend/app/configuration/generator/generator/Maven.service.js
 
b/modules/web-console/frontend/app/configuration/generator/generator/Maven.service.js
index 5442b79..83ffdeb 100644
--- 
a/modules/web-console/frontend/app/configuration/generator/generator/Maven.service.js
+++ 
b/modules/web-console/frontend/app/configuration/generator/generator/Maven.service.js
@@ -193,7 +193,7 @@ export default class IgniteMavenGenerator {
             if (_.get(cache, 'nodeFilter.kind') === 'Exclude')
                 this.addDependency(deps, 'org.apache.ignite', 
'ignite-extdata-p2p', igniteVer);
 
-            if (cache.diskPageCompression)
+            if (cache.diskPageCompression && versionService.since(igniteVer, 
'2.8.0'))
                 this.addDependency(deps, 'org.apache.ignite', 
'ignite-compress', igniteVer);
         });
 
diff --git 
a/modules/web-console/frontend/app/configuration/generator/generator/SpringTransformer.service.js
 
b/modules/web-console/frontend/app/configuration/generator/generator/SpringTransformer.service.js
index 21efd11..db9109b 100644
--- 
a/modules/web-console/frontend/app/configuration/generator/generator/SpringTransformer.service.js
+++ 
b/modules/web-console/frontend/app/configuration/generator/generator/SpringTransformer.service.js
@@ -100,6 +100,7 @@ export default class IgniteSpringTransformer extends 
AbstractTransformer {
                     return `${item}`;
                 case 'java.lang.String':
                 case 'PATH':
+                case 'PATH_ARRAY':
                     return this.escapeXml(item);
                 default:
                     return item;
@@ -209,6 +210,7 @@ export default class IgniteSpringTransformer extends 
AbstractTransformer {
 
                     break;
                 case 'ARRAY':
+                case 'PATH_ARRAY':
                 case 'COLLECTION':
                     this._setCollection(sb, prop);
 
diff --git 
a/modules/web-console/frontend/app/configuration/generator/generator/defaults/Cache.service.js
 
b/modules/web-console/frontend/app/configuration/generator/generator/defaults/Cache.service.js
index e3c69b6..ff06400 100644
--- 
a/modules/web-console/frontend/app/configuration/generator/generator/defaults/Cache.service.js
+++ 
b/modules/web-console/frontend/app/configuration/generator/generator/defaults/Cache.service.js
@@ -48,6 +48,7 @@ const DFLT_CACHE = {
             sqlEscapeAll: false
         }
     },
+    storeConcurrentLoadAllThreshold: 5,
     readThrough: false,
     writeThrough: false,
     writeBehindEnabled: false,
@@ -123,7 +124,13 @@ const DFLT_CACHE = {
     memoryPolicyName: 'default',
     diskPageCompression: {
         clsName: 'org.apache.ignite.configuration.DiskPageCompression'
-    }
+    },
+    sqlOnheapCacheEnabled: false,
+    sqlOnheapCacheMaxSize: 0,
+    storeByValue: false,
+    encryptionEnabled: false,
+    eventsDisabled: false,
+    maxQueryIteratorsCount: 1024
 };
 
 export default class IgniteCacheDefaults {
diff --git 
a/modules/web-console/frontend/app/configuration/generator/generator/defaults/IGFS.service.js
 
b/modules/web-console/frontend/app/configuration/generator/generator/defaults/IGFS.service.js
index ff72d50..056742a 100644
--- 
a/modules/web-console/frontend/app/configuration/generator/generator/defaults/IGFS.service.js
+++ 
b/modules/web-console/frontend/app/configuration/generator/generator/defaults/IGFS.service.js
@@ -21,7 +21,20 @@ const DFLT_IGFS = {
         value: 'DUAL_ASYNC'
     },
     secondaryFileSystem: {
-
+        userNameMapper: {
+            Basic: {
+                mappings: {
+                    keyClsName: 'java.lang.String',
+                    valClsName: 'java.lang.String',
+                    keyField: 'name',
+                    valField: 'value',
+                    entries: []
+                }
+            }
+        },
+        Kerberos: {
+            reloginInterval: 600000
+        }
     },
     ipcEndpointConfiguration: {
         type: {
diff --git a/modules/web-console/frontend/app/configuration/services/Caches.ts 
b/modules/web-console/frontend/app/configuration/services/Caches.ts
index 4a15c93..8ee2b48 100644
--- a/modules/web-console/frontend/app/configuration/services/Caches.ts
+++ b/modules/web-console/frontend/app/configuration/services/Caches.ts
@@ -69,7 +69,8 @@ export default class Caches {
             writeBehindCoalescing: true,
             nearConfiguration: {},
             sqlFunctionClasses: [],
-            domains: []
+            domains: [],
+            eagerTtl: true
         };
     }
 
diff --git a/modules/web-console/frontend/app/configuration/services/IGFSs.ts 
b/modules/web-console/frontend/app/configuration/services/IGFSs.ts
index b4c3039..3cfa99e 100644
--- a/modules/web-console/frontend/app/configuration/services/IGFSs.ts
+++ b/modules/web-console/frontend/app/configuration/services/IGFSs.ts
@@ -41,7 +41,10 @@ export default class IGFSs {
             ipcEndpointEnabled: true,
             fragmentizerEnabled: true,
             colocateMetadata: true,
-            relaxedConsistency: true
+            relaxedConsistency: true,
+            secondaryFileSystem: {
+                kind: 'Caching'
+            }
         };
     }
 
@@ -76,4 +79,15 @@ export default class IGFSs {
     };
 
     normalize = omit(['__v', 'space', 'clusters']);
+
+    addSecondaryFsNameMapper(igfs) {
+        if (!_.get(igfs, 'secondaryFileSystem.userNameMapper.Chained.mappers'))
+            _.set(igfs, 'secondaryFileSystem.userNameMapper.Chained.mappers', 
[]);
+
+        const item = {_id: ObjectID.generate(), kind: 'Basic'};
+
+        _.get(igfs, 
'secondaryFileSystem.userNameMapper.Chained.mappers').push(item);
+
+        return item;
+    }
 }
diff --git 
a/modules/web-console/src/test/java/org/apache/ignite/console/configuration/WebConsoleConfigurationSelfTest.java
 
b/modules/web-console/src/test/java/org/apache/ignite/console/configuration/WebConsoleConfigurationSelfTest.java
index c15b4c7..4665fee 100644
--- 
a/modules/web-console/src/test/java/org/apache/ignite/console/configuration/WebConsoleConfigurationSelfTest.java
+++ 
b/modules/web-console/src/test/java/org/apache/ignite/console/configuration/WebConsoleConfigurationSelfTest.java
@@ -24,6 +24,7 @@ import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 import org.apache.ignite.binary.BinaryTypeConfiguration;
+import org.apache.ignite.cache.CacheKeyConfiguration;
 import org.apache.ignite.cache.QueryEntity;
 import org.apache.ignite.cache.QueryIndex;
 import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction;
@@ -54,7 +55,11 @@ import 
org.apache.ignite.configuration.SqlConnectorConfiguration;
 import org.apache.ignite.configuration.TransactionConfiguration;
 import org.apache.ignite.hadoop.fs.CachingHadoopFileSystemFactory;
 import org.apache.ignite.hadoop.fs.IgniteHadoopIgfsSecondaryFileSystem;
+import org.apache.ignite.hadoop.fs.KerberosHadoopFileSystemFactory;
 import org.apache.ignite.hadoop.mapreduce.IgniteHadoopWeightedMapReducePlanner;
+import org.apache.ignite.hadoop.util.BasicUserNameMapper;
+import org.apache.ignite.hadoop.util.ChainedUserNameMapper;
+import org.apache.ignite.hadoop.util.KerberosUserNameMapper;
 import org.apache.ignite.igfs.IgfsGroupDataBlocksKeyMapper;
 import org.apache.ignite.igfs.IgfsIpcEndpointConfiguration;
 import org.apache.ignite.internal.marshaller.optimized.OptimizedMarshaller;
@@ -167,7 +172,6 @@ public class WebConsoleConfigurationSelfTest {
         igniteCfgProps.add("serviceThreadPoolSize");
         igniteCfgProps.add("managementThreadPoolSize");
         igniteCfgProps.add("igfsThreadPoolSize");
-        igniteCfgProps.add("rebalanceThreadPoolSize");
         igniteCfgProps.add("utilityCacheThreadPoolSize");
         igniteCfgProps.add("utilityCacheKeepAliveTime");
         igniteCfgProps.add("asyncCallbackPoolSize");
@@ -208,6 +212,12 @@ public class WebConsoleConfigurationSelfTest {
         metadata.put(IgniteConfiguration.class,
             new MetadataInfo(igniteCfgProps, igniteCfgPropsDep, 
igniteCfgPropsExcl));
 
+        Set<String> cacheKeyCfgProps = new HashSet<>();
+        cacheKeyCfgProps.add("typeName");
+        cacheKeyCfgProps.add("affinityKeyFieldName");
+
+        metadata.put(CacheKeyConfiguration.class, new 
MetadataInfo(cacheKeyCfgProps, EMPTY_FIELDS, EMPTY_FIELDS));
+
         Set<String> atomicCfgProps = new HashSet<>();
         atomicCfgProps.add("cacheMode");
         atomicCfgProps.add("atomicSequenceReserveSize");
@@ -619,6 +629,8 @@ public class WebConsoleConfigurationSelfTest {
         // Only on code generation.
         sslCfgProps.add("trustStorePassword");
         sslCfgProps.add("trustStoreType");
+        sslCfgProps.add("cipherSuites");
+        sslCfgProps.add("protocols");
         metadata.put(SslContextFactory.class, new MetadataInfo(sslCfgProps, 
EMPTY_FIELDS, EMPTY_FIELDS));
 
         Set<String> executorProps = new HashSet<>();
@@ -646,7 +658,7 @@ public class WebConsoleConfigurationSelfTest {
         cacheCfgProps.add("partitionLossPolicy");
         cacheCfgProps.add("readFromBackup");
         cacheCfgProps.add("copyOnRead");
-        cacheCfgProps.add("isInvalidate");
+        cacheCfgProps.add("invalidate");
         cacheCfgProps.add("affinityMapper");
         cacheCfgProps.add("topologyValidator");
         cacheCfgProps.add("maxConcurrentAsyncOperations");
@@ -658,7 +670,7 @@ public class WebConsoleConfigurationSelfTest {
         // cacheCfgProps.add("memoryMode");
         // cacheCfgProps.add("offHeapMode");
         // cacheCfgProps.add("offHeapMaxMemory");
-        cacheCfgProps.add("evictionPolicy");
+        cacheCfgProps.add("evictionPolicyFactory");
         cacheCfgProps.add("evictionFilter");
         // Removed since 2.0.
         // cacheCfgProps.add("startSize");
@@ -696,15 +708,37 @@ public class WebConsoleConfigurationSelfTest {
         cacheCfgProps.add("indexedTypes");
         cacheCfgProps.add("queryEntities");
         cacheCfgProps.add("pluginConfigurations");
+        cacheCfgProps.add("cacheWriterFactory");
+        cacheCfgProps.add("cacheLoaderFactory");
+        cacheCfgProps.add("expiryPolicyFactory");
+        cacheCfgProps.add("storeConcurrentLoadAllThreshold");
+        cacheCfgProps.add("sqlIndexMaxInlineSize");
+        cacheCfgProps.add("sqlOnheapCacheEnabled");
+        cacheCfgProps.add("sqlOnheapCacheMaxSize");
+        cacheCfgProps.add("diskPageCompression");
+        cacheCfgProps.add("diskPageCompressionLevel");
+        cacheCfgProps.add("interceptor");
+        cacheCfgProps.add("storeByValue");
+        cacheCfgProps.add("eagerTtl");
+        cacheCfgProps.add("encryptionEnabled");
+        cacheCfgProps.add("eventsDisabled");
+        cacheCfgProps.add("maxQueryIteratorsCount");
+        cacheCfgProps.add("keyConfiguration");
+        cacheCfgProps.add("cacheStoreSessionListenerFactories");
+        cacheCfgProps.add("affinity");
 
         Set<String> cacheCfgPropsDep = new HashSet<>();
         // Removed since 2.0.
         // cacheCfgPropsDep.add("atomicWriteOrderMode");
         cacheCfgPropsDep.add("memoryPolicyName");
         cacheCfgPropsDep.add("longQueryWarningTimeout");
+        cacheCfgPropsDep.add("rebalanceThreadPoolSize");
+        cacheCfgPropsDep.add("transactionManagerLookupClassName");
+        cacheCfgPropsDep.add("evictionPolicy");
 
         Set<String> cacheCfgPropsExcl = new HashSet<>();
         cacheCfgPropsExcl.add("nodeFilter");
+        cacheCfgPropsExcl.add("types");
 
         metadata.put(CacheConfiguration.class, new MetadataInfo(cacheCfgProps, 
cacheCfgPropsDep, cacheCfgPropsExcl));
 
@@ -815,9 +849,38 @@ public class WebConsoleConfigurationSelfTest {
         Set<String> cachingIgfsCfgProps = new HashSet<>();
         cachingIgfsCfgProps.add("uri");
         cachingIgfsCfgProps.add("configPaths");
+        cachingIgfsCfgProps.add("userNameMapper");
 
         metadata.put(CachingHadoopFileSystemFactory.class, new 
MetadataInfo(cachingIgfsCfgProps, EMPTY_FIELDS, EMPTY_FIELDS));
 
+        Set<String> kerberosIgfsCfgProps = new HashSet<>();
+        kerberosIgfsCfgProps.add("uri");
+        kerberosIgfsCfgProps.add("configPaths");
+        kerberosIgfsCfgProps.add("userNameMapper");
+        kerberosIgfsCfgProps.add("keyTab");
+        kerberosIgfsCfgProps.add("keyTabPrincipal");
+        kerberosIgfsCfgProps.add("reloginInterval");
+
+        metadata.put(KerberosHadoopFileSystemFactory.class, new 
MetadataInfo(kerberosIgfsCfgProps, EMPTY_FIELDS, EMPTY_FIELDS));
+
+        Set<String> chainedIgfsUsrNameMapperProps = new HashSet<>();
+        chainedIgfsUsrNameMapperProps.add("mappers");
+
+        metadata.put(ChainedUserNameMapper.class, new 
MetadataInfo(chainedIgfsUsrNameMapperProps, EMPTY_FIELDS, EMPTY_FIELDS));
+
+        Set<String> basicIgfsUsrNameMapperProps = new HashSet<>();
+        basicIgfsUsrNameMapperProps.add("defaultUserName");
+        basicIgfsUsrNameMapperProps.add("useDefaultUserName");
+        basicIgfsUsrNameMapperProps.add("mappings");
+
+        metadata.put(BasicUserNameMapper.class, new 
MetadataInfo(basicIgfsUsrNameMapperProps, EMPTY_FIELDS, EMPTY_FIELDS));
+
+        Set<String> kerberosIgfsUsrNameMapperProps = new HashSet<>();
+        kerberosIgfsUsrNameMapperProps.add("instance");
+        kerberosIgfsUsrNameMapperProps.add("realm");
+
+        metadata.put(KerberosUserNameMapper.class, new 
MetadataInfo(kerberosIgfsUsrNameMapperProps, EMPTY_FIELDS, EMPTY_FIELDS));
+
         Set<String> ipcEndpointProps = new HashSet<>();
         ipcEndpointProps.add("type");
         ipcEndpointProps.add("host");

Reply via email to