-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
188 lines (149 loc) · 5.96 KB
/
app.py
File metadata and controls
188 lines (149 loc) · 5.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
import subprocess
import logging
import os
import sys
import yaml
from flask import Flask
from flask_cors import CORS
from app_core.config.logging import setup_logging
from app_core.presentation.api import api_bp
# ===== Configurar logging =====
log_file = "app.log"
logger = setup_logging(log_file)
class StreamToLogger(object):
def __init__(self, logger, level):
self.logger = logger
self.level = level
def write(self, message):
if message.rstrip() != "":
self.logger.log(self.level, message.rstrip())
def flush(self):
pass
logging.basicConfig(level=logging.INFO)
sys.stdout = StreamToLogger(logger, logging.INFO)
sys.stderr = StreamToLogger(logger, logging.ERROR)
# === Generar y cargar credenciales OpenStack ===
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
GEN_SCRIPT = os.path.join(BASE_DIR, "generate_app_cred_openrc_from_clouds.sh")
OPENRC_PATH = os.path.join(BASE_DIR, "admin-openrc.sh")
KOLLA_CLOUDS = "/etc/kolla/clouds.yaml"
DEFAULT_CLOUD = "kolla-admin"
def load_clouds_creds(clouds_path: str, cloud_name: str) -> dict:
"""Lee /etc/kolla/clouds.yaml y devuelve las credenciales del cloud elegido."""
with open(clouds_path, "r") as f:
data = yaml.safe_load(f) or {}
clouds = data.get("clouds") or {}
cloud_cfg = clouds.get(cloud_name)
if not cloud_cfg:
raise ValueError(f"No se encontró el cloud '{cloud_name}' en {clouds_path}")
auth = cloud_cfg.get("auth") or {}
return {
"OS_AUTH_URL": auth.get("auth_url"),
"OS_USERNAME": auth.get("username"),
"OS_PASSWORD": auth.get("password"),
"OS_PROJECT_NAME": auth.get("project_name", "admin"),
"OS_PROJECT_DOMAIN_NAME": auth.get("project_domain_name", "Default"),
"OS_USER_DOMAIN_NAME": auth.get("user_domain_name", "Default"),
"OS_REGION_NAME": cloud_cfg.get("region_name", "RegionOne"),
"OS_INTERFACE": cloud_cfg.get("interface", "public"),
}
def write_openrc(creds: dict, output_path: str):
"""Escribe un admin-openrc.sh a partir de credenciales ya leídas."""
content = [
"#!/bin/bash",
"# Archivo generado automáticamente desde /etc/kolla/clouds.yaml",
"",
"unset OS_AUTH_TYPE",
"unset OS_AUTH_URL",
"unset OS_USERNAME",
"unset OS_PASSWORD",
"unset OS_USER_DOMAIN_NAME",
"unset OS_PROJECT_NAME",
"unset OS_PROJECT_DOMAIN_NAME",
"unset OS_REGION_NAME",
"unset OS_APPLICATION_CREDENTIAL_ID",
"unset OS_APPLICATION_CREDENTIAL_SECRET",
"unset OS_APPLICATION_CREDENTIAL_NAME",
"",
]
for key, value in creds.items():
if value:
content.append(f"export {key}={value}")
content.append('echo "Credenciales OpenStack cargadas"')
with open(output_path, "w") as f:
f.write("\n".join(content) + "\n")
os.chmod(output_path, 0o755)
logger.info(f" admin-openrc.sh generado en {output_path}")
def ensure_openrc() -> bool:
"""
Asegura que exista admin-openrc.sh.
1) Si ya existe, no lo toca.
2) Intenta generarlo en Python desde /etc/kolla/clouds.yaml (sin tmp/ni apt).
3) Como último recurso, llama al script legacy si existe.
"""
if os.path.exists(OPENRC_PATH):
logger.info(f" admin-openrc.sh ya existe en {OPENRC_PATH}, se reutiliza.")
return True
try:
if os.path.exists(KOLLA_CLOUDS):
creds = load_clouds_creds(KOLLA_CLOUDS, DEFAULT_CLOUD)
write_openrc(creds, OPENRC_PATH)
return True
else:
logger.warning(f" No se encontró {KOLLA_CLOUDS}. Se probará el script legacy.")
except Exception as e:
logger.warning(f" Falló la generación Python de admin-openrc.sh: {e}")
try:
if os.path.exists(GEN_SCRIPT):
logger.info(f" Ejecutando script legacy de credenciales: {GEN_SCRIPT}")
if not os.access(GEN_SCRIPT, os.X_OK):
os.chmod(GEN_SCRIPT, 0o755)
logger.info(f" Permisos de ejecución otorgados a {GEN_SCRIPT}")
proc = subprocess.run(
["bash", GEN_SCRIPT],
cwd=BASE_DIR,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
check=False
)
logger.info(" Salida del script:")
logger.info(proc.stdout)
if proc.stderr:
logger.warning(" Errores durante la ejecución del script:")
logger.warning(proc.stderr)
if proc.returncode == 0 and os.path.exists(OPENRC_PATH):
logger.info(f" Script ejecutado correctamente. Archivo generado: {OPENRC_PATH}")
return True
else:
logger.warning(f" No se generó correctamente {OPENRC_PATH}. Código de salida: {proc.returncode}")
else:
logger.warning(f" Script {GEN_SCRIPT} no encontrado. Se omite la generación automática.")
except Exception as e:
logger.error(f" Error al ejecutar el script {GEN_SCRIPT}: {e}", exc_info=True)
return False
ensure_openrc()
if os.path.exists(OPENRC_PATH):
try:
with open(OPENRC_PATH) as f:
for line in f:
line = line.strip()
if line.startswith("export "):
key, value = line.replace("export ", "").split("=", 1)
os.environ[key] = value
logger.info(f" Credenciales OpenStack cargadas desde {OPENRC_PATH}")
except Exception as e:
logger.error(f" Error al cargar {OPENRC_PATH}: {e}")
else:
logger.warning(f" Archivo {OPENRC_PATH} no encontrado. Los comandos OpenStack pueden fallar.")
def create_app():
"""
Factory mínima que registra el blueprint API.
"""
flask_app = Flask(__name__)
CORS(flask_app)
flask_app.register_blueprint(api_bp)
return flask_app
app = create_app()
if __name__ == "__main__":
app.run(host="localhost", port=5001, debug=True)