diff --git a/local-volume-provisioner/Chart.yaml b/local-volume-provisioner/Chart.yaml new file mode 100644 index 000000000..a33684e87 --- /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 000000000..84f0affae --- /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 000000000..e9a937f4e --- /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 "".format(str(self)) + except InvalidEntry: + return "" +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 = "