diff --git a/local-volume-provisioner/Chart.yaml b/local-volume-provisioner/Chart.yaml
new file mode 100644
index 0000000000..a33684e87f
--- /dev/null
+++ b/local-volume-provisioner/Chart.yaml
@@ -0,0 +1,24 @@
+# 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.
+
+---
+apiVersion: v1
+appVersion: v1.0.0
+description: OpenStack-Helm local-volume-provisioner
+name: local-volume-provisioner
+version: 0.1.0
+home: https://github.com/kubernetes-sigs/sig-storage-local-static-provisioner
+sources:
+  - https://opendev.org/openstack/openstack-helm
+maintainers:
+  - name: OpenStack-Helm Authors
+...
diff --git a/local-volume-provisioner/requirements.yaml b/local-volume-provisioner/requirements.yaml
new file mode 100644
index 0000000000..84f0affae0
--- /dev/null
+++ b/local-volume-provisioner/requirements.yaml
@@ -0,0 +1,18 @@
+# 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.
+
+---
+dependencies:
+  - name: helm-toolkit
+    repository: file://../helm-toolkit
+    version: ">= 0.1.0"
+...
diff --git a/local-volume-provisioner/templates/bin/_fakemount.py.tpl b/local-volume-provisioner/templates/bin/_fakemount.py.tpl
new file mode 100644
index 0000000000..e9a937f4e2
--- /dev/null
+++ b/local-volume-provisioner/templates/bin/_fakemount.py.tpl
@@ -0,0 +1,377 @@
+#!/usr/bin/env python3
+#
+# Copyright 2019 Mirantis, Inc.
+#
+#    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.
+"""Fakemount python module
+The module is aimed to crate fake mountpoints (--bind).
+Example:
+  python3  fakemount --config-file '/root/mymount.yml'
+Attributes:
+  config-file - file path to config file that contains fake mounts.
+"""
+__version__ = "1.0"
+import argparse
+import logging
+import os
+import re
+import subprocess
+import sys
+from collections import defaultdict
+import yaml
+logging.basicConfig(stream=sys.stdout, level=logging.INFO)
+LOG = logging.getLogger(__name__)
+MOUNT_BIN = "/bin/mount"
+###Fork https://github.com/b10011/pyfstab/ #####################################
+#  Latest commit 828540d
+class InvalidEntry(Exception):
+    """
+    Raised when a string cannot be generated because of the Entry is invalid.
+    """
+class InvalidFstabLine(Exception):
+    """
+    Raised when a line is invalid in fstab. This doesn't just mean that the
+    Entry will be invalid but also that the system can not process the fstab
+    file fully either.
+    """
+class Entry:
+    """
+    Handles parsing and formatting fstab line entries.
+    :var device:
+        (str or None) -
+        Fstab device (1st parameter in the fstab entry)
+    :var dir:
+        (str or None) -
+        Fstab device (2nd parameter in the fstab entry)
+    :var type:
+        (str or None) -
+        Fstab device (3rd parameter in the fstab entry)
+    :var options:
+        (str or None) -
+        Fstab device (4th parameter in the fstab entry)
+    :var dump:
+        (int or None) -
+        Fstab device (5th parameter in the fstab entry)
+    :var fsck:
+        (int or None) -
+        Fstab device (6th parameter in the fstab entry)
+    :var valid:
+        (bool) -
+        Whether the Entry is valid or not. Can be checked with "if entry:".
+    """
+    def __init__(
+            self,
+            _device=None,
+            _dir=None,
+            _type=None,
+            _options=None,
+            _dump=None,
+            _fsck=None,
+    ):
+        """
+        :param _device: Fstab device (1st parameter in the fstab entry)
+        :type _device: str
+        :param _dir: Fstab device (2nd parameter in the fstab entry)
+        :type _dir: str
+        :param _type: Fstab device (3rd parameter in the fstab entry)
+        :type _type: str
+        :param _options: Fstab device (4th parameter in the fstab entry)
+        :type _options: str
+        :param _dump: Fstab device (5th parameter in the fstab entry)
+        :type _dump: int
+        :param _fsck: Fstab device (6th parameter in the fstab entry)
+        :type _fsck: int
+        """
+        self.device = _device
+        self.dir = _dir
+        self.type = _type
+        self.options = _options
+        self.dump = _dump
+        self.fsck = _fsck
+        self.valid = True
+        self.valid &= self.device is not None
+        self.valid &= self.dir is not None
+        self.valid &= self.type is not None
+        self.valid &= self.options is not None
+        self.valid &= self.dump is not None
+        self.valid &= self.fsck is not None
+    def read_string(self, line):
+        """
+        Parses an entry from a string
+        :param line: Fstab entry line.
+        :type line: str
+        :return: self
+        :rtype: Entry
+        :raises InvalidEntry: If the data in the string cannot be parsed.
+        """
+        line = line.strip()
+        if line and not line[0] == "#":
+            parts = re.split(r"\s+", line)
+            if len(parts) == 6:
+                [_device, _dir, _type, _options, _dump, _fsck] = parts
+                _dump = int(_dump)
+                _fsck = int(_fsck)
+                self.device = _device
+                self.dir = _dir
+                self.type = _type
+                self.options = _options
+                self.dump = _dump
+                self.fsck = _fsck
+                self.valid = True
+                return self
+            else:
+                raise InvalidFstabLine()
+        self.device = None
+        self.dir = None
+        self.type = None
+        self.options = None
+        self.dump = None
+        self.fsck = None
+        self.valid = False
+        raise InvalidEntry("Entry cannot be parsed")
+    def write_string(self):
+        """
+        Formats the Entry into fstab entry line.
+        :return: Fstab entry line.
+        :rtype: str
+        :raises InvalidEntry:
+            A string cannot be generated because the entry is invalid.
+        """
+        if self:
+            return "{} {} {} {} {} {}".format(
+                self.device,
+                self.dir,
+                self.type,
+                self.options,
+                self.dump,
+                self.fsck,
+            )
+        else:
+            raise InvalidEntry("Entry cannot be formatted")
+    def __bool__(self):
+        return self.valid
+    def __str__(self):
+        return self.write_string()
+    def __repr__(self):
+        try:
+            return "<Entry {}>".format(str(self))
+        except InvalidEntry:
+            return "<Entry Invalid>"
+class Fstab:
+    """
+    Handles reading, parsing, formatting and writing of fstab files.
+    :var entries:
+        (list[Entry]) -
+        List of entries.
+        When writing to a file, entries are listed from this list.
+    :var entries_by_device:
+        (dict[str, list[Entry]]) -
+        Fstab entries by device.
+    :var entry_by_dir:
+        (dict[str, Entry]) -
+        Fstab entry by directory.
+    :var entries_by_type:
+        (dict[str, list[Entry]]) -
+        Fstab entries by type.
+    """
+    def __init__(self):
+        self.entries = []
+        # A single device can have multiple mountpoints
+        self.entries_by_device = defaultdict(list)
+        # If multiple devices have same mountpoint, only the last entry in the
+        # fstab file is taken into consideration
+        self.entry_by_dir = dict()
+        # And the most obvious one, many entries can have mountpoints of same
+        # type
+        self.entries_by_type = defaultdict(list)
+    def read_string(self, data, only_valid=False):
+        """
+        Parses entries from a data string
+        :param data: Contents of the fstab file
+        :type data: str
+        :param only_valid:
+            Skip the entries that do not actually mount. For example, if device
+            A is mounted to directory X and later device B is mounted to
+            directory X, the A mount to X is undone by the system.
+        :type only_valid: bool
+        :return: self
+        :rtype: Fstab
+        """
+        for line in reversed(data.splitlines()):
+            try:
+                entry = Entry().read_string(line)
+                if entry and (
+                        not only_valid or entry.dir not in self.entry_by_dir
+                ):
+                    self.entries.insert(0, entry)
+                    self.entries_by_device[entry.device].insert(0, entry)
+                    self.entry_by_dir[entry.dir] = entry
+                    self.entries_by_type[entry.type].insert(0, entry)
+            except InvalidEntry:
+                pass
+        return self
+    def write_string(self):
+        """
+        Formats entries into a string.
+        :return: Formatted fstab file.
+        :rtype: str
+        :raises InvalidEntry:
+            A string cannot be generated because one of the entries is invalid.
+        """
+        return "\n".join(str(entry) for entry in self.entries)
+    def read_file(self, handle, only_valid=False):
+        """
+        Parses entries from a file
+        :param handle: File handle
+        :type handle: file
+        :param only_valid:
+            Skip the entries that do not actually mount. For example, if device
+            A is mounted to directory X and later device B is mounted to
+            directory X, the A mount to X is undone by the system.
+        :type only_valid: bool
+        :return: self
+        :rtype: Fstab
+        """
+        self.read_string(handle.read(), only_valid)
+        return self
+    def write_file(self, handle):
+        """
+        Parses entries in data string
+        :param path: File handle
+        :type path: file
+        :return: self
+        :rtype: Fstab
+        """
+        handle.write(str(self))
+        return self
+    def __bool__(self):
+        return len(self.entries) > 0
+    def __str__(self):
+        return self.write_string()
+    def __repr__(self):
+        res = "<Fstab [{} entries]".format(len(self.entries))
+        if self.entries:
+            res += "\n"
+            for entry in self.entries:
+                res += "  {}\n".format(entry)
+        res += ">"
+        return res
+###End Fork https://github.com/b10011/pyfstab/ #################################
+def fstab_bindmount(src, mountpoint, fstab_path="/mnt/host/fstab", opts=None):
+    if opts is None:
+        opts = ["bind"]
+    mountpoint = os.path.normpath(mountpoint.strip())
+    with open(fstab_path, "r") as f:
+        fstab = Fstab().read_file(f)
+    if mountpoint in fstab.entry_by_dir:
+        LOG.info(f'Mount point {mountpoint} already defined in {fstab_path}')
+        return
+    fstab.entries.append(Entry(src, mountpoint, "none", ",".join(opts), 0, 0))
+    str_fstab = str(fstab)
+    LOG.info(f'Attempt to overwrite file:{fstab_path}, with data:\n'
+             f'{str_fstab}')
+    with open(fstab_path, "w") as f:
+        f.write(str_fstab)
+def get_volumes(mount_point, i):
+    vol_template = "vol%d%%d" % i
+    volumes = mount_point.get("mounts")
+    if volumes is not None:
+        return volumes
+    return [vol_template % vol_number for vol_number in
+            range(mount_point["volPerNode"])]
+def ensure_directories_exists(storage_class):
+    target_root = storage_class.get("mountDir", storage_class["hostDir"])
+    for i, bind_mount in enumerate(storage_class["bindMounts"]):
+        for vol_name in get_volumes(bind_mount, i):
+            source = os.path.normpath(f"{bind_mount['srcRoot']}/{vol_name}")
+            target = os.path.normpath(f"{target_root}/{vol_name}")
+            os.makedirs(target, exist_ok=True)
+            os.makedirs(source, exist_ok=True)
+def is_mount(directory):
+    # Do not use os.path.ismount due to bug
+    # https://bugs.python.org/issue29707
+    directory = os.path.normpath(directory.strip())
+    with open("/proc/mounts") as f:
+        for line in f.readlines():
+            if line.split(" ")[1] == directory:
+                return True
+def mount_directories(storage_class):
+    failed_mounts = []
+    target_root = storage_class.get("mountDir", storage_class["hostDir"])
+    additional_opts = storage_class.get("additionalMountOptions", [])
+    opts = ["bind"] + additional_opts
+    for i, bind_mount in enumerate(storage_class["bindMounts"]):
+        for vol_name in get_volumes(bind_mount, i):
+            source = os.path.normpath(f"{bind_mount['srcRoot']}/{vol_name}")
+            target = os.path.normpath(f"{target_root}/{vol_name}")
+            LOG.info(f"Trying to mount {source} to {target}")
+            if is_mount(target):
+                LOG.info(
+                    f"The directory {target} already mounted, skipping it...")
+            else:
+                cmd = [MOUNT_BIN, "-o", ",".join(opts), source, target]
+                LOG.info(f"Running {cmd}")
+                obj = None
+                try:
+                    obj = subprocess.run(
+                        cmd,
+                        stdout=subprocess.PIPE,
+                        stderr=subprocess.PIPE,
+                    )
+                    obj.check_returncode()
+                except Exception as e:
+                    LOG.exception(
+                        f"Failed to mount {source} {target}\n"
+                        f"stdout: {obj.stdout}\n"
+                        f"stderr: {obj.stderr}"
+                    )
+                    failed_mounts.append((source, target))
+                else:
+                    LOG.info(f"Successfully mount {source} {target}")
+            fstab_bindmount(source, target, opts=opts)
+    if failed_mounts:
+        raise Exception(f"Failed to mount some directories: {failed_mounts}")
+def main():
+    parser = argparse.ArgumentParser(
+        description="Create fake mountpotins with specified directories."
+    )
+    group = parser.add_mutually_exclusive_group(required=True)
+    group.add_argument(
+        "--config-file", help="Path to file with image layout",
+    )
+    parser.add_argument(
+        "--create-only",
+        help="Ensure target directories exists.",
+        dest="create_only",
+        action="store_true",
+    )
+    parser.set_defaults(create_only=False)
+    args = parser.parse_args()
+    with open(args.config_file) as f:
+        data = yaml.safe_load(f)
+    if data is None:
+        LOG.exception("Invalid data supplied from the config file.")
+        raise Exception
+    classes_data = data.get("classes", [])
+    if isinstance(classes_data, list):
+        for storage_class in classes_data:
+            ensure_directories_exists(storage_class)
+        if not args.create_only:
+            for storage_class in classes_data:
+                mount_directories(storage_class)
+if __name__ == "__main__":
+    try:
+        main()
+    except Exception as e:
+        LOG.exception("Can't create volume mounts.")
+        sys.exit(1)
diff --git a/local-volume-provisioner/templates/configmap-bin.yaml b/local-volume-provisioner/templates/configmap-bin.yaml
new file mode 100644
index 0000000000..5160cf88fb
--- /dev/null
+++ b/local-volume-provisioner/templates/configmap-bin.yaml
@@ -0,0 +1,58 @@
+{{/*
+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.
+*/}}
+
+{{- define "lvp.configmap.bin" }}
+{{- $configMapName := index . 0 }}
+{{- $envAll := index . 1 }}
+{{- with $envAll }}
+
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: {{ $configMapName }}
+data:
+{{- if .Values.images.local_registry.active }}
+  image-repo-sync.sh: |
+{{- include "helm-toolkit.scripts.image_repo_sync" . | indent 4 }}
+{{- end }}
+  fakemount.py: |
+{{ tuple "bin/_fakemount.py.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
+  storageClassMap: |
+    {{- range $classConfig := $envAll.Values.conf.fake_mounts.classes }}
+    {{ $classConfig.name }}:
+      hostDir: {{ $classConfig.hostDir }}
+      mountDir: {{ $classConfig.mountDir | default $classConfig.hostDir }}
+      {{- if $classConfig.blockCleanerCommand }}
+      blockCleanerCommand:
+      {{- range $val := $classConfig.blockCleanerCommand }}
+        - {{ $val | quote }}
+      {{- end}}
+      {{- end }}
+      {{- if $classConfig.volumeMode }}
+      volumeMode: {{ $classConfig.volumeMode }}
+      {{- end }}
+      {{- if $classConfig.fsType }}
+      fsType: {{ $classConfig.fsType }}
+      {{- end }}
+      {{- if $classConfig.namePattern }}
+      namePattern: {{ $classConfig.namePattern | quote }}
+      {{- end }}
+    {{- end }}
+{{- end }}
+{{- end }}
+
+{{- if .Values.manifests.configmap_bin }}
+{{- list "local-volume-provisioner-bin" . | include "lvp.configmap.bin" }}
+{{- end }}
diff --git a/local-volume-provisioner/templates/configmap-etc.yaml b/local-volume-provisioner/templates/configmap-etc.yaml
new file mode 100644
index 0000000000..4684854852
--- /dev/null
+++ b/local-volume-provisioner/templates/configmap-etc.yaml
@@ -0,0 +1,33 @@
+{{/*
+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.
+*/}}
+
+{{- define "lvp.configmap.etc" }}
+{{- $configMapName := index . 0 }}
+{{- $envAll := index . 1 }}
+{{- with $envAll }}
+
+---
+apiVersion: v1
+kind: Secret
+metadata:
+  name: {{ $configMapName }}
+type: Opaque
+data:
+  fake_mounts.conf: {{ $envAll.Values.conf.fake_mounts | toJson | b64enc }}
+{{- end }}
+{{- end }}
+
+{{- if .Values.manifests.configmap_etc }}
+{{- list "local-volume-provisioner-etc" . | include "lvp.configmap.etc" }}
+{{- end }}
diff --git a/local-volume-provisioner/templates/daemonset-lvp.yaml b/local-volume-provisioner/templates/daemonset-lvp.yaml
new file mode 100644
index 0000000000..0c8da93e98
--- /dev/null
+++ b/local-volume-provisioner/templates/daemonset-lvp.yaml
@@ -0,0 +1,212 @@
+{{/*
+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.
+*/}}
+
+{{- define "lvp.daemonset" }}
+{{- $daemonset := index . 0 }}
+{{- $configMapName := index . 1 }}
+{{- $serviceAccountName := index . 2 }}
+{{- $envAll := index . 3 }}
+
+{{- with $envAll }}
+
+{{- $mounts_lvp := $envAll.Values.pod.mounts.local_volume_provisioner.lvp }}
+{{- $mounts_lvp_init := $envAll.Values.pod.mounts.local_volume_provisioner.init_container }}
+---
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+  name: local-volume-provisioner
+  annotations:
+    {{ tuple $envAll | include "helm-toolkit.snippets.release_uuid" }}
+  labels:
+{{ tuple $envAll .Chart.Name $daemonset | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 4 }}
+spec:
+  selector:
+    matchLabels:
+{{ tuple $envAll .Chart.Name $daemonset | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 6 }}
+{{ tuple $envAll $daemonset | include "helm-toolkit.snippets.kubernetes_upgrades_daemonset" | indent 2 }}
+  template:
+    metadata:
+      labels:
+{{ tuple $envAll .Chart.Name $daemonset | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 8 }}
+      annotations:
+{{- dict "envAll" $envAll "podName" "local-volume-provisioner" "containerNames" (list "lvp") | include "helm-toolkit.snippets.kubernetes_mandatory_access_control_annotation" | indent 8 }}
+{{ tuple $envAll | include "helm-toolkit.snippets.release_uuid" | indent 8 }}
+        configmap-bin-hash: {{ tuple "configmap-bin.yaml" . | include "helm-toolkit.utils.hash" }}
+        configmap-etc-hash: {{ tuple "configmap-etc.yaml" . | include "helm-toolkit.utils.hash" }}
+    spec:
+{{ dict "envAll" $envAll "application" "local-volume-provisioner" | include "helm-toolkit.snippets.kubernetes_pod_security_context" | indent 6 }}
+      serviceAccountName: {{ $serviceAccountName }}
+      nodeSelector:
+        {{ $envAll.Values.labels.local_volume_provisioner.node_selector_key }}: {{ $envAll.Values.labels.local_volume_provisioner.node_selector_value }}
+      initContainers:
+        - name: init-mounts
+{{ tuple $envAll "local_volume_provisioner_mounts" | include "helm-toolkit.snippets.image" | indent 10 }}
+{{ dict "envAll" $envAll "application" "local_volume_provisioner" "container" "init_mounts" | include "helm-toolkit.snippets.kubernetes_container_security_context" | indent 10 }}
+          terminationMessagePath: /var/log/termination-log
+          env:
+          - name: POD_NAME
+            valueFrom:
+              fieldRef:
+                apiVersion: v1
+                fieldPath: metadata.name
+          - name: NAMESPACE
+            valueFrom:
+              fieldRef:
+                apiVersion: v1
+                fieldPath: metadata.namespace
+          - name: PATH
+            value: /var/lib/openstack/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/
+          command:
+            - /tmp/fakemount.py
+            - --config-file
+            - /etc/provisioner/fake_mounts.conf
+          volumeMounts:
+            - name: fstab
+              mountPath: /mnt/host/fstab
+            - name: local-volume-provisioner-etc
+              mountPath: /etc/provisioner/fake_mounts.conf
+              subPath: fake_mounts.conf
+              readOnly: true
+            - name: local-volume-provisioner-bin
+              mountPath: /tmp/fakemount.py
+              subPath: fakemount.py
+              readOnly: true
+            {{- range $classConfig := $envAll.Values.conf.fake_mounts.classes }}
+              {{- range $bindMount := $classConfig.bindMounts }}
+            - mountPath: {{ $bindMount.srcRoot }}
+              mountPropagation: Bidirectional
+              name: {{ replace "/" ""  $bindMount.srcRoot }}
+              {{- end }}
+            - mountPath: {{ if $classConfig.mountDir }} {{- $classConfig.mountDir -}} {{ else }} {{- $classConfig.hostDir -}} {{ end }}
+              mountPropagation: Bidirectional
+              name: {{ $classConfig.name }}
+            {{- end }}
+            - mountPath: /run
+              name: run
+      containers:
+        - name: lvp
+{{ tuple $envAll "local_volume_provisioner" | include "helm-toolkit.snippets.image" | indent 10 }}
+{{ tuple $envAll $envAll.Values.pod.resources.local_volume_provisioner | include "helm-toolkit.snippets.kubernetes_resources" | indent 10 }}
+{{ dict "envAll" $envAll "application" "local_volume_provisioner" "container" "lvp" | include "helm-toolkit.snippets.kubernetes_container_security_context" | indent 10 }}
+          env:
+          - name: MY_NODE_NAME
+            valueFrom:
+              fieldRef:
+                fieldPath: spec.nodeName
+          - name: NAMESPACE
+            valueFrom:
+              fieldRef:
+                apiVersion: v1
+                fieldPath: metadata.namespace
+          command:
+            - /local-provisioner
+          volumeMounts:
+            - name: local-volume-provisioner-bin
+              mountPath: /etc/provisioner/config/storageClassMap
+              subPath: storageClassMap
+              readOnly: true
+            - name: dev
+              mountPath: /dev
+            {{- range $classConfig := $envAll.Values.conf.fake_mounts.classes }}
+            - name: {{ $classConfig.name }}
+              mountPath: {{ $classConfig.mountDir | default $classConfig.hostDir }}
+              mountPropagation: HostToContainer
+            {{- end }}
+      volumes:
+        - name: fstab
+          hostPath:
+            type: File
+            path: /etc/fstab
+        - name: local-volume-provisioner-bin
+          configMap:
+            name: local-volume-provisioner-bin
+            defaultMode: 0555
+        - name: local-volume-provisioner-etc
+          secret:
+            secretName: {{ $configMapName }}
+            defaultMode: 0444
+        - name: run
+          hostPath:
+            path: /run
+        - name: dev
+          hostPath:
+            path: /dev
+          {{- range $classConfig := $envAll.Values.conf.fake_mounts.classes }}
+            {{- range $bindMount := $classConfig.bindMounts }}
+        - name: {{ replace "/" ""  $bindMount.srcRoot }}
+          hostPath:
+            path: {{ $bindMount.srcRoot }}
+            type: ""
+            {{- end }}
+          {{- end }}
+        {{- range $classConfig := $envAll.Values.conf.fake_mounts.classes }}
+        - name: {{ $classConfig.name }}
+          hostPath:
+            path: {{ $classConfig.hostDir }}
+        {{- end }}
+{{ if $mounts_lvp.volumes }}{{ toYaml $mounts_lvp.volumes | indent 8 }}{{ end }}
+{{- end }}
+{{- end }}
+
+{{- if .Values.manifests.daemonset_local_volume_provisioner }}
+
+{{- $envAll := . }}
+{{- $daemonset := "local_volume_provisioner" }}
+{{- $configMapName := "local_volume_provisioner-etc" }}
+{{- $serviceAccountName := "local-volume-provisioner" }}
+
+{{ tuple $envAll "lvp" $serviceAccountName | include "helm-toolkit.snippets.kubernetes_pod_rbac_serviceaccount" }}
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: {{ $serviceAccountName }}-nodes
+rules:
+- apiGroups: [""]
+  resources: ["nodes"]
+  verbs: ["get"]
+
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+  name: {{ $serviceAccountName }}-nodes
+subjects:
+- kind: ServiceAccount
+  name: {{ $serviceAccountName }}
+  namespace: {{ .Release.Namespace }}
+roleRef:
+  kind: ClusterRole
+  name: {{ $serviceAccountName }}-nodes
+  apiGroup: rbac.authorization.k8s.io
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+  name: {{ $serviceAccountName }}-cluter-admin
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: cluster-admin
+subjects:
+- kind: ServiceAccount
+  name: {{ $serviceAccountName }}
+  namespace: {{ .Release.Namespace }}
+
+{{- $daemonset_yaml := list $daemonset $configMapName $serviceAccountName . | include "lvp.daemonset" | toString | fromYaml }}
+{{- $configmap_yaml := "lvp.configmap.etc" }}
+{{- list $daemonset $daemonset_yaml $configmap_yaml $configMapName . | include "helm-toolkit.utils.daemonset_overrides" }}
+
+{{- end }}
diff --git a/local-volume-provisioner/templates/job-image-repo-sync.yaml b/local-volume-provisioner/templates/job-image-repo-sync.yaml
new file mode 100644
index 0000000000..1aab34c9c3
--- /dev/null
+++ b/local-volume-provisioner/templates/job-image-repo-sync.yaml
@@ -0,0 +1,18 @@
+{{/*
+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.
+*/}}
+
+{{- if and .Values.manifests.job_image_repo_sync .Values.images.local_registry.active }}
+{{- $imageRepoSyncJob := dict "envAll" . "serviceName" "local-volume-provisioner" -}}
+{{ $imageRepoSyncJob | include "helm-toolkit.manifests.job_image_repo_sync" }}
+{{- end }}
diff --git a/local-volume-provisioner/templates/secret-registry.yaml b/local-volume-provisioner/templates/secret-registry.yaml
new file mode 100644
index 0000000000..da979b3223
--- /dev/null
+++ b/local-volume-provisioner/templates/secret-registry.yaml
@@ -0,0 +1,17 @@
+{{/*
+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.
+*/}}
+
+{{- if and .Values.manifests.secret_registry .Values.endpoints.oci_image_registry.auth.enabled }}
+{{ include "helm-toolkit.manifests.secret_registry" ( dict "envAll" . "registryUser" .Chart.Name ) }}
+{{- end }}
diff --git a/local-volume-provisioner/templates/storageclasses.yaml b/local-volume-provisioner/templates/storageclasses.yaml
new file mode 100644
index 0000000000..33b573c9eb
--- /dev/null
+++ b/local-volume-provisioner/templates/storageclasses.yaml
@@ -0,0 +1,27 @@
+{{- if .Values.manifests.storageclass }}
+{{- $envAll := . }}
+{{- range $val := $envAll.Values.conf.fake_mounts.classes }}
+{{- if $val.storageClass }}
+---
+apiVersion: storage.k8s.io/v1
+kind: StorageClass
+metadata:
+  name: {{ $val.name }}
+  {{- if kindIs "map" $val.storageClass }}
+  {{- if $val.storageClass.isDefaultClass }}
+  annotations:
+    storageclass.kubernetes.io/is-default-class: "true"
+  {{- end }}
+  {{- end }}
+  labels:
+{{ tuple $envAll $envAll.Chart.Name "storageclass" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 4 }}
+provisioner: kubernetes.io/no-provisioner
+volumeBindingMode: WaitForFirstConsumer
+{{- if kindIs "map" $val.storageClass }}
+reclaimPolicy: {{ $val.storageClass.reclaimPolicy | default "Delete" }}
+{{- else }}
+reclaimPolicy: Delete
+{{- end }}
+{{- end }}
+{{- end }}
+{{- end }}
diff --git a/local-volume-provisioner/values.yaml b/local-volume-provisioner/values.yaml
new file mode 100644
index 0000000000..4cbb5db223
--- /dev/null
+++ b/local-volume-provisioner/values.yaml
@@ -0,0 +1,153 @@
+# 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.
+
+# Default values for local-volume-provisioner.
+# This is a YAML-formatted file.
+# Declare name/value pairs to be passed into your templates.
+# name: value
+
+---
+release_group: null
+
+labels:
+  local_volume_provisioner:
+    node_selector_key: openstack-compute-node
+    node_selector_value: enabled
+
+images:
+  tags:
+    local_volume_provisioner: mirantis.azurecr.io/bm/external/local-volume-provisioner:v2.4.0
+    dep_check: quay.io/airshipit/kubernetes-entrypoint:latest-ubuntu_focal
+    image_repo_sync: docker.io/library/docker:17.07.0
+    local_volume_provisioner_mounts: mirantis.azurecr.io/openstack/openstack-controller:0.1.1
+  pull_policy: "IfNotPresent"
+  local_registry:
+    active: false
+    exclude:
+      - dep_check
+      - image_repo_sync
+
+dependencies:
+  static: {}
+  dynamic: {}
+
+endpoints:
+  cluster_domain_suffix: cluster.local
+  local_image_registry:
+    name: docker-registry
+    namespace: docker-registry
+    hosts:
+      default: localhost
+      internal: docker-registry
+      node: localhost
+    host_fqdn_override:
+      default: null
+    port:
+      registry:
+        node: 5000
+  oci_image_registry:
+    name: oci-image-registry
+    namespace: oci-image-registry
+    auth:
+      enabled: false
+      local_volume_provisioner:
+        username: local_volume_provisioner
+        password: password
+    hosts:
+      default: localhost
+    host_fqdn_override:
+      default: null
+    port:
+      registry:
+        default: null
+
+conf:
+  fake_mounts:
+    classes:
+      - bindMounts:
+        - mounts:
+          - vol1
+          - vol2
+          - vol3
+          - vol4
+          - vol5
+          - vol6
+          - vol7
+          - vol8
+          - vol9
+          - vol10
+          - vol11
+          - vol12
+          - vol13
+          - vol14
+          - vol15
+          srcRoot: /var/lib/local-volume-provisioner
+        hostDir: /mnt/local-volume-provisioner
+        mountDir: /mnt/local-volume-provisioner
+        name: lvp-fake-root
+        storageClass: true
+        volumeMode: Filesystem
+pod:
+  security_context:
+    local_volume_provisioner:
+      pod:
+        runAsUser: 0
+      container:
+        lvp:
+          privileged: true
+          readOnlyRootFilesystem: true
+        init_mounts:
+          privileged: true
+          readOnlyRootFilesystem: true
+  dns_policy: "ClusterFirstWithHostNet"
+  mounts:
+    local_volume_provisioner:
+      init_container: null
+      lvp: null
+  lifecycle:
+    upgrades:
+      daemonsets:
+        pod_replacement_strategy: RollingUpdate
+        local_volume_provisioner:
+          enabled: true
+          min_ready_seconds: 0
+          max_unavailable: 1
+  resources:
+    enabled: false
+    local_volume_provisioner:
+      requests:
+        memory: "128Mi"
+        cpu: "100m"
+      limits:
+        memory: "1024Mi"
+        cpu: "2000m"
+    jobs:
+      image_repo_sync:
+        requests:
+          memory: "128Mi"
+          cpu: "100m"
+        limits:
+          memory: "1024Mi"
+          cpu: "2000m"
+
+manifests:
+  configmap_bin: true
+  configmap_etc: true
+  daemonset_local_volume_provisioner: true
+  job_image_repo_sync: true
+  secret_registry: true
+  storageclass: true
+
+secrets:
+  oci_image_registry:
+    local_volume_provisioner: local-volume-provisioner-oci-image-registry-key
+...
diff --git a/releasenotes/notes/local-volume-provisioner.yaml b/releasenotes/notes/local-volume-provisioner.yaml
new file mode 100644
index 0000000000..ccf1a1731b
--- /dev/null
+++ b/releasenotes/notes/local-volume-provisioner.yaml
@@ -0,0 +1,4 @@
+---
+local-volume-provisioner:
+  - 0.1.0 Initial Chart
+...