Compare commits

..

No commits in common. "main" and "add_python_scripts" have entirely different histories.

16 changed files with 359 additions and 2205 deletions

2
.gitignore vendored
View File

@ -7,5 +7,3 @@ debian/files
debian/*.debhelper debian/*.debhelper
debian/*.debhelper.log debian/*.debhelper.log
debian/debhelper-build-stamp debian/debhelper-build-stamp
.venv/
.vscode/

View File

@ -1,83 +1,5 @@
# Changelog # 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.7] - 2026-09-17
### Fixed
- **createTorrentSum**: Corregido error (`OSError: [Errno 22] Invalid argument`) al calcular la suma de verificación MD5 de los ficheros de imagen cuando estos ocupan menos de 1 MB, ajustando dinámicamente el `seek_offset` al tamaño real del fichero.
## [0.10.6] - 2026-07-27
### Added
- API de Repositorios Git (`repo_api.py`): Implementado el endpoint `DELETE /ogrepository/v1/git/repositories/<repo>` que sustituye al antiguo código "Not implemented". Ahora se encarga de eliminar el repositorio correctamente de la base de datos de Forgejo y de purgar el directorio `.git` del disco duro.
### Changed
- **createTorrentSum**: Optimizada la creación de ficheros torrent (`mktorrent`) calculando el tamaño de pieza (`-l`) de forma dinámica según el tamaño de la imagen, evitando archivos `.torrent` con cientos de miles de piezas que saturaban el tracker en imágenes muy grandes. Se ha incrementado `target_pieces` a 200.000 para garantizar que las piezas no superen los 2 MB en imágenes de hasta 400 GB.
## [0.10.5] - 2026-04-14
### Fixed
- Force 755 permissions on `/opt/opengnsys` in `preinst` to prevent `oggit` user from being locked out when `useradd` creates the directory with a restrictive umask (e.g. 027), which caused `opengnsys-forgejo` to fail to start during installation before `postinst` could apply the correct permissions
- Ensure forgejo working directory (`var/lib/forgejo/work`) is created in `postinst` before setting ownership, and restart `opengnsys-forgejo` after fixing permissions so it recovers from a failed state caused by the ordering between dependency and package configuration
## [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)
### Removed
- Removed unused BitTorrent-related packages and logic
## [0.9.0] - 2025-06-25
### Added
- Changed old tools for tools non dependant of Pyhton2 in repo
- mktorrent to handle creation of torrent files
- aria2c as torrent client for initial seeding
- opentracker as torrent tracker tool
## [0.8.2] - 2025-06-01
### Changed
- Modified sudoersfile to start torrent
## [0.8.1] - 2025-04-01 ## [0.8.1] - 2025-04-01
### Changed ### Changed

View File

@ -49,32 +49,6 @@ pipeline {
} }
} }
stage('Generate Changelog (Nightly)'){
when {
branch 'main'
}
steps {
script {
def devName = params.DEV_NAME ? params.DEV_NAME : env.DEFAULT_DEV_NAME
def devEmail = params.DEV_EMAIL ? params.DEV_EMAIL : env.DEFAULT_DEV_EMAIL
generateDebianChangelog(env.BUILD_DIR, devName, devEmail,"nightly")
}
}
}
stage('Generate Changelog (Devel)') {
when {
branch 'devel'
}
steps {
script {
def devName = params.DEV_NAME ? params.DEV_NAME : env.DEFAULT_DEV_NAME
def devEmail = params.DEV_EMAIL ? params.DEV_EMAIL : env.DEFAULT_DEV_EMAIL
generateDebianChangelog(env.BUILD_DIR, devName, devEmail, "devel")
}
}
}
stage('Build') { stage('Build') {
steps { steps {
script { script {
@ -97,57 +71,17 @@ pipeline {
} }
} }
} }
stage ('Publish to Debian Repository (Nightly)') {
when {
branch 'main'
}
agent { label 'debian-repo' }
steps {
script {
// Construir el patrón de versión esperado en el nombre del paquete
def versionPattern = "-${env.BUILD_NUMBER}~nightly"
publicarEnAptly('/var/tmp/opengnsys/debian-repo/ogrepository', 'nightly', versionPattern)
}
}
}
stage ('Publish to Debian Repository (Devel)') {
when {
branch 'devel'
}
agent { label 'debian-repo' }
steps {
script {
def versionPattern = "-${env.BUILD_NUMBER}~devel"
publicarEnAptly('/var/tmp/opengnsys/debian-repo/ogrepository', 'devel', versionPattern)
}
}
}
} }
post { 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}")
]
}
if (env.BRANCH_NAME == 'devel') {
build job: 'Aptly publish develop repository',
wait: false,
parameters: [
string(name: 'TRIGGERED_BY', value: "${env.JOB_NAME}-${env.BUILD_NUMBER}")
]
}
}
}
always { always {
notifyBuildStatus('opengnsys@qindel.com') notifyBuildStatus('narenas@qindel.com')
} }
} }
} }
// stage ('Publish to Debian Repository') {
// agent { label 'debian-repo' }
// steps {
// sh "aptly repo add opengnsys-devel /var/tmp/opengnsys/debian-repo/*.deb"
// }
// }

File diff suppressed because it is too large Load Diff

View File

@ -18,7 +18,7 @@ tags:
- name: "Transferencia entre Repositorios y Backup" - name: "Transferencia entre Repositorios y Backup"
- name: "Importar y Exportar Máquinas Virtuales" - name: "Importar y Exportar Máquinas Virtuales"
- name: "Varios" - name: "Varios"
- name: "Git"
# ----------------------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------------------------------
# Apartado "Estado de ogRepository" # Apartado "Estado de ogRepository"
@ -1960,721 +1960,3 @@ paths:
example: "(Exception description)" example: "(Exception description)"
# ----------------------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------------------------------
# -----------------------------------------------------------
# ____ _ _
# / ___(_) |_
# | | _| | __|
# | |_| | | |_
# \____|_|\__|
#
# -----------------------------------------------------------
/ogrepository/v1/git/ssh_key:
post:
summary: "Agregar clave de SSH de ogLive"
description: |
Agrega una clave de SSH que va a usarse desde el ogLive
para interactuar con Git.
Es necesario especificar **ssh_key** o **oglive**.
Especificando **ssh_key** se agrega la cclave especificada directamente.
tags:
- "Git"
parameters:
- name: JSON
in: body
required: true
description: |
* **ssh_key** - Clave de SSH (opcional)
* **oglive** - URL a ogLive (opcional, NO USAR DE MOMENTO)
* **description** - Descripcion (opcional)
schema:
type: object
properties:
ssh_key:
type: string
example: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINEOttwhJ+9THRZ1Zv/6QUwPUDq1X7opG9V7EFLVWxQV"
required: False
description:
type: string
example: "OgLive r20250518"
required: False
responses:
"200":
description: "Exito"
schema:
type: object
properties:
success:
type: boolean
example: True
required: True
output:
type: string
example: "SSH key added"
required: True
job_id:
type: string
example: "GitSshKey_873f353f"
required: False
/ogrepository/v1/git/repositories:
get:
summary: "Obtener lista de repositorios"
description: |
Devuelve una lista de repositorios de Git
tags:
- "Git"
responses:
"200":
description: "Lista de repositorios"
schema:
type: object
properties:
repositories:
type: array
items:
type: string
example: linux
"500":
description: "Excepción"
schema:
type: object
properties:
success:
type: boolean
example: false
exception:
type: string
example: "(Exception description)"
post:
summary: "Crear repositorio"
description: |
Crea un repositorio nuevo de Git
tags:
- "Git"
parameters:
- name: JSON
in: body
required: true
description: |
* **name** - Nombre de repositorio
schema:
type: object
properties:
name:
type: string
example: linux
responses:
"201":
description: "Repositorio creado"
schema:
type: object
properties:
status:
type: string
example: "Repository created"
"500 (Exception)":
description: "JSON post data missing"
schema:
type: object
properties:
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"
description: |
Devuelve una lista de tags de Git
tags:
- "Git"
parameters:
- name: repository
in: path
required: true
type: string
description: "Nombre de repositorio"
responses:
"200":
description: "Lista de tags"
schema:
type: object
properties:
tags:
type: array
items:
type: object
properties:
name:
type: string
example: v0.1
commit:
type: string
example: db8e84d5d2548f589ee503c1c6d5003cc6a0d803
committer:
type: string
example: John Smith
committed_datetime:
type: int
example: 1745360193
message:
type: string
example: "Initial release"
required: False
tagged_date:
type: int
example: 1745360194
required: False
tagger:
type: string
example: John Smith
required: False
tagger_tz_offset:
type: int
example: -7200
required: False
"500":
description: "Excepción"
schema:
type: object
properties:
success:
type: boolean
example: false
exception:
type: string
example: "(Exception description)"
post:
summary: "Crear tag"
description: |
Crea una tag de git
tags:
- "Git"
parameters:
- name: repository
in: path
required: true
type: string
description: "Nombre de repositorio"
- name: JSON
in: body
required: true
description: |
* **name** - Nombre del tag
* **commit** - Commit al que apunta el tag nuevo. Puede ser un nombre de otra rama/tag.
* **message** - Mensaje descriptivo para el tag. Opcional, si no se especifica se asume una cadena vacía.
schema:
type: object
properties:
name:
type: string
example: v1.0
required: True
commit:
type: string
example: HEAD
required: True
message:
type: string
example: Version 1.0
required: False
responses:
"201":
description: "Tag creado"
schema:
type: object
properties:
status:
type: string
example: created
"500":
description: "Excepción"
schema:
type: object
properties:
success:
type: boolean
example: false
exception:
type: string
example: "(Exception description)"
"404":
description: "El repositorio no existe"
schema:
type: object
properties:
error:
type: string
example: "Repository not found"
"409":
description: "El tag ya existe"
schema:
type: object
properties:
error:
type: string
example: "Tag already exists"
delete:
summary: "Eliminar tag"
description: |
Elimina un tag de git
tags:
- "Git"
parameters:
- name: repository
in: path
required: true
type: string
description: "Nombre de repositorio"
- name: tag
in: path
required: true
type: string
description: "Rama del repositorio"
responses:
"200":
description: "Tag eliminado"
schema:
type: object
properties:
status:
type: string
example: deleted
"500":
description: "Excepción"
schema:
type: object
properties:
success:
type: boolean
example: false
exception:
type: string
example: "(Exception description)"
/ogrepository/v1/git/repositories/{repository}/branches/{branch}/commits:
get:
summary: "Obtener lista de commits en una rama"
description: |
Devuelve una lista de commits de Git.
**Filtrado de commits:**
Por defecto algunos commits que no son utiles para restaurar una imagen se ocultan.
Pasar filter_commits=0 para desactivar esta funcionalidad y ver todos los commits
del repositorio.
tags:
- "Git"
parameters:
- name: repository
in: path
required: true
type: string
description: "Nombre de repositorio"
- name: branch
in: path
required: true
type: string
description: "Rama dentro del repositorio"
- name: max_commits
in: query
required: false
type: int
description: "Máximo de commits a obtener"
- name: skip
in: query
required: false
type: int
description: "Commits a saltar (para paginación)"
- name: filter_commits
in: query
required: false
type: int
description: "Si aplicar filtrado de commits. Por defecto 1."
responses:
"200":
description: "Lista de commits"
schema:
type: object
properties:
commits:
type: array
items:
type: object
properties:
committed_date:
type: int
example: 1745360193
hexsha:
type: string
example: "db8e84d5d2548f589ee503c1c6d5003cc6a0d803"
message:
type: string
example: "Install updates"
size:
type: int
example: 67108864
tags:
type: array
example: ["updates"]
"500":
description: "Excepción"
schema:
type: object
properties:
success:
type: boolean
example: false
exception:
type: string
example: "(Exception description)"
"404":
description: "El repositorio o branch no existe"
schema:
type: object
properties:
error:
type: string
example: "Repository not found"
/ogrepository/v1/git/repositories/{repository}/branches:
get:
summary: "Obtener lista de branches"
description: |
Devuelve una lista de branches de Git
tags:
- "Git"
parameters:
- name: repository
in: path
required: true
type: string
description: "Nombre de repositorio"
responses:
"200":
description: "Lista de branches"
schema:
type: object
properties:
branches:
type: array
items:
type: string
example: main
"500":
description: "Excepción"
schema:
type: object
properties:
success:
type: boolean
example: false
exception:
type: string
example: "(Exception description)"
"404":
description: "El repositorio no existe"
schema:
type: object
properties:
error:
type: string
example: "Repository not found"
"409":
description: "El branch ya existe"
schema:
type: object
properties:
error:
type: string
example: "Branch already exists"
post:
summary: "Crear branch"
description: |
Crea una rama de git
tags:
- "Git"
parameters:
- name: repository
in: path
required: true
type: string
description: "Nombre de repositorio"
- name: JSON
in: body
required: true
description: |
* **commit** - Commit al que apunta la rama nueva. Puede ser un nombre de otra rama/tag.
schema:
type: object
properties:
name:
type: string
example: devel
required: True
commit:
type: string
example: HEAD
required: True
responses:
"201":
description: "Rama creada"
schema:
type: array
items:
type: string
example: main
"500":
description: "Git no instalado"
schema:
type: object
properties:
success:
type: boolean
example: false
exception:
type: string
example: "(Exception description)"
delete:
summary: "Eliminar branch"
description: |
Elimina una rama de git
tags:
- "Git"
parameters:
- name: repository
in: path
required: true
type: string
description: "Nombre de repositorio"
- name: branch
in: path
required: true
type: string
description: "Branch del repositorio"
responses:
"200":
description: "Branch eliminado"
schema:
type: object
properties:
status:
type: string
example: deleted
"500":
description: "Excepción"
schema:
type: object
properties:
success:
type: boolean
example: false
exception:
type: string
example: "(Exception description)"

View File

@ -96,13 +96,8 @@ def get_md5_sum(file_path, megabytes=1):
Se utiliza para crear el archivo ".sum" (para transferencias Unicast y Multicast). Se utiliza para crear el archivo ".sum" (para transferencias Unicast y Multicast).
""" """
hash_md5 = hashlib.md5() hash_md5 = hashlib.md5()
file_size = os.path.getsize(file_path)
seek_offset = -megabytes * 1024 * 1024
if file_size < (-seek_offset):
seek_offset = -file_size
with open(file_path, "rb") as f: with open(file_path, "rb") as f:
f.seek(seek_offset, os.SEEK_END) f.seek(-megabytes * 1024 * 1024, os.SEEK_END)
data = f.read(megabytes * 1024 * 1024) data = f.read(megabytes * 1024 * 1024)
hash_md5.update(data) hash_md5.update(data)
return hash_md5.hexdigest() return hash_md5.hexdigest()
@ -139,18 +134,8 @@ def create_torrent(file_path, torrent_file, datafullsum):
repo_ip = get_IPlocal() repo_ip = get_IPlocal()
tracker_url = f"http://{repo_ip}:6969/announce" tracker_url = f"http://{repo_ip}:6969/announce"
import math # Creamos una lista con el comando para crear el torrrent, y lo imprimimos con espacios:
file_size = os.path.getsize(file_path) splitted_cmd = f"nice -n 0 ctorrent -t {file_path} -u {tracker_url} -s {torrent_file} -c {datafullsum} -l 4194304".split()
target_pieces = 200000
piece_size_target = file_size / target_pieces
if piece_size_target <= 262144:
l_val = 18
else:
l_val = math.ceil(math.log(piece_size_target, 2))
l_val = max(18, min(26, l_val))
# Creamos una litas para ejecutar el comando mktorrent para crear el archivo torrent
splitted_cmd = f"nice -n 0 mktorrent -l {l_val} -a {tracker_url} -c {datafullsum} -o {torrent_file} {file_path}".split()
print(f"Sending command: {' '.join(splitted_cmd)}") print(f"Sending command: {' '.join(splitted_cmd)}")
# Ejecutamos el comando en el sistema, e imprimimos el resultado: # Ejecutamos el comando en el sistema, e imprimimos el resultado:
@ -199,17 +184,12 @@ def main():
# Obtenemos la ruta completa de la imagen: # Obtenemos la ruta completa de la imagen:
file_path = build_file_path() file_path = build_file_path()
# Si no existe el archivo de imagen o el .info, imprimimos un mensaje de error y salimos del script: # Si no existe el archivo de imagen, 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):
if not os.path.exists(file_path): journal.send("createTorrentSum.py: Image not found", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
journal.send(f"createTorrentSum.py: Image file '{file_path}' not found", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") print("Image file doesn't exist")
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) sys.exit(2)
# Si la imagen está bloqueada, imprimimos un mensaje de error y salimos del script: # Si la imagen está bloqueada, imprimimos un mensaje de error y salimos del script:
if os.path.exists(f"{file_path}.lock"): if os.path.exists(f"{file_path}.lock"):
journal.send("createTorrentSum.py: Image is locked", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") journal.send("createTorrentSum.py: Image is locked", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
@ -277,8 +257,7 @@ def main():
# Actualizamos la información del repositorio, ejecutando el script "updateRepoInfo.py": # 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") journal.send("createTorrentSum.py: Updating repository info...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
print("Updating Repository Info...") print("Updating Repository Info...")
if os.path.exists(f"{file_path}.info"): update_repo_info()
update_repo_info()

View File

@ -106,11 +106,11 @@ def main():
total_disk, used_disk, free_disk, percent_disk = get_disk_info() total_disk, used_disk, free_disk, percent_disk = get_disk_info()
# Obtenemos el estado de los servicios listados, que almacenamos en un diccionario: # Obtenemos el estado de los servicios listados, que almacenamos en un diccionario:
service_list = ['ssh', 'smbd', 'opentracker'] service_list = ['ssh', 'smbd', 'rsync']
services_status = {service: get_service_status(service) for service in service_list} services_status = {service: get_service_status(service) for service in service_list}
# Obtenemos el estado de los procesos listados, que almacenamos en un diccionario: # Obtenemos el estado de los procesos listados, que almacenamos en un diccionario:
process_list = ['udp-sender', 'uftp', 'aria2c'] process_list = ['udp-sender', 'uftp', 'bttrack', 'btlaunchmany.bittornado']
process_status = {process: get_process_status(process) for process in process_list} process_status = {process: get_process_status(process) for process in process_list}
# Creamos un diccionario con toda la información obtenida: # Creamos un diccionario con toda la información obtenida:

View File

@ -16,8 +16,6 @@ No recibe ningún parámetro.
import os import os
import sys import sys
import subprocess import subprocess
import psutil
import re
from systemd import journal from systemd import journal
@ -33,73 +31,29 @@ repo_path = '/opt/opengnsys/ogrepository/images' # En este caso, no lleva barra
# -------------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------------
def run_bittornado(repo_path):
""" Ejecuta el comando "btlaunchmany.bittornado", con sus parámetros correspondientes.
Además, captura el resultado y los posibles errores, y los imprime.
"""
# Creamos una lista con el comando "btlaunchmany.bittornado" y sus parámetros, y lo imprimimos con espacios:
splitted_cmd = f"btlaunchmany.bittornado {repo_path}".split()
print(f"Sending command: {' '.join(splitted_cmd)}")
journal.send(f"runTorrentSeeder.py: Running command: {' '.join(splitted_cmd)}", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
# def run_bittornado(repo_path): # Ejecutamos el comando "btlaunchmany.bittornado" en el sistema, e imprimimos el resultado:
# """ Ejecuta el comando "btlaunchmany.bittornado", con sus parámetros correspondientes.
# Además, captura el resultado y los posibles errores, y los imprime.
# """
# # Creamos una lista con el comando "btlaunchmany.bittornado" y sus parámetros, y lo imprimimos con espacios:
# splitted_cmd = f"btlaunchmany.bittornado {repo_path}".split()
# print(f"Sending command: {' '.join(splitted_cmd)}")
# journal.send(f"runTorrentSeeder.py: Running command: {' '.join(splitted_cmd)}", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
# # Ejecutamos el comando "btlaunchmany.bittornado" en el sistema, e imprimimos el resultado:
# try:
# result = subprocess.run(splitted_cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# journal.send(f"runTorrentSeeder.py: Command ReturnCode: {result.returncode}", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
# print(f"Bittornado ReturnCode: {result.returncode}")
# except subprocess.CalledProcessError as error:
# journal.send("runTorrentSeeder.py: Process finalized", PRIORITY=journal.LOG_WARNING, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
# print(f"Bittornado ReturnCode: {error.returncode}")
# print(f"Bittornado Error Output: {error.stderr.decode()}")
# except Exception as error:
# journal.send(f"runTorrentSeeder.py: Command exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
# print(f"Unexpected bittornado error: {error}")
def run_aria2c_seeder(image_name):
"""Lanza aria2c como seeder puro para una imagen concreta ya existente."""
repo_path = '/opt/opengnsys/ogrepository/images'
torrent_file = os.path.join(repo_path, f"{image_name}.img.torrent")
image_file = os.path.join(repo_path, f"{image_name}.img")
# Verificación básica
if not os.path.exists(torrent_file):
print(f"Torrent file not found: {torrent_file}")
journal.send(f"Seeder error: Torrent file not found: {torrent_file}",
PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api")
return
if not os.path.exists(image_file):
print(f"Image file not found: {image_file}")
journal.send(f"Seeder error: Image file not found: {image_file}",
PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api")
return
# Comando aria2c como seeder puro
cmd = [
'aria2c',
'--enable-peer-exchange=true',
'--bt-seed-unverified=true',
'--check-integrity=true',
'--seed-ratio=0.0',
'--dir=' + repo_path,
torrent_file
]
journal.send(f"Launching aria2c seeder for {image_name}",
PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api")
journal.send(f"Command: {' '.join(cmd)}",
PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api")
print("Running command:", ' '.join(cmd))
try: try:
subprocess.run(cmd, check=True) result = subprocess.run(splitted_cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except subprocess.CalledProcessError as e: journal.send(f"runTorrentSeeder.py: Command ReturnCode: {result.returncode}", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
journal.send(f"aria2c seeder failed: {e}", print(f"Bittornado ReturnCode: {result.returncode}")
PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api") except subprocess.CalledProcessError as error:
print(f"Seeder process exited with code {e.returncode}") journal.send("runTorrentSeeder.py: Process finalized", PRIORITY=journal.LOG_WARNING, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
print(f"Bittornado ReturnCode: {error.returncode}")
print(f"Bittornado Error Output: {error.stderr.decode()}")
except Exception as error:
journal.send(f"runTorrentSeeder.py: Command exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
print(f"Unexpected bittornado error: {error}")
# -------------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------------
# MAIN # MAIN
@ -110,40 +64,16 @@ def main():
""" """
""" """
# Finalizamos el proceso "btlaunchmany.bittornado" (en caso de que estuviera corriendo): # Finalizamos el proceso "btlaunchmany.bittornado" (en caso de que estuviera corriendo):
if len(sys.argv) != 2: try:
print("Usage: runTorrentSeeder.py <image_name>") journal.send("runTorrentSeeder.py: Killing process 'btlaunchmany.bittornado'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
journal.send("runTorrentSeeder.py: Invalid number of arguments. Expected 1 argument: <image_name>", subprocess.run(f"pkill btlaunchmany".split(), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") except Exception as error_description:
sys.exit(1) journal.send("runTorrentSeeder.py: No 'btlaunchmany.bittornado' process running", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
print(f"No btlaunchmany.bittornado process running? Returned error: {error_description}")
image_name = sys.argv[1] # Ejecutamos el comando "btlaunchmany.bittornado" (para hacer seed de los torrents):
torrent_file = os.path.join(repo_path, f"{image_name}.img.torrent") run_bittornado(repo_path)
found = False
# Matamos los procesos de aria2c que sirvan la imagen en concreto. Chequeamos todos los procesos
journal.send(f"runTorrentSeeder.py: looking for aria2c processes for {image_name}.torrent",
PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
for proc in psutil.process_iter(['pid','name','cmdline']):
try:
if proc.info['name'] != 'aria2c':
continue
if any(arg.endswith(torrent_file) for arg in proc.info['cmdline']):
proc.terminate()
found = True
print(f"Killed aria2c process with PID {proc.info['pid']} for {image_name}.torrent")
journal.send(f"runTorrentSeeder.py: Killed aria2c process with PID {proc.info['pid']} for {image_name}.torrent",
PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
except (psutil.NoSuchProcess, psutil.AccessDenied):
continue
if not found:
print(f"No aria2c process found for {image_name}.torrent")
journal.send(f"runTorrentSeeder.py: No aria2c process found for {image_name}.torrent",
PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
# Lanzamos aria2c como seeder para la imagen proporcionada
run_aria2c_seeder(image_name)
# -------------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------------

View File

@ -67,50 +67,33 @@ def check_files():
continue continue
# Comprobamos si existe un archivo ".info" asociado a la imagen actual: # Comprobamos si existe un archivo ".info" asociado a la imagen actual:
info_file = f"{img_path}.info" info_file = f"{img_path}.info"
try: if os.path.exists(info_file):
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):
# 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):
if os.path.getmtime(info_file) < os.path.getmtime(img_path): os.remove(info_file)
os.remove(info_file) print(f"Warning: Deleted outdated file {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": # En caso contrario, almacenamos el contenido del archivo ".info" (del tipo "PARTCLONE:LZOP:EXTFS:8500000:Ubuntu_20") en la variable "data":
else: else:
with open(info_file, 'r') as file: with open(info_file, 'r') as file:
info_data = file.read() info_data = file.read()
# Almacenamos el contenido de los archivos ".size", ".sum" y ".full.sum": # Almacenamos el contenido de los archivos ".size", ".sum" y ".full.sum":
with open(f"{img_path}.size", 'r') as file: with open(f"{img_path}.size", 'r') as file:
size = file.read().strip('\n') size = file.read().strip('\n')
with open(f"{img_path}.sum", 'r') as file: with open(f"{img_path}.sum", 'r') as file:
sum = file.read().strip('\n') _sum = file.read().strip('\n')
with open(f"{img_path}.full.sum", 'r') as file: with open(f"{img_path}.full.sum", 'r') as file:
fullsum = file.read().strip('\n') 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)
# Renombramos el archivo ".info" a ".info.checked", para que ya no se añada la información que contiene # 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): # (originalmente se eliminaba el archivo, pero creo que es mejor mantenerlo):
os.rename(info_file, f"{info_file}.checked") 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)
except (IOError, OSError, PermissionError) as e: def add_to_json(image_name, image_type, data, size, _sum, fullsum):
# 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). """ 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: # Almacenamos el contenido de la variable "data" (del tipo "PARTCLONE:LZOP:EXTFS:8500000:Ubuntu_20") en variables separadas:
@ -126,7 +109,7 @@ def add_to_json(image_name, image_type, data, size, sum, fullsum):
"filesystem": fstype.upper(), "filesystem": fstype.upper(),
"datasize": int(datasize) * 1024, # Convertimos el valor a bytes (desde KB) "datasize": int(datasize) * 1024, # Convertimos el valor a bytes (desde KB)
"size": int(size), "size": int(size),
"sum": sum, "sum": _sum,
"fullsum": fullsum "fullsum": fullsum
} }
# Almacenamos el contenido del archivo "repoinfo.json" en la variable "info_data" # Almacenamos el contenido del archivo "repoinfo.json" en la variable "info_data"

40
debian/changelog vendored
View File

@ -1,43 +1,3 @@
ogrepository (1.1.5) UNRELEASED; urgency=medium
* refs #2363 Fix breaking forgejo permissions
-- OpenGnsys <opengnsys@opengnsys.com> Tue, 1 Jul 2025 16:05:12 +0000
ogrepository (1.1.4) UNRELEASED; urgency=medium
* refs #2363 Reduce number of required dependencies
-- OpenGnsys <opengnsys@opengnsys.com> Tue, 30 Jun 2025 15:50:11 +0000
ogrepository (1.1.3) UNRELEASED; urgency=medium
* refs #2317 Fix performance problems, remove stats
* refs #2298 Add commmits endpoint
-- OpenGnsys <opengnsys@opengnsys.com> Tue, 30 Jun 2025 15:50:11 +0000
ogrepository (1.1.2) UNRELEASED; urgency=medium
* Fix path handling when there are no repositories
* Add another search path for installer module
* Fix path handling
* Add SSH key endpoint
* Update dependencies
-- OpenGnsys <opengnsys@opengnsys.com> Tue, 30 Jun 2025 15:20:23 +0000
ogrepository (1.1.1) unstable; urgency=medium
* OgGit - fix repo path handling
-- Tu Nombre <tuemail@example.com> Jue, 5 Jun 2025 08:43:58 +0000
ogrepository (1.1.0) unstable; urgency=medium
* OgGit
-- Tu Nombre <tuemail@example.com> Tue, 11 Mar 2025 04:43:58 +0000
ogrepository (1.0.0+deb-packages20250311-1) unstable; urgency=medium ogrepository (1.0.0+deb-packages20250311-1) unstable; urgency=medium
* First debian version * First debian version

5
debian/control vendored
View File

@ -8,7 +8,6 @@ Build-Depends: debhelper-compat (= 12)
Package: ogrepository Package: ogrepository
Architecture: all Architecture: all
Pre-Depends: debian-archive-keyring , debconf (>= 1.5.0), Pre-Depends: debian-archive-keyring , debconf (>= 1.5.0),
Depends: ${misc:Depends}, git, python3, python3-pip, python3-flask, python3-paramiko, python3-psutil, python3-flasgger, samba, gunicorn, wakeonlan , lzop , partclone , qemu-utils , udpcast, uftp, mktorrent, aria2 , opengnsys-opentracker, opengnsys-forgejo, python3-git Depends: ${misc:Depends}, git, python3, python3-pip, python3-flask, python3-paramiko, python3-psutil, python3-flasgger, samba, gunicorn, wakeonlan , lzop , partclone , qemu-utils , udpcast, uftp
Description: Ogrepsoitory Package Description: Ogrepsoitory Package
This package provides Ogrepository service. This package provides Ogrepsoitory service.

View File

@ -1,6 +1,7 @@
api/* /opt/opengnsys/ogrepository/api/ api/* /opt/opengnsys/ogrepository/api/
bin/* /opt/opengnsys/ogrepository/bin/ bin/* /opt/opengnsys/ogrepository/bin/
etc/* /opt/opengnsys/ogrepository/etc/ etc/* /opt/opengnsys/ogrepository/etc/
installer/files/ctorrent.sources /etc/apt/sources.list.d/
installer/files/ogrepo-api.service /etc/systemd/system/ installer/files/ogrepo-api.service /etc/systemd/system/
installer/files/ogrepo-smb.conf /etc/samba/ installer/files/ogrepo-smb.conf /etc/samba/
installer/ssh-keys/* /opt/opengnsys/ogrepository/etc/ installer/ssh-keys/* /opt/opengnsys/ogrepository/etc/

View File

@ -5,25 +5,6 @@ set -x
. /usr/share/debconf/confmodule . /usr/share/debconf/confmodule
restore_config_if_modified() {
local new="$1"
local backup="$1.bak.upgrade_package"
if [ -f "$backup" ]; then
if ! cmp -s "$new" "$backup"; then
echo ">>> Archivo modificado por el usuario detectado en $new"
echo " - Guardando archivo nuevo como ${new}.new"
mv -f "$new" "${new}.new"
echo " - Restaurando archivo anterior desde backup"
mv -f "$backup" "$new"
else
echo ">>> El archivo $new no ha cambiado desde la última versión, eliminando backup"
rm -f "$backup"
fi
fi
}
# Cargar variables de configuración # Cargar variables de configuración
db_get opengnsys/ogrepository_ogrepoIp db_get opengnsys/ogrepository_ogrepoIp
OGREPO_IP="$RET" OGREPO_IP="$RET"
@ -40,7 +21,18 @@ USER="opengnsys"
# Provisionar base de datos si es necesario en caso de instalación. # Provisionar base de datos si es necesario en caso de instalación.
# Detectar si es una instalación nueva o una actualización
if [ "$1" = "configure" ] && [ -z "$2" ]; then if [ "$1" = "configure" ] && [ -z "$2" ]; then
systemd-run --no-block /bin/bash -c "
sleep 10;
apt update -y;
for pkg in bittorrent bittornado ctorrent; do
if ! dpkg -l | grep -qw \"\$pkg\"; then
apt install -y \"\$pkg\"
fi
done
"
sed -i "s/%%OGREPOSITORY_USER%%/$SAMBA_USER/g" /etc/systemd/system/ogrepo-api.service 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 sed -i "s/%%OGREPOSITORY_USER%%/$SAMBA_USER/g" /etc/samba/ogrepo-smb.conf
@ -70,7 +62,7 @@ if [ "$1" = "configure" ] && [ -z "$2" ]; then
fi fi
(echo "$SAMBA_PASS"; echo "$SAMBA_PASS") | smbpasswd -a $SAMBA_USER (echo "$SAMBA_PASS"; echo "$SAMBA_PASS") | smbpasswd -a $SAMBA_USER
fi fi
systemctl enable ogrepo-api
# Configure Repo # Configure Repo
cp /opt/opengnsys/ogrepository/etc/ogAdmRepo.cfg.tmpl /opt/opengnsys/ogrepository/etc/ogAdmRepo.cfg cp /opt/opengnsys/ogrepository/etc/ogAdmRepo.cfg.tmpl /opt/opengnsys/ogrepository/etc/ogAdmRepo.cfg
@ -91,45 +83,12 @@ elif [ "$1" = "configure" ] && [ -n "$2" ]; then
cp /opt/opengnsys/ogrepository/etc/opengnsys.pub $OPENGNSYS_HOME/.ssh/id_ed25519.pub cp /opt/opengnsys/ogrepository/etc/opengnsys.pub $OPENGNSYS_HOME/.ssh/id_ed25519.pub
cat $OPENGNSYS_HOME/.ssh/id_ed25519.pub >> $OPENGNSYS_HOME/.ssh/authorized_keys cat $OPENGNSYS_HOME/.ssh/id_ed25519.pub >> $OPENGNSYS_HOME/.ssh/authorized_keys
restore_config_if_modified "/opt/opengnsys/ogrepository/etc/ogAdmRepo.cfg"
restore_config_if_modified "/opt/opengnsys/ogrepository/etc/repoinfo.json"
restore_config_if_modified "/opt/opengnsys/ogrepository/etc/trashinfo.json"
restore_config_if_modified "/etc/samba/smb.conf"
restore_config_if_modified "/etc/samba/ogrepo-smb.conf"
restore_config_if_modified "/etc/sudoers.d/opengnsys-repository"
fi fi
# Cambiar la propiedad de los archivos al usuario especificado # Cambiar la propiedad de los archivos al usuario especificado
chown opengnsys:www-data /opt/opengnsys/ chown opengnsys:www-data /opt/opengnsys/
chown -R opengnsys:www-data /opt/opengnsys/ogrepository chown -R opengnsys:www-data /opt/opengnsys/ogrepository
chmod 755 /opt/opengnsys chmod 755 /opt/opengnsys/ogrepository/bin/
chmod 755 /opt/opengnsys/ogrepository/bin/*
# oggit -- these are from opengnsys-forgejo, and we're overwriting their
# permissions above.
#
# Ensure the forgejo working directory exists and has the right ownership
# before the service tries to start. This is needed because opengnsys-forgejo
# is configured (and starts its service) before ogrepository's postinst runs,
# so without this the service fails with CHDIR/Permission denied.
if getent passwd oggit > /dev/null 2>&1; then
mkdir -p /opt/opengnsys/ogrepository/var/lib/forgejo/work
mkdir -p /opt/opengnsys/ogrepository/var/lib/forgejo/data
chown -R oggit:oggit /opt/opengnsys/ogrepository/var/lib/forgejo/
fi
if [ -d "/opt/opengnsys/ogrepository/oggit/" ] ; then
chown -R oggit:oggit /opt/opengnsys/ogrepository/oggit/
fi
# Restart forgejo now that permissions are correct (it may have failed during
# opengnsys-forgejo's own postinst due to the chown above overwriting its dirs)
if getent passwd oggit > /dev/null 2>&1; then
systemctl reset-failed opengnsys-forgejo 2>/dev/null || true
systemctl restart opengnsys-forgejo 2>/dev/null || true
fi
# Install http server stuff # Install http server stuff
# Reiniciar servicios si es necesario # Reiniciar servicios si es necesario
@ -139,8 +98,39 @@ systemctl daemon-reload
systemctl enable ogrepo-api systemctl enable ogrepo-api
systemctl restart ogrepo-api systemctl restart ogrepo-api
systemctl restart smbd systemctl restart smbd
systemctl enable --now opentracker || true
systemctl restart opentracker || true
# echo "ogrepository-trigger" > /var/lib/dpkg/triggers/ogrepository.trigger
# POST_INVOKE_SCRIPT="/var/lib/dpkg/info/ogrepository.trigger"
# echo "Registrando post-invoke para instalación de paquetes adicionales..."
# cat <<EOF > "$POST_INVOKE_SCRIPT"
# #!/bin/sh
# set -e
# echo "Ejecutando post-trigger: Instalando bittorrent, bittornado y ctorrent..."
# export DEBIAN_FRONTEND=noninteractive
# apt-get update
# apt-get install -y bittorrent bittornado ctorrent
# echo "Instalación de paquetes adicionales completada."
# exit 0
# EOF
# chmod +x "$POST_INVOKE_SCRIPT"
# # Intentar ejecutar el script ahora si no hay otro proceso de apt corriendo
# if ! pgrep -x "apt" > /dev/null; then
# echo "Ejecutando instalación de paquetes adicionales inmediatamente..."
# "$POST_INVOKE_SCRIPT"
# else
# echo "Apt está en uso, los paquetes se instalarán después."
# fi
# find /opt/opengnsys/ogrepository -type f -name "*.py" -exec chmod +x {} \;
# dpkg-trigger --by-package=ogrepository ogrepository-trigger
exit 0 exit 0

View File

@ -2,18 +2,8 @@
set -e set -e
backup_file_if_exists() { KEY_FILE="/usr/share/keyrings/debian-archive-buster-stable.gpg"
local original="$1" REPO_FILE="/etc/apt/sources.list.d/buster.list"
local backup="$1.bak.upgrade_package"
if [ -e "$original" ]; then
echo " - Guardando backup de $original en $backup"
cp -a "$original" "$backup"
fi
}
# KEY_FILE="/usr/share/keyrings/debian-archive-buster-stable.gpg"
# REPO_FILE="/etc/apt/sources.list.d/buster.list"
# Asegurarse de que el usuario exista # Asegurarse de que el usuario exista
USER="opengnsys" USER="opengnsys"
@ -24,30 +14,16 @@ else
echo "Creando el usuario $USER con home en $HOME_DIR." echo "Creando el usuario $USER con home en $HOME_DIR."
useradd -m -d "$HOME_DIR" -s /bin/bash "$USER" useradd -m -d "$HOME_DIR" -s /bin/bash "$USER"
fi fi
# Forzar 755 en /opt/opengnsys independientemente del umask del sistema.
# useradd -m puede crear el directorio con 750 si el umask es 027, lo que
# impide que el usuario oggit (de opengnsys-forgejo) atraviese el árbol
# antes de que el postinst de ogrepository aplique su propio chmod.
mkdir -p "$HOME_DIR"
chmod 755 "$HOME_DIR"
echo "Añadiendo el repositorio de Debian Buster en $REPO_FILE..." echo "Añadiendo el repositorio de Debian Buster en $REPO_FILE..."
# Crear el directorio si no existe # Crear el directorio si no existe
mkdir -p "$(dirname "$REPO_FILE")" mkdir -p "$(dirname "$REPO_FILE")"
# Crear el archivo de repositorio si no existe # Crear el archivo de repositorio si no existe
# if [ ! -f "$REPO_FILE" ]; then if [ ! -f "$REPO_FILE" ]; then
# echo "deb [signed-by=$KEY_FILE] http://ftp.de.debian.org/debian buster main" > "$REPO_FILE" echo "deb [signed-by=$KEY_FILE] http://ftp.de.debian.org/debian buster main" > "$REPO_FILE"
# else else
# echo "El repositorio ya está configurado en $REPO_FILE" echo "El repositorio ya está configurado en $REPO_FILE"
# fi fi
backup_file_if_exists "/opt/opengnsys/ogrepository/etc/ogAdmRepo.cfg"
backup_file_if_exists "/opt/opengnsys/ogrepository/etc/repoinfo.json"
backup_file_if_exists "/opt/opengnsys/ogrepository/etc/trashinfo.json"
backup_file_if_exists "/etc/samba/smb.conf"
backup_file_if_exists "/etc/samba/ogrepo-smb.conf"
backup_file_if_exists "/etc/sudoers.d/ogrepository"
exit 0 exit 0

View File

@ -10,25 +10,6 @@ Cmnd_Alias MOUNT_RECOVERY = \
/usr/bin/umount /mnt/recovery/sys, \ /usr/bin/umount /mnt/recovery/sys, \
/usr/bin/umount -l /mnt/recovery /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 = \ Cmnd_Alias CHROOT_GRUB = \
/usr/sbin/chroot /mnt/recovery /usr/sbin/grub-install --target=i386-pc *, \ /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 /usr/sbin/chroot /mnt/recovery /usr/sbin/grub-mkconfig -o /boot/grub/grub.cfg
@ -44,7 +25,5 @@ Cmnd_Alias KILL_BT = \
/usr/bin/pkill -9 bttrack, \ /usr/bin/pkill -9 bttrack, \
/usr/bin/kill -9 * /usr/bin/kill -9 *
Cmnd_Alias PYTHON_OGREPO = /usr/bin/python3 /opt/opengnsys/ogrepository/bin/*
# Permitir al usuario opengnsys ejecutar estos comandos sin contraseña # Permitir al usuario opengnsys ejecutar estos comandos sin contraseña
opengnsys ALL=(root) NOPASSWD: MOUNT_RECOVERY, CHROOT_GRUB, LOOP_KPARTX, OGBOOT, KILL_BT, PYTHON_OGREPO opengnsys ALL=(root) NOPASSWD: MOUNT_RECOVERY, CHROOT_GRUB, LOOP_KPARTX, KILL_BT

View File

@ -0,0 +1,6 @@
Types: deb
URIs: http://ftp.de.debian.org/debian
Suites: buster
Components: main
Signed-By: /usr/share/keyrings/debian-archive-buster-stable.gpg