diff --git a/doc/source/install/developer/deploy-with-tungsten-fabric.rst b/doc/source/install/developer/deploy-with-tungsten-fabric.rst
new file mode 100644
index 0000000000..bca1aa13f9
--- /dev/null
+++ b/doc/source/install/developer/deploy-with-tungsten-fabric.rst
@@ -0,0 +1,147 @@
+===============================
+Deployment with Tungsten Fabric
+===============================
+
+Intro
+^^^^^
+
+Tungsten Fabric is the multicloud and multistack network solution which you can
+use for your OpenStack as a network plugin. This document decribes how you can deploy
+a single node Open Stack based on Tungsten Fabric using openstack helm for development purpose.
+
+Prepare host
+^^^^^^^^^^^^
+
+First you have to set up OpenStack and Linux versions and install needed packages
+
+.. code-block:: shell
+
+  export OPENSTACK_RELEASE=train
+  export CONTAINER_DISTRO_NAME=ubuntu
+  export CONTAINER_DISTRO_VERSION=bionic
+  sudo apt update -y
+  sudo apt install -y resolvconf
+  cd ~/openstack-helm
+
+Install OpenStack packages
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: shell
+
+  ./tools/deployment/common/install-packages.sh
+
+Install k8s Minikube
+^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: shell
+
+  ./tools/deployment/common/deploy-k8s.sh
+
+Setup DNS for use cluster DNS
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: shell
+
+  dns_cluster_ip=`kubectl get svc kube-dns -n kube-system --no-headers -o custom-columns=":spec.clusterIP"`
+  echo "nameserver ${dns_cluster_ip}" | sudo tee -a /etc/resolvconf/resolv.conf.d/head > /dev/null
+  sudo dpkg-reconfigure --force resolvconf
+  sudo systemctl restart resolvconf
+
+
+Setup env for apply values_overrides
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: shell
+
+  export FEATURE_GATES=tf
+
+Setup OpenStack client
+^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: shell
+
+  ./tools/deployment/common/setup-client.sh
+
+Setup Ingress
+^^^^^^^^^^^^^
+
+.. code-block:: shell
+
+  ./tools/deployment/component/common/ingress.sh
+
+Setup MariaDB
+^^^^^^^^^^^^^
+
+.. code-block:: shell
+
+  ./tools/deployment/component/common/mariadb.sh
+
+Setup Memcached
+^^^^^^^^^^^^^^^
+
+.. code-block:: shell
+
+  ./tools/deployment/component/common/memcached.sh
+
+Setup RabbitMQ
+^^^^^^^^^^^^^^
+
+.. code-block:: shell
+
+  ./tools/deployment/component/common/rabbitmq.sh
+
+Setup NFS
+^^^^^^^^^
+
+.. code-block:: shell
+
+  ./tools/deployment/component/nfs-provisioner/nfs-provisioner.sh
+
+Setup Keystone
+^^^^^^^^^^^^^^
+
+.. code-block:: shell
+
+  ./tools/deployment/component/keystone/keystone.sh
+
+Setup Heat
+^^^^^^^^^^
+
+.. code-block:: shell
+
+  ./tools/deployment/component/heat/heat.sh
+
+Setup Glance
+^^^^^^^^^^^^
+
+.. code-block:: shell
+
+  ./tools/deployment/component/glance/glance.sh
+
+Prepare host and openstack helm for tf
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: shell
+
+  ./tools/deployment/component/compute-kit/tungsten-fabric.sh prepare
+
+Setup libvirt
+^^^^^^^^^^^^^
+
+.. code-block:: shell
+
+  ./tools/deployment/component/compute-kit/libvirt.sh
+
+Setup Neutron and Nova
+^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: shell
+
+  ./tools/deployment/component/compute-kit/compute-kit.sh
+
+Setup Tungsten Fabric
+^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: shell
+
+  ./tools/deployment/component/compute-kit/tungsten-fabric.sh deploy
\ No newline at end of file
diff --git a/doc/source/install/developer/index.rst b/doc/source/install/developer/index.rst
index ed4498a35e..8b2d75588a 100644
--- a/doc/source/install/developer/index.rst
+++ b/doc/source/install/developer/index.rst
@@ -9,6 +9,7 @@ Contents:
    requirements-and-host-config
    kubernetes-and-common-setup
    deploy-with-nfs
+   deploy-with-tungsten-fabric
    deploy-with-ceph
    deploy-ovs-dpdk.rst
    exercise-the-cloud
diff --git a/neutron/templates/bin/_db-sync.sh.tpl b/neutron/templates/bin/_db-sync.sh.tpl
index cfaaec0a9a..58edecfcd0 100644
--- a/neutron/templates/bin/_db-sync.sh.tpl
+++ b/neutron/templates/bin/_db-sync.sh.tpl
@@ -18,7 +18,11 @@ set -ex
 
 neutron-db-manage \
   --config-file /etc/neutron/neutron.conf \
+{{- if ( has "tungstenfabric" .Values.network.backend ) }}
+  --config-file /etc/neutron/plugins/tungstenfabric/tf_plugin.ini \
+{{- else }}
   --config-file /etc/neutron/plugins/ml2/ml2_conf.ini \
+{{- end }}
   upgrade head
 
 {{- if .Values.conf.plugins.taas.taas.enabled }}
diff --git a/neutron/templates/bin/_neutron-server.sh.tpl b/neutron/templates/bin/_neutron-server.sh.tpl
index 51d0c5c5e2..83ca918658 100644
--- a/neutron/templates/bin/_neutron-server.sh.tpl
+++ b/neutron/templates/bin/_neutron-server.sh.tpl
@@ -20,7 +20,11 @@ COMMAND="${@:-start}"
 function start () {
   exec neutron-server \
         --config-file /etc/neutron/neutron.conf \
+{{- if ( has "tungstenfabric" .Values.network.backend ) }}
+        --config-file /etc/neutron/plugins/tungstenfabric/tf_plugin.ini
+{{- else }}
         --config-file /etc/neutron/plugins/ml2/ml2_conf.ini
+{{- end }}
 {{- if .Values.conf.plugins.taas.taas.enabled }} \
         --config-file /etc/neutron/taas_plugin.ini
 {{- end }}
diff --git a/neutron/templates/configmap-bin.yaml b/neutron/templates/configmap-bin.yaml
index f3299a55ee..3cb1ee4a24 100644
--- a/neutron/templates/configmap-bin.yaml
+++ b/neutron/templates/configmap-bin.yaml
@@ -91,4 +91,8 @@ data:
 {{- include "helm-toolkit.scripts.rabbit_init" . | indent 4 }}
   neutron-test-force-cleanup.sh: |
 {{ tuple "bin/_neutron-test-force-cleanup.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
+{{- if ( has "tungstenfabric" .Values.network.backend ) }}
+  tf-plugin.pth: |
+    /opt/plugin/site-packages
+{{- end }}
 {{- end }}
diff --git a/neutron/templates/configmap-etc.yaml b/neutron/templates/configmap-etc.yaml
index 27e207813d..719f82c586 100644
--- a/neutron/templates/configmap-etc.yaml
+++ b/neutron/templates/configmap-etc.yaml
@@ -212,6 +212,31 @@ just set it along with nova_metadata_host.
 {{- $_ := set .Values.conf.neutron.ironic "password" .Values.endpoints.identity.auth.ironic.password -}}
 {{- end -}}
 {{- end -}}
+
+{{- if ( has "tungstenfabric" .Values.network.backend ) -}}
+{{- if empty .Values.conf.plugins.tungstenfabric.KEYSTONE.auth_url -}}
+{{- $_ := tuple "identity" "internal" "api" . | include "helm-toolkit.endpoints.keystone_endpoint_uri_lookup" | set .Values.conf.plugins.tungstenfabric.KEYSTONE "auth_url" -}}
+{{- end -}}
+{{- if empty .Values.conf.plugins.tungstenfabric.KEYSTONE.admin_user -}}
+{{- $_ := set .Values.conf.plugins.tungstenfabric.KEYSTONE "admin_user" .Values.endpoints.identity.auth.admin.username -}}
+{{- end -}}
+{{- if empty .Values.conf.plugins.tungstenfabric.KEYSTONE.admin_password -}}
+{{- $_ := set .Values.conf.plugins.tungstenfabric.KEYSTONE "admin_password" .Values.endpoints.identity.auth.admin.password -}}
+{{- end -}}
+{{- if empty .Values.conf.plugins.tungstenfabric.KEYSTONE.admin_tenant_name -}}
+{{- $_ := set .Values.conf.plugins.tungstenfabric.KEYSTONE "admin_tenant_name" .Values.endpoints.identity.auth.admin.project_name -}}
+{{- end -}}
+{{- if empty .Values.conf.plugins.tf_vnc_api_lib.auth.AUTHN_SERVER -}}
+{{- $_ := tuple "identity" . | include "helm-toolkit.endpoints.keystone_endpoint_name_lookup" | set .Values.conf.plugins.tf_vnc_api_lib.auth "AUTHN_SERVER" -}}
+{{- end -}}
+{{- if empty .Values.conf.plugins.tf_vnc_api_lib.auth.AUTHN_PORT -}}
+{{- $_ := tuple "identity" "internal" "api" . | include "helm-toolkit.endpoints.endpoint_port_lookup" | set .Values.conf.plugins.tf_vnc_api_lib.auth "AUTHN_PORT" -}}
+{{- end -}}
+{{- if empty .Values.conf.plugins.tf_vnc_api_lib.auth.AUTHN_DOMAIN -}}
+{{- $_ := set .Values.conf.plugins.tf_vnc_api_lib.auth "AUTHN_DOMAIN" .Values.endpoints.identity.auth.neutron.project_domain_name -}}
+{{- end -}}
+{{- end -}}
+
 ---
 apiVersion: v1
 kind: Secret
@@ -240,6 +265,8 @@ data:
   sriov_agent.ini: {{ include "helm-toolkit.utils.to_oslo_conf" $envAll.Values.conf.plugins.sriov_agent | b64enc }}
   l2gw_agent.ini: {{ default "\"\"" (include "helm-toolkit.utils.to_oslo_conf" .Values.conf.l2gateway_agent | b64enc) }}
   bagpipe_bgp.conf: {{ default "\"\"" (include "helm-toolkit.utils.to_oslo_conf" .Values.conf.bagpipe_bgp | b64enc) }}
+  tf_plugin.ini: {{ include "helm-toolkit.utils.to_oslo_conf" $envAll.Values.conf.plugins.tungstenfabric | b64enc }}
+  vnc_api_lib.ini: {{ include "helm-toolkit.utils.to_oslo_conf" $envAll.Values.conf.plugins.tf_vnc_api_lib | b64enc }}
   dnsmasq.conf: ""
   neutron_sudoers: {{ $envAll.Values.conf.neutron_sudoers | b64enc }}
   rootwrap.conf: {{ $envAll.Values.conf.rootwrap | b64enc }}
diff --git a/neutron/templates/deployment-server.yaml b/neutron/templates/deployment-server.yaml
index e39fd3f0ba..74c9d3f18d 100644
--- a/neutron/templates/deployment-server.yaml
+++ b/neutron/templates/deployment-server.yaml
@@ -66,6 +66,20 @@ spec:
       terminationGracePeriodSeconds: {{ .Values.pod.lifecycle.termination_grace_period.server.timeout | default "30" }}
       initContainers:
 {{ tuple $envAll "pod_dependency" $mounts_neutron_server_init | include "helm-toolkit.snippets.kubernetes_entrypoint_init_container" | indent 8 }}
+        {{- if ( has "tungstenfabric" .Values.network.backend ) }}
+        - name: tungstenfabric-neutron-init
+          image: {{ .Values.images.tags.tf_neutron_init }}
+          imagePullPolicy: {{ .Values.images.pull_policy }}
+{{ tuple $envAll $envAll.Values.pod.resources.server | include "helm-toolkit.snippets.kubernetes_resources" | indent 10 }}
+          securityContext:
+            runAsUser: {{ .Values.pod.security_context.neutron_server.pod.runAsUser }}
+          env:
+            - name: OPENSTACK_VERSION
+              value: "{{ .Values.conf.openstack_version }}"
+          volumeMounts:
+            - name: neutron-plugin-shared
+              mountPath: /opt/plugin
+        {{- end }}
       containers:
         - name: neutron-server
 {{ tuple $envAll "neutron_server" | include "helm-toolkit.snippets.image" | indent 10 }}
@@ -108,10 +122,35 @@ spec:
               mountPath: /etc/neutron/api_audit_map.conf
               subPath: api_audit_map.conf
               readOnly: true
+            {{- if( has "tungstenfabric" .Values.network.backend ) }}
+            - name: neutron-etc
+              mountPath: /etc/neutron/plugins/tungstenfabric/tf_plugin.ini
+              subPath: tf_plugin.ini
+              readOnly: true
+            - name: neutron-etc
+              mountPath: /etc/contrail/vnc_api_lib.ini
+              subPath: vnc_api_lib.ini
+              readOnly: true
+            - name: neutron-plugin-shared
+              mountPath: /opt/plugin
+            - name: neutron-bin
+              mountPath: /usr/local/lib/python2.7/site-packages/tf-plugin.pth
+              subPath: tf-plugin.pth
+              readOnly: true
+            - name: neutron-bin
+              mountPath: /var/lib/openstack/lib/python2.7/site-packages/tf-plugin.pth
+              subPath: tf-plugin.pth
+              readOnly: true
+            - name: neutron-bin
+              mountPath: /var/lib/openstack/lib/python3.6/site-packages/tf-plugin.pth
+              subPath: tf-plugin.pth
+              readOnly: true
+            {{- else }}
             - name: neutron-etc
               mountPath: /etc/neutron/plugins/ml2/ml2_conf.ini
               subPath: ml2_conf.ini
               readOnly: true
+            {{- end }}
             {{ if ( has "sriov" .Values.network.backend ) }}
             - name: neutron-etc
               mountPath: /etc/neutron/plugins/ml2/sriov_agent.ini
@@ -152,5 +191,9 @@ spec:
           secret:
             secretName: neutron-etc
             defaultMode: 0444
+        {{- if ( has "tungstenfabric" .Values.network.backend ) }}
+        - name: neutron-plugin-shared
+          emptyDir: {}
+        {{- end }}
 {{ if $mounts_neutron_server.volumes }}{{ toYaml $mounts_neutron_server.volumes | indent 8 }}{{ end }}
 {{- end }}
diff --git a/neutron/values_overrides/tf.yaml b/neutron/values_overrides/tf.yaml
new file mode 100644
index 0000000000..463c6224f1
--- /dev/null
+++ b/neutron/values_overrides/tf.yaml
@@ -0,0 +1,70 @@
+---
+images:
+  tags:
+    tf_neutron_init: opencontrailnightly/contrail-openstack-neutron-init:master-latest
+labels:
+  job:
+    node_selector_key: openstack-control-plane
+    node_selector_value: enabled
+  server:
+    node_selector_key: openstack-control-plane
+    node_selector_value: enabled
+  test:
+    node_selector_key: openstack-control-plane
+    node_selector_value: enabled
+network:
+  backend:
+    - tungstenfabric
+dependencies:
+  dynamic:
+    targeted:
+      tungstenfabric:
+        server:
+          daemonset: []
+conf:
+  openstack_version: queens
+  neutron:
+    DEFAULT:
+      core_plugin: neutron_plugin_contrail.plugins.opencontrail.contrail_plugin.NeutronPluginContrailCoreV2
+      service_plugins: neutron_plugin_contrail.plugins.opencontrail.loadbalancer.v2.plugin.LoadBalancerPluginV2
+      l3_ha: False
+      api_extensions_path: /opt/plugin/site-packages/neutron_plugin_contrail/extensions:/opt/plugin/site-packages/neutron_lbaas/extensions
+      interface_driver: null
+    quotas:
+      quota_driver: neutron_plugin_contrail.plugins.opencontrail.quota.driver.QuotaDriver
+  plugins:
+    tungstenfabric:
+      APISERVER:
+        api_server_ip: config-api-server.tungsten-fabric.svc.cluster.local
+        api_server_port: 8082
+        contrail_extensions: "ipam:neutron_plugin_contrail.plugins.opencontrail.contrail_plugin_ipam.NeutronPluginContrailIpam,policy:neutron_plugin_contrail.plugins.opencontrail.contrail_plugin_policy.NeutronPluginContrailPolicy,route-table:neutron_plugin_contrail.plugins.opencontrail.contrail_plugin_vpc.NeutronPluginContrailVpc,contrail:None,service-interface:None,vf-binding:None"
+        multi_tenancy: True
+      KEYSTONE:
+        insecure: True
+    tf_vnc_api_lib:
+      global:
+        WEB_SERVER: config-api-server.tungsten-fabric.svc.cluster.local
+        WEB_PORT: 8082
+      auth:
+        AUTHN_TYPE: keystone
+        AUTHN_PROTOCOL: http
+        AUTHN_URL: /v3/auth/tokens
+manifests:
+  daemonset_dhcp_agent: false
+  daemonset_l3_agent: false
+  daemonset_lb_agent: false
+  daemonset_metadata_agent: false
+  daemonset_ovs_agent: false
+  daemonset_sriov_agent: false
+  pod_rally_test: false
+pod:
+  mounts:
+    neutron_db_sync:
+      neutron_db_sync:
+        volumeMounts:
+          - name: db-sync-conf
+            mountPath: /etc/neutron/plugins/tungstenfabric/tf_plugin.ini
+            subPath: tf_plugin.ini
+            readOnly: true
+        volumes:
+...
diff --git a/nova/templates/configmap-bin.yaml b/nova/templates/configmap-bin.yaml
index c4e47fbb97..6c2d3bde66 100644
--- a/nova/templates/configmap-bin.yaml
+++ b/nova/templates/configmap-bin.yaml
@@ -97,4 +97,8 @@ data:
 {{- include "helm-toolkit.scripts.rabbit_init" . | indent 4 }}
   wait-for-computes-init.sh: |
 {{ tuple "bin/_wait-for-computes-init.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
+{{- if ( has "tungstenfabric" .Values.network.backend ) }}
+  tf-plugin.pth: |
+    /opt/plugin/site-packages
+{{- end }}
 {{- end }}
diff --git a/nova/templates/daemonset-compute.yaml b/nova/templates/daemonset-compute.yaml
index 6b73a72755..a37bf1ee52 100644
--- a/nova/templates/daemonset-compute.yaml
+++ b/nova/templates/daemonset-compute.yaml
@@ -205,6 +205,19 @@ spec:
             - name: pod-shared
               mountPath: /tmp/pod-shared
         {{ end }}
+        {{- if ( has "tungstenfabric" .Values.network.backend ) }}
+        - name: tungstenfabric-compute-init
+          image: {{ .Values.images.tags.tf_compute_init }}
+          imagePullPolicy: {{ .Values.images.pull_policy }}
+{{ tuple $envAll $envAll.Values.pod.resources.compute | include "helm-toolkit.snippets.kubernetes_resources" | indent 10 }}
+          securityContext:
+            runAsUser: {{ .Values.pod.user.nova.uid }}
+          volumeMounts:
+            - name: tf-plugin-shared
+              mountPath: /opt/plugin
+            - name: tf-plugin-bin
+              mountPath: /opt/plugin/bin
+        {{- end }}
       containers:
         - name: nova-compute
 {{ tuple $envAll "nova_compute" | include "helm-toolkit.snippets.image" | indent 10 }}
@@ -344,6 +357,26 @@ spec:
               mountPath: /usr/local/sbin/iscsiadm
               subPath: iscsiadm
             {{- end }}
+            {{- if ( has "tungstenfabric" .Values.network.backend ) }}
+            - name: tf-plugin-shared
+              mountPath: /opt/plugin
+              readOnly: true
+            - name: tf-plugin-bin
+              mountPath: /usr/sbin
+              readOnly: true
+            - name: nova-bin
+              mountPath: /usr/local/lib/python2.7/site-packages/tf-plugin.pth
+              subPath: tf-plugin.pth
+              readOnly: true
+            - name: nova-bin
+              mountPath: /var/lib/openstack/lib/python2.7/site-packages/tf-plugin.pth
+              subPath: tf-plugin.pth
+              readOnly: true
+            - name: nova-bin
+              mountPath: /var/lib/openstack/lib/python3.6/site-packages/tf-plugin.pth
+              subPath: tf-plugin.pth
+              readOnly: true
+            {{- end }}
 {{ if $mounts_nova_compute.volumeMounts }}{{ toYaml $mounts_nova_compute.volumeMounts | indent 12 }}{{ end }}
         {{- if .Values.network.sshd.enabled }}
         - name: nova-compute-ssh
@@ -442,6 +475,12 @@ spec:
         - name: usrlocalsbin
           emptyDir: {}
         {{- end }}
+        {{- if ( has "tungstenfabric" .Values.network.backend ) }}
+        - name: tf-plugin-shared
+          emptyDir: {}
+        - name: tf-plugin-bin
+          emptyDir: {}
+        {{- end }}
 {{ if $mounts_nova_compute.volumes }}{{ toYaml $mounts_nova_compute.volumes | indent 8 }}{{ end }}
 {{- end }}
 {{- end }}
diff --git a/nova/values_overrides/tf.yaml b/nova/values_overrides/tf.yaml
new file mode 100644
index 0000000000..913802c3fe
--- /dev/null
+++ b/nova/values_overrides/tf.yaml
@@ -0,0 +1,84 @@
+---
+images:
+  tags:
+    tf_compute_init: opencontrailnightly/contrail-openstack-compute-init:master-latest
+conf:
+  nova:
+    libvirt:
+      virt_type: qemu
+      cpu_mode: host-model
+  agent:
+    compute:
+      node_selector_key: openstack-compute-node
+      node_selector_value: enabled
+    compute_ironic:
+      node_selector_key: openstack-compute-node
+      node_selector_value: enabled
+  api_metadata:
+    node_selector_key: openstack-control-plane
+    node_selector_value: enabled
+  conductor:
+    node_selector_key: openstack-control-plane
+    node_selector_value: enabled
+  consoleauth:
+    node_selector_key: openstack-control-plane
+    node_selector_value: enabled
+  job:
+    node_selector_key: openstack-control-plane
+    node_selector_value: enabled
+  novncproxy:
+    node_selector_key: openstack-control-plane
+    node_selector_value: enabled
+  osapi:
+    node_selector_key: openstack-control-plane
+    node_selector_value: enabled
+  placement:
+    node_selector_key: openstack-control-plane
+    node_selector_value: enabled
+  scheduler:
+    node_selector_key: openstack-control-plane
+    node_selector_value: enabled
+  spiceproxy:
+    node_selector_key: openstack-control-plane
+    node_selector_value: enabled
+  test:
+    node_selector_key: openstack-control-plane
+    node_selector_value: enabled
+  rootwrap: |
+    # Configuration for nova-rootwrap
+    # This file should be owned by (and only-writeable by) the root user
+
+    [DEFAULT]
+    # List of directories to load filter definitions from (separated by ',').
+    # These directories MUST all be only writeable by root !
+    filters_path=/etc/nova/rootwrap.d,/usr/share/nova/rootwrap
+
+    # List of directories to search executables in, in case filters do not
+    # explicitely specify a full path (separated by ',')
+    # If not specified, defaults to system PATH environment variable.
+    # These directories MUST all be only writeable by root !
+    exec_dirs=/sbin,/usr/sbin,/bin,/usr/bin,/usr/local/bin,/usr/local/sbin,/var/lib/openstack/bin,/var/lib/kolla/venv/bin,/opt/plugin/bin
+
+    # Enable logging to syslog
+    # Default value is False
+    use_syslog=False
+
+    # Which syslog facility to use.
+    # Valid values include auth, authpriv, syslog, local0, local1...
+    # Default value is 'syslog'
+    syslog_log_facility=syslog
+
+    # Which messages to log.
+    # INFO means log all usage
+    # ERROR means only log unsuccessful attempts
+    syslog_log_level=ERROR
+network:
+  backend:
+    - tungstenfabric
+dependencies:
+  dynamic:
+    targeted:
+      tungstenfabric:
+        compute:
+          daemonset: []
+...
diff --git a/tools/deployment/component/compute-kit/compute-kit.sh b/tools/deployment/component/compute-kit/compute-kit.sh
index ab6274b472..a6d2652c2e 100755
--- a/tools/deployment/component/compute-kit/compute-kit.sh
+++ b/tools/deployment/component/compute-kit/compute-kit.sh
@@ -128,6 +128,11 @@ helm upgrade --install neutron ./neutron \
     ${OSH_VALUES_OVERRIDES_HELM_ARGS:=} \
     ${OSH_EXTRA_HELM_ARGS_NEUTRON}
 
+
+# If compute kit installed using Tungsten Fubric, it will be alive when Tunsten Fabric become active.
+if [[ "$FEATURE_GATES" =~ (,|^)tf(,|$) ]]; then
+  exit 0
+fi
 #NOTE: Wait for deploy
 ./tools/deployment/common/wait-for-pods.sh openstack
 
diff --git a/tools/deployment/component/compute-kit/tungsten-fabric.sh b/tools/deployment/component/compute-kit/tungsten-fabric.sh
new file mode 100755
index 0000000000..75594f9b64
--- /dev/null
+++ b/tools/deployment/component/compute-kit/tungsten-fabric.sh
@@ -0,0 +1,249 @@
+#!/bin/bash
+
+#    Licensed 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.
+set -xe
+
+stages="prepare deploy checkdns setupdns"
+OSH_INFRA_PATH=${OSH_INFRA_PATH:="../openstack-helm-infra"}
+
+function get_node_ip() {
+  local phys_int=$(ip route get 1 | grep -o 'dev.*' | awk '{print($2)}')
+  local node_ip=$(ip addr show dev $phys_int | grep -Pom1 "(?<=inet )([0-9]+\.{0,1}){4}")
+  echo $node_ip
+}
+
+function nic_has_ip() {
+  local nic=$1
+  if nic_ip=$(ip addr show $nic | grep -Pom1 "(?<=inet )([0-9]+\.{0,1}){4}"); then
+    printf "\n$nic has IP $nic_ip"
+    return 0
+  else
+    return 1
+  fi
+}
+
+function wait_cmd_success() {
+  # silent mode = don't print output of input cmd for each attempt.
+  local cmd=$1
+  local interval=${2:-3}
+  local max=${3:-300}
+  local silent_cmd=${4:-1}
+
+  local state_save=$(set +o)
+  set +o xtrace
+  set -o pipefail
+  local i=0
+  if [[ "$silent_cmd" != "0" ]]; then
+    local to_dev_null="&>/dev/null"
+  else
+    local to_dev_null=""
+  fi
+  while ! eval "$cmd" "$to_dev_null"; do
+    printf "."
+    i=$((i + 1))
+    if (( i > max )) ; then
+      echo ""
+      echo "ERROR: wait failed in $((i*10))s"
+      eval "$cmd"
+      eval "$state_save"
+      return 1
+    fi
+    sleep $interval
+  done
+  echo ""
+  echo "INFO: done in $((i*10))s"
+  eval "$state_save"
+}
+
+function wait_nic_up() {
+  local nic=$1
+  printf "INFO: wait for $nic is up"
+  if ! wait_cmd_success "nic_has_ip $nic" 10 60; then
+    echo "ERROR: $nic is not up"
+    echo "INFO: Start vrouter logs"
+    local agent_pod=$(kubectl get pods -n tungsten-fabric --no-headers -o custom-columns=NAME:.metadata.name)
+    kubectl describe pod $agent_pod -n tungsten-fabric
+    echo "INFO: vrouter-agent logs"
+    kubectl logs $agent_pod -n tungsten-fabric -c contrail-vrouter-agent
+    echo "INFO: vrouter-init-kernel logs"
+    kubectl logs $agent_pod -c contrail-vrouter-init-kernel -n tungsten-fabric
+    sudo docker image list
+    echo "INFO: End vrouter logs"
+    return 1
+  fi
+  echo "INFO: $nic is up"
+}
+
+function show_usage_tf(){
+  cat <<EOF
+To use this script pass a stage you need as a first argument:
+
+  tungsten_fabric.sh <stage>
+
+Possible stages are:
+
+  'setupdns' - configure DNS for use k8s using resolvconf service
+    - Install resolvconf service
+    - Add k8s cluster IP as a nameserver to the config
+
+  'prepare' - prepared host to deploy Tungsten fabric:
+    - add an tf.yaml file to libvirt/values_overrides
+    - comment lines in compute_kit.sh which wait nova and neutron is working and run tests
+    - check and add line to /etc/hosts file
+    Run 'preapare' stage after install kubernetes and before run libvirt.sh and compute_kit.sh
+
+  'deploy' - deploy Tungsten fabric:
+    - download tf Helm charts
+    - prepare tf config
+    - deploy Tungsten fabric to Kubernetes
+    - wait for tf pods
+    - wait for openstack pods
+    - run couple of openstack commands and nova tests
+    Run 'deploy' stage after compute_kit.sh
+EOF
+}
+
+# 'setupdns' stage implementation
+function setupdns_tf() {
+  local distro=$(cat /etc/*release | egrep '^ID=' | awk -F= '{print $2}' | tr -d \")
+  if [[ $distro == 'ubuntu' ]] ; then
+    export DEBIAN_FRONTEND=noninteractive
+    sudo -E apt-get install -y resolvconf
+    dns_cluster_ip=`kubectl get svc kube-dns -n kube-system --no-headers -o custom-columns=":spec.clusterIP"`
+    echo "nameserver ${dns_cluster_ip}" | sudo tee -a /etc/resolvconf/resolv.conf.d/head > /dev/null
+    sudo systemctl restart resolvconf
+  fi
+}
+
+# 'checkdns' stage
+function checkdns_tf() {
+  cat /etc/resolv.conf
+}
+
+# 'prepare' stage implementation
+function prepare_tf(){
+  # Linux kernel headers required to build vrouter kernel module on Ubuntu
+  local distro=$(cat /etc/*release | egrep '^ID=' | awk -F= '{print $2}' | tr -d \")
+  if [[ $distro == 'ubuntu' ]] ; then
+    sudo apt-get install -y linux-headers-$(uname -r) chrony
+  fi
+  # add an tf.yaml file to libvirt/values_overrides
+  cat <<EOF > ${OSH_INFRA_PATH}/libvirt/values_overrides/tf.yaml
+---
+network:
+  backend:
+    - tungstenfabric
+dependencies:
+  dynamic:
+    targeted:
+      tungstenfabric:
+        libvirt:
+          daemonset: []
+conf:
+  qemu:
+    cgroup_device_acl: ["/dev/null", "/dev/full", "/dev/zero", "/dev/random", "/dev/urandom", "/dev/ptmx", "/dev/kvm", "/dev/kqemu", "/dev/rtc", "/dev/hpet", "/dev/net/tun"]
+...
+
+EOF
+
+  # check and add a line to /etc/hosts file
+  local node_ip=$(get_node_ip)
+  if ! cat /etc/hosts | grep "${node_ip}" ; then
+    local tf_hostname=$(hostname)
+    cat <<EOF | sudo tee -a /etc/hosts
+${node_ip} ${tf_hostname}.cluster.local ${tf_hostname}
+EOF
+  fi
+}
+
+# 'deploy' stage implementation
+function deploy_tf(){
+  if [[ -z "$CONTAINER_DISTRO_NAME" ]] ; then
+    echo "ERROR: Please set up CONTAINER_DISTRO_NAME"
+    exit 1
+  fi
+
+  export CONTROLLER_NODES=$(get_node_ip)
+
+  # download tf Helm charts
+  sudo docker create --name tf-helm-deployer-src --entrypoint /bin/true tungstenfabric/tf-helm-deployer-src:latest
+  sudo docker cp tf-helm-deployer-src:/src ./tf-helm-deployer
+  sudo docker rm -fv tf-helm-deployer-src
+
+  pushd tf-helm-deployer
+  helm repo add local http://localhost:8879/charts
+  sudo make all
+  popd
+
+  # prepare tf config
+  cat <<EOF > ./tf-devstack-values.yaml
+global:
+  contrail_env:
+    CONTAINER_REGISTRY: tungstenfabric
+    CONTRAIL_CONTAINER_TAG: "2020-06-08"
+    CONTROLLER_NODES: ${CONTROLLER_NODES}
+    JVM_EXTRA_OPTS: "-Xms1g -Xmx2g"
+    BGP_PORT: "1179"
+    CONFIG_DATABASE_NODEMGR__DEFAULTS__minimum_diskGB: "2"
+    DATABASE_NODEMGR__DEFAULTS__minimum_diskGB: "2"
+    LOG_LEVEL: SYS_DEBUG
+    VROUTER_ENCRYPTION: FALSE
+    ANALYTICS_ALARM_ENABLE: TRUE
+    ANALYTICS_SNMP_ENABLE: TRUE
+    ANALYTICSDB_ENABLE: TRUE
+    CLOUD_ORCHESTRATOR: ${CONTAINER_DISTRO_NAME}
+  node:
+    host_os: ubuntu
+EOF
+
+  # deploy Tungsten fabric to Kubernetes
+  sudo mkdir -p /var/log/contrail
+  kubectl create ns tungsten-fabric
+  helm upgrade --install --namespace tungsten-fabric tungsten-fabric tf-helm-deployer/contrail -f tf-devstack-values.yaml
+  kubectl label nodes --all opencontrail.org/vrouter-kernel=enabled
+  wait_nic_up vhost0
+  kubectl label nodes --all opencontrail.org/controller=enabled
+
+  # wait for tf pods
+  ./tools/deployment/common/wait-for-pods.sh tungsten-fabric
+  echo "INFO: Tungsten Fabric info"
+  # Display contrail state
+  sudo contrail-status
+  kubectl get pods -n tungsten-fabric
+
+  # wait for openstack pods
+  ./tools/deployment/common/wait-for-pods.sh openstack
+
+  # run couple of openstack commands and nova tests
+  openstack compute service list
+  openstack hypervisor list
+  if [ "x${RUN_HELM_TESTS}" == "xno" ]; then
+    exit 0
+  fi
+  helm test nova --timeout 900
+  helm test neutron --timeout 900
+}
+
+if [[ $# == 0 ]] ; then
+  echo "ERROR: You have to pass some stage in this script"
+  show_usage_tf
+  exit 1
+fi
+
+if [[ ! $stages =~ .*${1}.* ]] ; then
+  echo "ERROR: Not any valid stage has been found"
+  show_usage_tf
+  exit 1
+fi
+
+${1}_tf
\ No newline at end of file
diff --git a/zuul.d/jobs-openstack-helm.yaml b/zuul.d/jobs-openstack-helm.yaml
index 859d20760c..cc0a6af5ff 100644
--- a/zuul.d/jobs-openstack-helm.yaml
+++ b/zuul.d/jobs-openstack-helm.yaml
@@ -354,7 +354,40 @@
         - ./tools/deployment/common/openstack-exporter.sh
         - ./tools/deployment/developer/common/900-use-it.sh
         - ./tools/deployment/common/test-networkpolicy.sh
-
+- job:
+    name: openstack-helm-tf
+    parent: openstack-helm-compute-kit
+    timeout: 9600
+    nodeset: openstack-helm-single-32GB-node
+    roles:
+      - zuul: openstack/openstack-helm-infra
+    required-projects:
+      - openstack/openstack-helm-infra
+    vars:
+      zuul_osh_infra_relative_path: ../openstack-helm-infra/
+      osh_params:
+        feature_gates: tf
+        openstack_release: train
+        container_distro_name: ubuntu
+        container_distro_version: bionic
+      gate_scripts:
+        - ./tools/deployment/common/install-packages.sh
+        - ./tools/deployment/common/deploy-k8s.sh
+        - ./tools/deployment/common/setup-client.sh
+        - ./tools/deployment/component/common/ingress.sh
+        - ./tools/deployment/component/common/mariadb.sh
+        - ./tools/deployment/component/common/memcached.sh
+        - ./tools/deployment/component/common/rabbitmq.sh
+        - ./tools/deployment/component/nfs-provisioner/nfs-provisioner.sh
+        - ./tools/deployment/component/compute-kit/tungsten-fabric.sh checkdns
+        - ./tools/deployment/component/compute-kit/tungsten-fabric.sh setupdns
+        - ./tools/deployment/component/keystone/keystone.sh
+        - ./tools/deployment/component/heat/heat.sh
+        - ./tools/deployment/component/glance/glance.sh
+        - ./tools/deployment/component/compute-kit/tungsten-fabric.sh prepare
+        - ./tools/deployment/component/compute-kit/libvirt.sh
+        - ./tools/deployment/component/compute-kit/compute-kit.sh
+        - ./tools/deployment/component/compute-kit/tungsten-fabric.sh deploy
 - job:
     name: openstack-helm-netpol-compute-kit
     parent: openstack-helm-chart-deploy
diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml
index 25493f2136..9def1575eb 100644
--- a/zuul.d/project.yaml
+++ b/zuul.d/project.yaml
@@ -32,6 +32,7 @@
         - openstack-helm-compute-kit-rocky-ubuntu_bionic
         - openstack-helm-compute-kit-train-ubuntu_bionic
         - openstack-helm-horizon
+        - openstack-helm-tf
     gate:
       jobs:
         - openstack-helm-lint