Merge pull request 'Clonación de branch y commit específico' (#108) from git-initial-branch into main
ogclient/pipeline/head This commit looks good Details

Reviewed-on: #108
main
Vadim vtroshchinskiy 2025-08-28 15:19:49 +02:00
commit a63e12ff54
5 changed files with 163 additions and 118 deletions

View File

@ -2,6 +2,7 @@
import sys
import resource
import logging
import argparse
import ogGlobals
@ -41,6 +42,9 @@ def create_image(disk_num, partition_num, repo, image_name):
og_git.progress_callback = OgProgressPrinterWeb()
device = DiskLib.ogDiskToDev(disk_num, partition_num)
if device is None:
sys.exit(SystemLib.ogRaiseError([], ogGlobals.OG_ERR_FORMAT, f"Failed to translate disk {disk_num} partition {partition_num} to a device"))
if og_git.initRepo(device, image_name):
return 0
else:
@ -59,19 +63,26 @@ def main():
print(f"No se pudo aumentar el límite de archivos abiertos: {e}")
parser = argparse.ArgumentParser(
prog = "OpenGnsys Git Image Create",
description = "Creates a git repository from a partition"
)
if len(sys.argv) < 5:
sys.exit(SystemLib.ogRaiseError([], ogGlobals.OG_ERR_FORMAT, "Incorrect number of arguments. Usage: CrearImagenGit disk_num partition_num image_name repo"))
parser.add_argument("--disk", type=int, metavar="DISK", required=True, help="Disk ID")
parser.add_argument("--partition", type=int, metavar="PART", required=True, help="Disk partition")
parser.add_argument("--repository", type=str, metavar="REPO", required=True, help="Address of the Git repository to clone")
parser.add_argument("--image-name", type=str, metavar="REPO", required=True, help="Name of the new image at the repository")
parser.add_argument("--tag", type=str, metavar="TAG", required=False, help="Tag to automatically create")
parser.add_argument("--message", type=str, metavar="MSG", required=False, help="Commit message")
# repo - repositorio, ip address. Opcional porque oglive lo recibe como parametro de kernel
parser.add_help = True
args = parser.parse_args()
#disk_num, partition_num, image_name, repo, tag = sys.argv[1:6]
disk_num, partition_num, image_name, repo = sys.argv[1:5]
opengnsys_log_dir = "/opt/opengnsys/log"
ip_address = NetLib.ogGetIpAddress()
logFilePath = f"{opengnsys_log_dir}/{ip_address}.log"
logFilePath = "/var/log/opengnsys.CrearImagenGit.log"
ogLog = OgLogger()
ogLog.setLevel(logging.DEBUG)
@ -91,8 +102,11 @@ def main():
logger.info("Starting CrearImagenGit")
# TODO:
# repo = repositorio, oggit@server.com:/oggit
# image = nombre repo
retval = create_image(disk_num, partition_num, repo, image_name)
retval = create_image(args.disk, args.partition, args.repository, args.image_name)

View File

@ -4,7 +4,7 @@ import subprocess
import sys
import time
import resource
import argparse
soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE)
@ -67,34 +67,56 @@ class OgLogger(logging.StreamHandler):
def commit_image(disk_num, partition_num, image_name, msg):
def commit_image(disk_num, partition_num, repository, branch, options, msg):
ntfs_impl = NTFSImplementation.NTFS3G
og_git = OpengnsysGitLibrary(ntfs_implementation = ntfs_impl)
og_git.progress_callback = OgProgressPrinterWeb()
device = DiskLib.ogDiskToDev(disk_num, partition_num)
og_git.commit(device = device, message = msg)
og_git.push(device = device)
if device is None:
sys.exit(SystemLib.ogRaiseError([], ogGlobals.OG_ERR_FORMAT, f"Failed to translate disk {disk_num} partition {partition_num} to a device"))
force_push = False
if options:
opts = options.split(",")
if "force_push" in opts:
force_push = True
try:
if branch:
if not og_git.create_branch(device = device, name = branch):
sys.exit(SystemLib.ogRaiseError([], ogGlobals.OG_ERR_FORMAT, f"Failed to create branch"))
og_git.commit(device = device, message = msg)
og_git.push(device = device, force = force_push)
except Exception as ex:
sys.exit(SystemLib.ogRaiseError([], ogGlobals.OG_ERR_FORMAT, f"Exception during commit: {ex}"))
return 0
def main():
if len(sys.argv) != 5:
import json
args = json.dumps(sys.argv)
sys.exit(SystemLib.ogRaiseError([], ogGlobals.OG_ERR_FORMAT, f"Incorrect number of arguments. Usage: ModificarImagenGit disk_num partition_num image_name repo msg. Received args: {args}"))
# repo - repositorio, ip address. Opcional porque oglive lo recibe como parametro de kernel
# tag - tag a crear automaticamente. Opcional, no necesitamos crear un tag siempre.
disk_num, partition_num, image_name, msg = sys.argv[1:5]
parser = argparse.ArgumentParser(
prog = "OpenGnsys Git Image Modify",
description = "Commits changes to a partition to a git repository"
)
parser.add_argument("--disk", type=int, metavar="DISK", required=True, help="Disk ID")
parser.add_argument("--partition", type=int, metavar="PART", required=True, help="Disk partition")
parser.add_argument("--repository", type=str, metavar="REPO", required=True, help="Address of the Git repository to clone")
opengnsys_log_dir = "/opt/opengnsys/log"
ip_address = NetLib.ogGetIpAddress()
logFilePath = f"{opengnsys_log_dir}/{ip_address}.log"
parser.add_argument("--branch", type=str, metavar="BRANCH", required=False, help="Branch to automatically create")
parser.add_argument("--options", type=str, metavar="OPTS", required=False, help="Options to branch creation (forcepush)")
parser.add_argument("--message", type=str, metavar="MSG", required=False, help="Commit message")
parser.add_help = True
args = parser.parse_args()
logFilePath = "/var/log/opengnsys.ModificarImagenGit.log"
ogLog = OgLogger()
ogLog.setLevel(logging.DEBUG)
@ -114,7 +136,7 @@ def main():
logger.info("Starting ModificarImagenGit")
retval = commit_image(disk_num, partition_num, image_name, msg)
retval = commit_image(args.disk, args.partition, args.repository, args.branch, args.options, args.message)
logger.info("ModificarImagenGit done, return code %i", retval)

View File

@ -10,6 +10,10 @@ import DiskLib
from GitLib import OpengnsysGitLibrary, NTFSImplementation, OgProgressPrinterWeb
import argparse
class OgLogger(logging.StreamHandler):
def emit(self, record):
log_types = ["command"]
@ -42,20 +46,25 @@ if __name__ == "__main__":
print(f"No se pudo aumentar el límite de archivos abiertos: {e}")
if len(sys.argv) < 6:
print("Usage: python RestaurarImagenGit <disk> <partition> <repo> <ip> <ref> <protocol>")
sys.exit(1)
disk = sys.argv[1]
partition = sys.argv[2]
repo = sys.argv[3]
ipaddr = sys.argv[4]
gitref = sys.argv[5]
proto = sys.argv[6]
parser = argparse.ArgumentParser(
prog = "OpenGnsys Git Image Restore",
description = "Restores an image from Git"
)
opengnsys_log_dir = "/opt/opengnsys/log"
ip_address = NetLib.ogGetIpAddress()
logFilePath = f"{opengnsys_log_dir}/{ip_address}.log"
parser.add_argument("--disk", type=int, metavar="DISK", required=True, help="Disk ID")
parser.add_argument("--partition", type=int, metavar="PART", required=True, help="Disk partition")
parser.add_argument("--repository", type=str, metavar="REPO", required=True, help="Address of the Git repository to clone")
parser.add_argument("--image-name", type=str, metavar="REPO", required=True, help="Name of the new image at the repository")
parser.add_argument("--branch", type=str, metavar="BRANCH", required=True, help="Branch to check out")
parser.add_argument("--commit", type=str, metavar="COMMIT_ID", required=True, help="Commit to check out")
parser.add_help = True
args = parser.parse_args()
logFilePath = "/var/log/opengnsys.RestaurarImagenGit.log"
ogLog = OgLogger()
ogLog.setLevel(logging.DEBUG)
@ -81,9 +90,11 @@ if __name__ == "__main__":
og_git = OpengnsysGitLibrary(ntfs_implementation = ntfs_impl)
og_git.progress_callback = OgProgressPrinterWeb()
device = DiskLib.ogDiskToDev(disk, partition)
device = DiskLib.ogDiskToDev(args.disk, args.partition)
if device is None:
sys.exit(SystemLib.ogRaiseError([], ogGlobals.OG_ERR_FORMAT, f"Failed to translate disk {args.disk} partition {args.partition} to a device"))
og_git.cloneRepo(repo, device, device)
og_git.cloneRepo(args.image_name, destination = device, boot_device = device, ref = args.commit, branch = args.branch)
logger.info("RestaurarImagenGit Finished.")

View File

@ -47,6 +47,7 @@ from GitLib.disk import *
from GitLib.ntfs import *
from GitLib.kernel import parse_kernel_cmdline
import CacheLib
#import requests
@ -286,7 +287,8 @@ class OpengnsysGitLibrary:
self.repo_image_path = "oggit"
self.ntfs_implementation = ntfs_implementation
self.cache_dir = self._runBashFunction("ogMountCache", [])
self.cache_dir = CacheLib.ogMountCache()
# Si no hay cache, se va a crear el .git en el FS directamente
if (not self.cache_dir) and require_cache:
@ -348,6 +350,7 @@ class OpengnsysGitLibrary:
self.repo_server = self.kernel_args["ogrepo"]
self.ip_address = self.kernel_args["ip"]
self.initial_branch = "main"
if not self.repo_server:
self.logger.warning("ogrepo kernel argument wasn't passed, or was empty. Defaulting to oglive.")
@ -602,64 +605,6 @@ class OpengnsysGitLibrary:
except OSError as e:
self.logger.warning('Failed to delete %s. Error: %s', file_path, e)
def _runBashFunction(self, function, arguments):
"""
Executes an OpenGnsys bash function with given arguments.
This method creates a temporary bash script that sources all `.lib` files in a specific directory,
writes the specified bash function and its arguments to the script, makes the script executable,
and then runs the script. The output and errors from the script execution are captured and logged.
This is a temporary migration convenience function, it won't be present once the rest of the
code is migrated to Python.
Args:
function (str): The name of the bash function to execute.
arguments (list): A list of arguments to pass to the bash function.
Returns:
str: The standard output from the executed bash function.
Logs:
- Debug information about the bash function and arguments being run.
- The path of the temporary file created.
- The command being executed.
- The standard output and standard error from the script execution.
"""
# Create a temporary file
self.logger.debug(f"Running bash function: {function} {arguments}")
with tempfile.NamedTemporaryFile(mode='w', delete=False) as temp_file:
temp_file.write("#!/bin/bash\n")
temp_file.write("for lib in /opt/opengnsys/client/lib/engine/bin/*.lib ; do\n")
temp_file.write(" source $lib\n")
temp_file.write("done\n")
#temp_file.write("source /opt/oglive/rootfs/opt/opengnsys/lib/engine/bin/Cache.lib")
#temp_file.write("source /opt/oglive/rootfs/opt/opengnsys/lib/engine/bin/Git.lib")
temp_file.write(f"{function} \"$@\"\n")
# Make the temporary file executable
os.chmod(temp_file.name, 0o755)
self.logger.debug(f"File: {temp_file.name}")
# Run the temporary file
command = [temp_file.name] + arguments
self.logger.debug(f"Running: {command} {arguments}")
result = subprocess.run(command, shell=False, capture_output=True, text=True, check=True)
output = result.stdout.strip()
self.logger.debug(f"STDOUT: {output}")
self.logger.debug(f"STDERR: {result.stderr}")
return output
def _getOgRepository(self, name):
return f"{self.repo_user}@{self.repo_server}:{self.repo_image_path}/{name}.git"
@ -1370,7 +1315,7 @@ class OpengnsysGitLibrary:
os.symlink(real_git_dir, git_dir)
with git.Repo.init(path) as repo:
with git.Repo.init(path, initial_branch = self.initial_branch) as repo:
# On NTFS, we have to unmount the filesystem to do secaudit.
# Gitpython objects existing at that time may mean a dangling git process that prevents
# the required unmounting.
@ -1392,7 +1337,7 @@ class OpengnsysGitLibrary:
self.logger.debug("Fetching origin, callback=%s", self.progress_callback)
origin.fetch(progress=self.progress_callback)
repo.heads.master.set_tracking_branch(origin.refs.master)
repo.heads.main.set_tracking_branch(origin.refs.main)
metadata_ret = self._create_metadata(path, initial_creation=True)
@ -1479,7 +1424,7 @@ class OpengnsysGitLibrary:
self.logger.info("initRepo done")
return True
def cloneRepo(self, repo_name, destination, boot_device):
def cloneRepo(self, repo_name, destination, boot_device, ref = None, branch = None):
"""
Clones a repository to a specified destination and sets up the bootloader.
@ -1542,12 +1487,40 @@ class OpengnsysGitLibrary:
self.logger.info("Cloning repository from %s", repo_url)
repo = git.Repo.clone_from(repo_url, destination_dir, multi_options = [f"--separate-git-dir={real_git_dir}"], progress=self.progress_callback)
if repo_is_efi:
self._efi_install(root_directory=destination_dir)
if branch:
# We've got a nearby branch, start from that
self.logger.debug("Cloning repo %s, branch %s", repo_url, branch)
repo = git.Repo.clone_from(repo_url, destination_dir, branch = branch, multi_options = [f"--separate-git-dir={real_git_dir}"], progress=self.progress_callback)
else:
self._grub_install(root_directory=destination_dir, boot_device=boot_device)
# Start from main instead
self.logger.debug("Cloning repo %s", repo_url)
repo = git.Repo.clone_from(repo_url, destination_dir, multi_options = [f"--separate-git-dir={real_git_dir}"], progress=self.progress_callback)
self.logger.debug("Checking out indicated branch %s", branch)
remote_branch_ref = repo.heads[branch]
if branch in repo.heads:
self.logger.debug("Local branch %s exists, checking it out first", branch)
repo.git.checkout(branch)
self.logger.debug("Resetting branch %s to ref %s", branch, ref)
repo.git.reset("--hard", ref)
else:
if ref:
self.logger.debug("Local branch adjusted to ref %s", ref)
local_ref = repo.create_head(branch, ref)
else:
self.logger.debug("Local branch is set to remote branch %s", remote_branch_ref)
local_ref = repo.create_head(branch, remote_branch_ref)
local_ref.set_tracking_branch(remote_branch_ref)
self.logger.debug("Checking out local branch %s", branch)
local_ref.checkout()
self.fs.mklostandfound(destination_dir)
self._restore_metadata(destination_dir, set_device_uuids=True)
@ -1555,6 +1528,12 @@ class OpengnsysGitLibrary:
if self.fs.filesystem_type(mountpoint = destination_dir) == "ntfs":
self._ntfs_restore_secaudit(destination_dir)
if repo_is_efi:
self._efi_install(root_directory=destination_dir)
else:
self._grub_install(root_directory=destination_dir, boot_device=boot_device)
self.logger.info("Clone completed.")
@ -1614,7 +1593,23 @@ class OpengnsysGitLibrary:
# Restaurar cosas modificadas para git
self._restore_metadata(path, destructive_only=True)
def push(self, path = None, device = None):
def create_branch(self, path = None, device = None, name = ""):
if path is None:
path = self.fs.ensure_mounted(device)
repo = git.Repo(path)
if name in repo.branches:
self.logger.error("Can't create branch, it already exists")
return False
self.logger.info("Creating branch %s", name)
new_branch = repo.create_head(name)
repo.head.reference = new_branch
repo.head.reset(index=True, working_tree=True)
return True
def push(self, path = None, device = None, force = False):
"""
Push local changes to ogrepository
@ -1633,9 +1628,10 @@ class OpengnsysGitLibrary:
return
origin = repo.remotes["origin"]
repo.heads.master.set_tracking_branch(origin.refs.master)
repo.heads.main.set_tracking_branch(origin.refs.main)
origin.push(progress=self.progress_callback)
ret = origin.push(progress=self.progress_callback, force = force)
ret.raise_if_error()
#repo.git.push("--set-upstream", "origin", repo.head.ref, "--force") # force = True)
@ -1791,7 +1787,6 @@ if __name__ == '__main__':
og_git = OpengnsysGitLibrary(ntfs_implementation = ntfs_impl)
# og_git._runBashFunction("ogMountCache", [])
# if args.init_repo:

View File

@ -41,7 +41,7 @@ class FilesystemLibrary:
try:
with open(file, "r", encoding='utf-8') as f:
data = f.read()
except IOError as io_err:
except Exception as io_err:
self.logger.debug("IO Error reading file %s: %s", file, io_err)
return data
@ -51,7 +51,7 @@ class FilesystemLibrary:
try:
data = os.readlink(file)
except IOError as io_err:
except Exception as io_err:
self.logger.debug("IO Error reading link %s: %s", file, io_err)
return data
@ -106,13 +106,16 @@ class FilesystemLibrary:
self.logger.debug("PID %s (%s) is has a working directory within %s: %s", pid_dir, command_name, path, working_dir)
pids_using_path[pid_dir] = { "cmd" : command_name, "args" : cmdline}
else:
for fd_file in os.listdir(fd_path):
fd_file_full_path = os.path.join(fd_path, fd_file)
target = self._read_link(fd_file_full_path)
try:
for fd_file in os.listdir(fd_path):
fd_file_full_path = os.path.join(fd_path, fd_file)
target = self._read_link(fd_file_full_path)
if target.startswith(path):
self.logger.debug("PID %s (%s) is has an open file within %s: %s", pid_dir, command_name, path, target)
pids_using_path[pid_dir] = { "cmd" : command_name, "args" : cmdline}
if target.startswith(path):
self.logger.debug("PID %s (%s) is has an open file within %s: %s", pid_dir, command_name, path, target)
pids_using_path[pid_dir] = { "cmd" : command_name, "args" : cmdline}
except IOError as ioerr:
self.logger.warning("Exception during listdir: %s", ioerr)
return pids_using_path