added local copy of folder to pve then lxc

This commit is contained in:
Mathieu Broillet 2023-06-16 16:05:55 +02:00
parent cc408237d9
commit fafa85c0e1
No known key found for this signature in database
GPG Key ID: 7D4F25BC50A0AA32
4 changed files with 79 additions and 53 deletions

View File

@ -6,6 +6,7 @@ from typing import TYPE_CHECKING
from . import lxc_utils from . import lxc_utils
from ..utils.resources_utils import get_path from ..utils.resources_utils import get_path
from ..utils.utils import optional
if TYPE_CHECKING: if TYPE_CHECKING:
from .lxc import LXC from .lxc import LXC
@ -58,11 +59,6 @@ def are_all_conditions_met(lxc: LXC):
for condition_type in step["conditions"]: for condition_type in step["conditions"]:
result = check_conditions(c_type=condition_type, parent=step["conditions"], lxc=lxc, result=result) result = check_conditions(c_type=condition_type, parent=step["conditions"], lxc=lxc, result=result)
if all(result):
logging.info(f"All creations conditions met for LXC {lxc.lxc_id}, running deploy steps...")
else:
logging.info(f"Not all creations conditions met for LXC {lxc.lxc_id}, running creation steps...")
return all(result) return all(result)
@ -121,35 +117,13 @@ def check_conditions_for_step(step: dict, lxc: LXC):
result = [] result = []
if "conditions" in step: if "conditions" in step:
for condition in step['conditions']: for condition in step['conditions']:
result.append(check_conditions(condition, parent=step['conditions'], lxc=lxc, result=result)) result = check_conditions(condition, parent=step['conditions'], lxc=lxc, result=result)
else: else:
return True return False
return all(result) return all(result)
def optional(var: any, placeholder: any):
"""Return a placeholder if the given variable is None, otherwise return the variable
Parameters
----------
var: any
Variable to check if it is None
placeholder: any
Placeholder to return if the variable is None
Returns
-------
any[any]
The variable if it is not None, otherwise the placeholder
"""
if var is None:
return placeholder
else:
return var
def run_steps(lxc: LXC): def run_steps(lxc: LXC):
"""Run the creation steps for the given LXC """Run the creation steps for the given LXC
@ -164,43 +138,44 @@ def run_steps(lxc: LXC):
for index, step in enumerate(creation_steps): for index, step in enumerate(creation_steps):
logging.info(f"Running step {index + 1}/{len(creation_steps)} for LXC {lxc.get_id()}...")
if check_conditions_for_step(step, lxc): if check_conditions_for_step(step, lxc):
logging.info(f"Conditions already met for step {index + 1}/{len(creation_steps)} for LXC {lxc.get_id()}, " logging.info(f"Conditions already met for step {index + 1}/{len(creation_steps)} for LXC {lxc.get_id()}, "
f"skipping...") f"skipping...")
break continue
logging.info(f"Running step {index + 1}/{len(creation_steps)} for LXC {lxc.get_id()}...")
match step["type"]: match step["type"]:
# Support for scripts # Support for scripts
case "script": case "script":
lxc_utils.run_script_parser(lxc, step) lxc_utils.run_script_step_parser(lxc, step)
case "file_create": case "file_create":
lxc.create_file(step["path"], optional(step["permission"], 644)) lxc.create_file(step["path"], optional(step["permission"], 644))
case "file_copy": case "file_copy":
commands_utils.copy_local_file_to_lxc(lxc, get_path(lxc, step["path"]), step["destination"]) lxc.pve.copy_file_to_lxc(lxc, get_path(lxc, step["path"]), step["destination"])
case "folder": case "folder":
commands_utils.create_folder_in_lxc(lxc, step["path"], optional(step["permission"], 755)) lxc.create_directory(step["path"], optional(step["permission"], 755))
case "folder_copy": case "folder_copy":
commands_utils.copy_local_folder_to_lxc(lxc, get_path(lxc, step["path"]), step["destination"]) lxc.pve.copy_folder_to_lxc(lxc, get_path(lxc, step["path"]), step["destination"])
case "command": case "command":
lxc.run_command(command=step["command"], working_directory=optional(step["working_directory"], None), lxc.run_command(command=step["command"], working_directory=optional(step["working_directory"], None),
return_status_code=True) return_status_code=True)
case "docker": case "docker":
commands_utils.run_docker_command(lxc, step["container"], step["command"]) lxc.run_docker_command(step["container"], step["command"])
case "docker_compose": case "docker_compose":
commands_utils.run_docker_compose_command(lxc, step["command"], lxc.run_docker_compose_command(command=step["command"],
optional(step["working_directory"], None)) working_directory=optional(step["working_directory"], None))
case "git": case "git":
lxc.run_command(command=f"git clone {step['url']} {step['destination']}", return_status_code=True) lxc.run_command(command=f"git clone {step['url']} {step['destination']}", return_status_code=True)
case "download": case "download":
commands_utils.download_file(lxc, step["url"], step["destination"]) lxc.download_file(step["url"], step["destination"])
case "unzip": case "unzip":
commands_utils.unzip_file(lxc, step["path"], optional(step["destination"], None)) lxc.unzip_file(step["path"], optional(step["destination"], None))
case "install-package": case "install-package":
commands_utils.install_package(lxc, step["package"]) lxc.install_package(step["package"])
case "remove-package": case "remove-package":
commands_utils.remove_package(lxc, step["package"]) lxc.remove_package(step["package"])
case "start": case "start":
lxc.start() lxc.start()
case "stop": case "stop":
@ -208,4 +183,4 @@ def run_steps(lxc: LXC):
case "reboot": case "reboot":
lxc.reboot() lxc.reboot()
case "replace-in-files": case "replace-in-files":
commands_utils.replace_in_files(lxc, step["files"], step["search"], step["replace"]) lxc.replace_in_files(step["files"], step["search"], step["replace"])

View File

@ -2,7 +2,7 @@ from __future__ import annotations
import fnmatch import fnmatch
import subprocess import subprocess
from pathlib import Path, PosixPath from pathlib import Path
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from fabric import Connection from fabric import Connection
@ -134,7 +134,7 @@ class ProxmoxHost(LinuxMachine):
"""Get all the LXCs on the Proxmox host.""" """Get all the LXCs on the Proxmox host."""
pct_list_output = self.run_command("pct list", exception_on_exit=False) pct_list_output = self.run_command("pct list", exception_on_exit=False)
pct_list_output = pct_list_output.split("\n")[1:] pct_list_output = pct_list_output.split("\n")[1:]
ids = [line.split()[0] for line in pct_list_output] ids = [int(line.split()[0]) for line in pct_list_output]
if not ids: if not ids:
return [] return []
@ -212,10 +212,11 @@ class ProxmoxHost(LinuxMachine):
"""Copy the given file to the given LXC.""" """Copy the given file to the given LXC."""
if isinstance(source, Path): if isinstance(source, Path):
source = str(source.as_posix()) source = str(source.as_posix())
if isinstance(destination, Path): if isinstance(destination, str):
destination = str(destination.as_posix()) destination = Path(destination)
self.run_command(f"pct push {lxc.get_id()} {source} {destination}") lxc.create_directory(destination.parent.as_posix())
self.run_command(f"pct push {lxc.get_id()} {source} {destination.as_posix()}")
def copy_folder_to_lxc(self, lxc: LXC, source: str or Path, destination: str or Path): def copy_folder_to_lxc(self, lxc: LXC, source: str or Path, destination: str or Path):
"""Copy the given folder to the given LXC.""" """Copy the given folder to the given LXC."""
@ -224,7 +225,7 @@ class ProxmoxHost(LinuxMachine):
if isinstance(destination, Path): if isinstance(destination, Path):
destination = str(destination.as_posix()) destination = str(destination.as_posix())
self.run_command(f"pct push {lxc.get_id()} {source} {destination} -r") self.run_command(f"scp -B -r {source} {lxc.get_ssh_string()}:{destination}")
def list_dir(self, directory: str or Path, glob_filter: str = '*'): def list_dir(self, directory: str or Path, glob_filter: str = '*'):
"""List the given directory.""" """List the given directory."""

View File

@ -1,10 +1,9 @@
from __future__ import annotations from __future__ import annotations
import os
import pathlib import pathlib
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from .. import project_path
if TYPE_CHECKING: if TYPE_CHECKING:
from ..lxc.lxc import LXC from ..lxc.lxc import LXC
@ -35,14 +34,15 @@ def get_path(lxc: LXC, path: str):
Complete path to the resource file Complete path to the resource file
""" """
parent = pathlib.Path(project_path).joinpath("resources") parent = pathlib.Path(lxc.pve.repo_path)
if path.startswith("global/"): if path.startswith("global/"):
# Use global folder # Use global folder
return parent.joinpath(path[len("global/"):]) return parent.joinpath(path[len("global/"):])
elif path.startswith("protected/"): elif path.startswith("protected/"):
# Use protected folder # Use protected folder
return parent.parent.joinpath("protected_resources", path[len("protected/"):]) app_path = pathlib.Path(os.path.dirname(__file__)).parent.parent
return app_path.joinpath("protected_resources", path[len("protected/"):])
else: else:
# Use VM/LXC folder # Use VM/LXC folder
lxc_id = lxc.get_id() lxc_id = lxc.get_id()

View File

@ -1,3 +1,8 @@
from pathlib import Path
from src.utils.proxmox import ProxmoxHost
def get_install_package_command(distribution: str): def get_install_package_command(distribution: str):
"""Retrieve the correct command to install a package based on the distribution specified """Retrieve the correct command to install a package based on the distribution specified
It supports all the distribution supported by Proxmox VE (from the pct command documentation). It supports all the distribution supported by Proxmox VE (from the pct command documentation).
@ -88,3 +93,48 @@ def get_remove_package_command(distribution: str):
return "zypper remove -y" return "zypper remove -y"
else: else:
raise Exception(f"Unsupported distribution: {distribution}") raise Exception(f"Unsupported distribution: {distribution}")
def optional(var: any, placeholder: any):
"""Return a placeholder if the given variable is None, otherwise return the variable
Parameters
----------
var: any
Variable to check if it is None
placeholder: any
Placeholder to return if the variable is None
Returns
-------
any[any]
The variable if it is not None, otherwise the placeholder
"""
if var is None:
return placeholder
else:
return var
def copy_local_file_to_pve(pve: ProxmoxHost, local_source: str or Path, destination: str or Path):
"""Copy a local file (in the compiled app for users) to a Proxmox VE host
Parameters
----------
pve: ProxmoxHost
Proxmox VE host to copy the file to
local_source: str or Path
Path to the local file to copy
destination: str or Path
Destination path on the Proxmox VE host
"""
if isinstance(local_source, Path):
local_source = str(local_source.as_posix())
if isinstance(destination, str):
destination = Path(destination)
pve.run_command(f"mkdir -p {destination.parent.as_posix()}")
pve.get_connection().put(local_source, destination.as_posix())