Compare commits
27 Commits
ticket-261
...
main
Author | SHA1 | Date |
---|---|---|
|
b2066d3e5d | |
|
eace7142ae | |
|
8bd472fd6b | |
|
6ea7699ca5 | |
|
c9c8952741 | |
|
e0b9a036ca | |
|
206853bd23 | |
|
1761ec4378 | |
|
d8f3eb0a19 | |
|
4447126891 | |
|
49f72febf8 | |
|
6811665993 | |
|
bc134d13a4 | |
|
8611995dda | |
|
1256229340 | |
|
f6617aee77 | |
|
4301fb4635 | |
|
597f0a156b | |
|
7a878edf1d | |
|
32174016be | |
|
75efb96653 | |
|
ae1cec5cd4 | |
|
04c9cd7950 | |
|
bc50845742 | |
|
c964ab75da | |
|
61e2e2468d | |
|
ef8112b8c1 |
41
CHANGELOG.md
41
CHANGELOG.md
|
@ -1,17 +1,50 @@
|
|||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [0.10.4] - 2025-09-30
|
||||
|
||||
### Fixed
|
||||
|
||||
- Set safe.directory just once
|
||||
|
||||
## [0.10.3] - 2025-09-18
|
||||
|
||||
### Changed
|
||||
|
||||
- Create tags via a query to the forgejo API
|
||||
|
||||
## [0.10.2] - 2025-09-01
|
||||
|
||||
### Fixed
|
||||
|
||||
- Corregida la logica en el endpoint create torrent sum
|
||||
- Mejoras en los mensajes de logs
|
||||
- Mejoras en la validación de los archivos info e info.checked
|
||||
|
||||
## [0.10.1] - 2025-08-25
|
||||
|
||||
### Fixed
|
||||
|
||||
- Import images problems when there is not info.checked file (#2723, #2726)
|
||||
- Improves logging (#2727)
|
||||
|
||||
## [0.10.0] - 2025-07-07
|
||||
|
||||
### Added
|
||||
|
||||
- OgGit functionality (#2371, #2363, #2363, #2317)
|
||||
- OgGit functionality (#2371, #2363, #2363, #2317)
|
||||
|
||||
### Removed
|
||||
- Removed unused BitTorrent-related packages and logic
|
||||
### Removed
|
||||
|
||||
- Removed unused BitTorrent-related packages and logic
|
||||
|
||||
## [0.9.0] - 2025-06-25
|
||||
|
||||
## Added
|
||||
### Added
|
||||
|
||||
- Changed old tools for tools non dependant of Pyhton2 in repo
|
||||
- mktorrent to handle creation of torrent files
|
||||
|
|
|
@ -99,15 +99,22 @@ pipeline {
|
|||
}
|
||||
}
|
||||
post {
|
||||
success {
|
||||
script {
|
||||
// Solo lanzar cuando el build sea exitoso y en la rama main
|
||||
if (env.BRANCH_NAME == 'main') {
|
||||
build job: 'Aptly publish nightly repository',
|
||||
wait: false,
|
||||
parameters: [
|
||||
string(name: 'TRIGGERED_BY', value: "${env.JOB_NAME}-${env.BUILD_NUMBER}")
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
always {
|
||||
notifyBuildStatus('narenas@qindel.com')
|
||||
notifyBuildStatus('opengnsys@qindel.com')
|
||||
}
|
||||
}
|
||||
}
|
||||
// stage ('Publish to Debian Repository') {
|
||||
// agent { label 'debian-repo' }
|
||||
// steps {
|
||||
// sh "aptly repo add opengnsys-devel /var/tmp/opengnsys/debian-repo/*.deb"
|
||||
// }
|
||||
// }
|
||||
|
||||
|
|
424
api/repo_api.py
424
api/repo_api.py
File diff suppressed because it is too large
Load Diff
197
api/swagger.yaml
197
api/swagger.yaml
|
@ -2087,6 +2087,203 @@ paths:
|
|||
error:
|
||||
type: string
|
||||
example: "Parameters missing"
|
||||
/ogrepository/v1/git/repositories/{repository}:
|
||||
delete:
|
||||
summary: "Eliminar repositorio"
|
||||
description: |
|
||||
Elimina un repositorio de Git
|
||||
tags:
|
||||
- "Git"
|
||||
parameters:
|
||||
- name: repository
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
description: "Nombre de repositorio"
|
||||
responses:
|
||||
"200":
|
||||
description: "Repositorio eliminado"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
example: deleted
|
||||
"404":
|
||||
description: "Repositorio no encontrado"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
example: not found
|
||||
"500":
|
||||
description: "Excepción"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
exception:
|
||||
type: string
|
||||
example: "(Exception description)"
|
||||
|
||||
/ogrepository/v1/git/repositories/{repository}/sync:
|
||||
post:
|
||||
summary: "Sincronizar con repositorio remoto"
|
||||
description: |
|
||||
Sincroniza un repositorio de Git con uno remoto.
|
||||
tags:
|
||||
- "Git"
|
||||
parameters:
|
||||
- name: repository
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
description: "Nombre de repositorio"
|
||||
- name: JSON
|
||||
in: body
|
||||
required: true
|
||||
description: |
|
||||
* **remote_repository** - Reposition remoto al que hacer push
|
||||
responses:
|
||||
"200":
|
||||
description: "Repositorio en proceso de sincronización"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: True
|
||||
output:
|
||||
type: string
|
||||
example: "Synchronizing..."
|
||||
job_id:
|
||||
type: string
|
||||
example: "GitSync_02345"
|
||||
"404":
|
||||
description: "Repositorio no encontrado"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
example: not found
|
||||
"500":
|
||||
description: "Excepción"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
exception:
|
||||
type: string
|
||||
example: "(Exception description)"
|
||||
/ogrepository/v1/git/repositories/{repository}/backup:
|
||||
post:
|
||||
summary: "Sincronizar con repositorio remoto"
|
||||
description: |
|
||||
Sincroniza un repositorio de Git con uno remoto.
|
||||
tags:
|
||||
- "Git"
|
||||
parameters:
|
||||
- name: repository
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
description: "Nombre de repositorio"
|
||||
- name: JSON
|
||||
in: body
|
||||
required: true
|
||||
description: |
|
||||
* **ssh_server** - Servidor SSH al que enviar el backup
|
||||
* **ssh_port** - Puerto del servidor SSH al que enviar el backup
|
||||
* **ssh_user** - Usuario del servidor SSH al que enviar el backup
|
||||
* **filename** - Nombre de archivo del backup
|
||||
responses:
|
||||
"200":
|
||||
description: "Repositorio en proceso de sincronización"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: True
|
||||
output:
|
||||
type: string
|
||||
example: "Backing up..."
|
||||
job_id:
|
||||
type: string
|
||||
example: "GitBackup_02345"
|
||||
"404":
|
||||
description: "Repositorio no encontrado"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
example: not found
|
||||
"500":
|
||||
description: "Excepción"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
exception:
|
||||
type: string
|
||||
example: "(Exception description)"
|
||||
/ogrepository/v1/git/repositories/{repository}/compact:
|
||||
post:
|
||||
summary: "Compactar repositorio"
|
||||
description: |
|
||||
Compacta un repositorio de Git para optimizar el rendimiento y liberar espacio
|
||||
tags:
|
||||
- "Git"
|
||||
parameters:
|
||||
- name: repository
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
description: "Nombre de repositorio"
|
||||
responses:
|
||||
"200":
|
||||
description: "Repositorio en proceso de compactación"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: True
|
||||
output:
|
||||
type: string
|
||||
example: "Compacting..."
|
||||
job_id:
|
||||
type: string
|
||||
example: "GitGC_02345"
|
||||
"404":
|
||||
description: "Repositorio no encontrado"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
example: not found
|
||||
"500":
|
||||
description: "Excepción"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
exception:
|
||||
type: string
|
||||
example: "(Exception description)"
|
||||
|
||||
/ogrepository/v1/git/repositories/{repository}/tags:
|
||||
get:
|
||||
summary: "Obtener lista de tags"
|
||||
|
|
|
@ -184,11 +184,16 @@ def main():
|
|||
# Obtenemos la ruta completa de la imagen:
|
||||
file_path = build_file_path()
|
||||
|
||||
# Si no existe el archivo de imagen, imprimimos un mensaje de error y salimos del script:
|
||||
if not os.path.exists(file_path):
|
||||
journal.send("createTorrentSum.py: Image not found", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Image file doesn't exist")
|
||||
# Si no existe el archivo de imagen o el .info, imprimimos un mensaje de error y salimos del script:
|
||||
if not os.path.exists(file_path) or not (os.path.exists(f"{file_path}.info.checked") or os.path.exists(f"{file_path}.info")):
|
||||
if not os.path.exists(file_path):
|
||||
journal.send(f"createTorrentSum.py: Image file '{file_path}' not found", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"Image file '{file_path}' doesn't exist")
|
||||
if not os.path.exists(f"{file_path}.info.checked") and not os.path.exists(f"{file_path}.info"):
|
||||
journal.send(f"createTorrentSum.py: Neither '{file_path}.info.checked' nor '{file_path}.info' found", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"Neither info file '{file_path}.info.checked' nor '{file_path}.info' exists")
|
||||
sys.exit(2)
|
||||
|
||||
|
||||
# Si la imagen está bloqueada, imprimimos un mensaje de error y salimos del script:
|
||||
if os.path.exists(f"{file_path}.lock"):
|
||||
|
@ -257,7 +262,8 @@ def main():
|
|||
# Actualizamos la información del repositorio, ejecutando el script "updateRepoInfo.py":
|
||||
journal.send("createTorrentSum.py: Updating repository info...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Updating Repository Info...")
|
||||
update_repo_info()
|
||||
if os.path.exists(f"{file_path}.info"):
|
||||
update_repo_info()
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -67,33 +67,50 @@ def check_files():
|
|||
continue
|
||||
# Comprobamos si existe un archivo ".info" asociado a la imagen actual:
|
||||
info_file = f"{img_path}.info"
|
||||
if os.path.exists(info_file):
|
||||
# Si la fecha de modificación del archivo ".info" es anterior a la de la imagen, lo eliminamos (porque estará desactualizado):
|
||||
if os.path.getmtime(info_file) < os.path.getmtime(img_path):
|
||||
os.remove(info_file)
|
||||
print(f"Warning: Deleted outdated file {info_file}")
|
||||
try:
|
||||
if os.path.exists(info_file):
|
||||
# Si la fecha de modificación del archivo ".info" es anterior a la de la imagen, lo eliminamos (porque estará desactualizado):
|
||||
if os.path.getmtime(info_file) < os.path.getmtime(img_path):
|
||||
os.remove(info_file)
|
||||
print(f"Warning: Deleted outdated file {info_file}")
|
||||
# En caso contrario, almacenamos el contenido del archivo ".info" (del tipo "PARTCLONE:LZOP:EXTFS:8500000:Ubuntu_20") en la variable "data":
|
||||
else:
|
||||
with open(info_file, 'r') as file:
|
||||
info_data = file.read()
|
||||
# Almacenamos el contenido de los archivos ".size", ".sum" y ".full.sum":
|
||||
with open(f"{img_path}.size", 'r') as file:
|
||||
size = file.read().strip('\n')
|
||||
with open(f"{img_path}.sum", 'r') as file:
|
||||
_sum = file.read().strip('\n')
|
||||
with open(f"{img_path}.full.sum", 'r') as file:
|
||||
fullsum = file.read().strip('\n')
|
||||
# Llamamos a la función "add_to_json", para que inserte la información de la imagen en el archivo json
|
||||
# (pasándole el nombre de la imagen, la extensión, y los datos extraídos del archivo ".info"):
|
||||
img_name = os.path.relpath(img_path, repo_path)
|
||||
add_to_json(os.path.splitext(img_name)[0], os.path.splitext(img_name)[1][1:], info_data, size, _sum, fullsum)
|
||||
else:
|
||||
with open(info_file, 'r') as file:
|
||||
info_data = file.read()
|
||||
# Almacenamos el contenido de los archivos ".size", ".sum" y ".full.sum":
|
||||
with open(f"{img_path}.size", 'r') as file:
|
||||
size = file.read().strip('\n')
|
||||
with open(f"{img_path}.sum", 'r') as file:
|
||||
sum = file.read().strip('\n')
|
||||
with open(f"{img_path}.full.sum", 'r') as file:
|
||||
fullsum = file.read().strip('\n')
|
||||
|
||||
# Renombramos el archivo ".info" a ".info.checked", para que ya no se añada la información que contiene
|
||||
# (originalmente se eliminaba el archivo, pero creo que es mejor mantenerlo):
|
||||
os.rename(info_file, f"{info_file}.checked")
|
||||
# Renombramos el archivo ".info" a ".info.checked", para que ya no se añada la información que contiene
|
||||
# (originalmente se eliminaba el archivo, pero creo que es mejor mantenerlo):
|
||||
os.rename(info_file, f"{info_file}.checked")
|
||||
|
||||
# Llamamos a la función "add_to_json", para que inserte la información de la imagen en el archivo json
|
||||
# (pasándole el nombre de la imagen, la extensión, y los datos extraídos del archivo ".info"):
|
||||
img_name = os.path.relpath(img_path, repo_path)
|
||||
add_to_json(os.path.splitext(img_name)[0], os.path.splitext(img_name)[1][1:], info_data, size, sum, fullsum)
|
||||
|
||||
|
||||
def add_to_json(image_name, image_type, data, size, _sum, fullsum):
|
||||
except (IOError, OSError, PermissionError) as e:
|
||||
# Si hay algún error leyendo los archivos, registramos el error y continuamos con la siguiente imagen
|
||||
journal.send(f"updateRepoInfo.py: Error processing files for {img_path}: {str(e)}", PRIORITY=journal.LOG_WARNING, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"Warning: Could not process files for {item}: {str(e)}")
|
||||
continue
|
||||
except ValueError as e:
|
||||
# Si hay algún error con el formato de los datos en los archivos
|
||||
journal.send(f"updateRepoInfo.py: Data format error for {img_path}: {str(e)}", PRIORITY=journal.LOG_WARNING, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"Warning: Data format error for {item}: {str(e)}")
|
||||
continue
|
||||
except Exception as e:
|
||||
# Para cualquier otra excepción inesperada
|
||||
journal.send(f"updateRepoInfo.py: Unexpected error processing {img_path}: {str(e)}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"Error: Unexpected error processing {item}: {str(e)}")
|
||||
continue
|
||||
|
||||
def add_to_json(image_name, image_type, data, size, sum, fullsum):
|
||||
""" Esta función añade al archivo "repoinfo.json" la información de las imágenes que aun no ha sido introducida en él (imágenes nuevas, básicamente).
|
||||
"""
|
||||
# Almacenamos el contenido de la variable "data" (del tipo "PARTCLONE:LZOP:EXTFS:8500000:Ubuntu_20") en variables separadas:
|
||||
|
@ -109,7 +126,7 @@ def add_to_json(image_name, image_type, data, size, _sum, fullsum):
|
|||
"filesystem": fstype.upper(),
|
||||
"datasize": int(datasize) * 1024, # Convertimos el valor a bytes (desde KB)
|
||||
"size": int(size),
|
||||
"sum": _sum,
|
||||
"sum": sum,
|
||||
"fullsum": fullsum
|
||||
}
|
||||
# Almacenamos el contenido del archivo "repoinfo.json" en la variable "info_data"
|
||||
|
|
|
@ -42,7 +42,6 @@ USER="opengnsys"
|
|||
|
||||
if [ "$1" = "configure" ] && [ -z "$2" ]; then
|
||||
|
||||
|
||||
sed -i "s/%%OGREPOSITORY_USER%%/$SAMBA_USER/g" /etc/systemd/system/ogrepo-api.service
|
||||
sed -i "s/%%OGREPOSITORY_USER%%/$SAMBA_USER/g" /etc/samba/ogrepo-smb.conf
|
||||
|
||||
|
@ -129,5 +128,8 @@ systemctl daemon-reload
|
|||
systemctl enable ogrepo-api
|
||||
systemctl restart ogrepo-api
|
||||
systemctl restart smbd
|
||||
systemctl enable --now opentracker || true
|
||||
systemctl restart opentracker || true
|
||||
|
||||
|
||||
exit 0
|
||||
|
|
|
@ -10,6 +10,25 @@ Cmnd_Alias MOUNT_RECOVERY = \
|
|||
/usr/bin/umount /mnt/recovery/sys, \
|
||||
/usr/bin/umount -l /mnt/recovery
|
||||
|
||||
Cmnd_Alias OGBOOT = \
|
||||
/opt/bin/oglivecli, \
|
||||
/usr/bin/chmod, \
|
||||
/usr/bin/chown, \
|
||||
/usr/bin/md5sum, \
|
||||
/usr/bin/smbpasswd, \
|
||||
/usr/bin/cat, \
|
||||
/usr/bin/tee, \
|
||||
/usr/bin/sed, \
|
||||
/usr/bin/gzip, \
|
||||
/usr/bin/lz4, \
|
||||
/usr/bin/cpio, \
|
||||
/usr/bin/find, \
|
||||
/bin/tee, \
|
||||
/usr/bin/dd, \
|
||||
/usr/bin/mkfs.ext4, \
|
||||
/usr/bin/rsync, \
|
||||
/opt/opengnsys/ogboot/lib/*.iso /mnt
|
||||
|
||||
Cmnd_Alias CHROOT_GRUB = \
|
||||
/usr/sbin/chroot /mnt/recovery /usr/sbin/grub-install --target=i386-pc *, \
|
||||
/usr/sbin/chroot /mnt/recovery /usr/sbin/grub-mkconfig -o /boot/grub/grub.cfg
|
||||
|
@ -28,4 +47,4 @@ Cmnd_Alias KILL_BT = \
|
|||
Cmnd_Alias PYTHON_OGREPO = /usr/bin/python3 /opt/opengnsys/ogrepository/bin/*
|
||||
|
||||
# Permitir al usuario opengnsys ejecutar estos comandos sin contraseña
|
||||
opengnsys ALL=(root) NOPASSWD: MOUNT_RECOVERY, CHROOT_GRUB, LOOP_KPARTX, KILL_BT, PYTHON_OGREPO
|
||||
opengnsys ALL=(root) NOPASSWD: MOUNT_RECOVERY, CHROOT_GRUB, LOOP_KPARTX, OGBOOT, KILL_BT, PYTHON_OGREPO
|
||||
|
|
Loading…
Reference in New Issue