Skip to content

Commit

Permalink
Ensure poetry path to binaries in local files #2540
Browse files Browse the repository at this point in the history
Following our transition to Poetry, some local files generated
by Rockstor can still include now-legacy path to Rockstor binaries.
This commit ensures these local files include the new paths to the
binaries in the Poetry venv or correct when necessary at Rockstor's
start time.

Explicitly set file mask to defined setting or copied from target
file.

Check for status of associated systemd service (if defined) and
restart if currently active.
  • Loading branch information
FroggyFlox committed May 25, 2023
1 parent e5c3126 commit 3acb294
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 2 deletions.
73 changes: 71 additions & 2 deletions src/rockstor/scripts/initrock.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,17 @@
import os
import re
import shutil
import stat
import sys
from tempfile import mkstemp

from django.conf import settings

from system import services
from system.osi import run_command, md5sum
from system.osi import run_command, md5sum, replace_pattern_inline
from system.ssh import remove_sftp_server_subsystem, init_sftp_config
from system.constants import SYSTEMCTL
from collections import OrderedDict
from collections import OrderedDict, namedtuple


logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -105,6 +106,30 @@
"rockstor-ipv6check.service", # Legacy service from pre v4.1.0-0 development.
]

# Local files that need checking
# path: path to file.
# mask: use constants from the stat module to apply desired permissions to file.
# use None to use the current mask of the target file defined at <path>.
# services: Python List of service(s) to restart, if any, after modifying the file.
LocalFile = namedtuple("LocalFile", "path mask services")
LOCAL_FILES = {
"samba_config": LocalFile(
path="/etc/samba/smb.conf",
mask=None,
services=["nmb", "smb"]
),
"rockstor_crontab": LocalFile(
path="/etc/cron.d/rockstortab",
mask=stat.S_IRUSR | stat.S_IWUSR,
services=None
),
"replication_crontab": LocalFile(
path="/etc/cron.d/replicationtab",
mask=stat.S_IRUSR | stat.S_IWUSR,
services=None
),
}


def inet_addrs(interface=None):
cmd = [IP, "addr", "show"]
Expand Down Expand Up @@ -379,6 +404,48 @@ def install_or_update_systemd_service(
return False


def establish_poetry_paths():
"""Ensure path to Rockstor's binaries point to Poetry venv
Before our move to Poetry, our binaries lived in /opt/rockstor/bin.
After our move to Poetry, these now reside in /opt/rockstor/.venv/bin.
While the generation of new local files using these paths account for these
new paths, pre-existing files still use the non-existent old paths.
This function checks for these local files and changes them accordingly. If one
or more systemd service is associated to these files, it restarts it/them if the
given service(s) is/are currently active.
The local files in questions are defined in the LOCAL_FILES constant.
"""
logger.info("### BEGIN Establishing poetry path to binaries in local files...")
pattern = "/opt/rockstor/bin/"
replacement = "/opt/rockstor/.venv/bin/"
for local_file in LOCAL_FILES:
if os.path.isfile(LOCAL_FILES[local_file].path):
fh, npath = mkstemp()
altered = replace_pattern_inline(
LOCAL_FILES[local_file].path, npath, pattern, replacement
)
if altered:
if LOCAL_FILES[local_file].mask is not None:
logger.debug("Set {} to mask {}".format(local_file, oct(LOCAL_FILES[local_file].mask)))
os.chmod(npath, LOCAL_FILES[local_file].mask)
else:
shutil.copystat(LOCAL_FILES[local_file].path, npath)
shutil.move(npath, LOCAL_FILES[local_file].path)
logger.info("The path to binaries in {} ({}) has been updated.".format(local_file, LOCAL_FILES[local_file].path))
if LOCAL_FILES[local_file].services is not None:
for service in LOCAL_FILES[local_file].services:
if services.is_systemd_service_active(service):
logger.info("The {} service is currently active... restart it".format(service))
run_command([SYSTEMCTL, "restart", service], log=True)
else:
os.remove(npath)
logger.info("{} already looks good.".format(local_file))
else:
logger.info("The {} ({}) could not be found".format(local_file, LOCAL_FILES[local_file].path))
logger.info("### DONE establishing poetry path to binaries in local files.")


def main():
loglevel = logging.INFO
if len(sys.argv) > 1 and sys.argv[1] == "-x":
Expand Down Expand Up @@ -559,6 +626,8 @@ def main():

establish_systemd_services()

establish_poetry_paths()


if __name__ == "__main__":
main()
24 changes: 24 additions & 0 deletions src/rockstor/system/osi.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,30 @@ def append_to_line(original_file, new_file, regexes, new_content, sep, remove=Fa
tfo.write(line)


def replace_pattern_inline(source_file, target_file, pattern, replacement):
"""Replace a regex pattern with a string inline
Similar to `sed`, this function will search for the presence of the regex
pattern (re module) in a given line, and replace it with the `replacement`
string.
@param source_file: path to source file
@param target_file: path to target file
@param pattern: regex pattern
@param replacement: string
@return: boolean; True if pattern was found and replaced
"""
altered = False
with open(source_file) as sfo, open(target_file, "w") as tfo:
for line in sfo.readlines():
if re.search(pattern, line) is not None:
tfo.write(re.sub(pattern, replacement, line))
altered = True
else:
tfo.write(line)
return altered


def run_command(
cmd,
shell=False,
Expand Down
1 change: 1 addition & 0 deletions src/rockstor/system/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ def init_service_op(service_name, command, throw=True):
# to be used in for example model properties etc, where we need only a boolean.
supported_services = (
"nfs-server",
"nmb",
"smb",
"sshd",
"ypbind",
Expand Down

0 comments on commit 3acb294

Please sign in to comment.