Ajustar al manual del M1000e, añadir diagramas y docs de operación
Especificaciones tomadas del manual del propietario del gabinete PowerEdge M1000e (Dell, modelo BMX01, rev. A06, oct. 2019), que corrige el spec sheet comercial usado hasta ahora. Hardware: - Peso máximo 200,5 kg, no 179. Profundidad 75,5 cm - Seis fuentes y nueve ventiladores obligatorios, se usen 3 blades o 16. Toda bahía vacía necesita relleno - Conector CEI/IEC C20 a 16 A. La fuente de 3.000 W exige 200-240 V - Irrupción de 55 A por fuente durante 10 ms: un magnetotérmico de curva C salta, hace falta curva D - Temperatura de funcionamiento continuo 10-35 °C - ECM obligatorio con blades M630 de 120 W o más, o por encima de 30 °C Red: - Fabric A (ranuras A1/A2) es la Ethernet integrada de cada blade, así que no hacen falta tarjetas intermedias. Fabrics B y C sí las exigirían y no se usan - Pendiente saber si en A1/A2 hay un switch o un módulo de paso a través: cambia el montaje de red por completo Costes recalculados: el suelo fijo del chasis sube de 350 a ~500 W al contar los nueve ventiladores, los módulos de I/O y las pérdidas de las seis fuentes. 360 €/mes a 24/7, 59 €/mes por ventanas. Que las fuentes y los ventiladores sean obligatorios convierte en hecho documentado lo que antes era estimación: los pilotos parciales en el chasis son el peor caso posible. Documentación: - assets/ con cuatro diagramas SVG propios: arquitectura, chasis, stack de software y modos de red - docs/usabilidad.md: órdenes, flujos de trabajo, problemas conocidos y ergonomía del hardware - Diagramas ASCII del panel frontal, el posterior y la topología de fabrics en hardware_m1000e.md - Eliminada la parte de charla y divulgación, fuera del alcance del repo
This commit is contained in:
parent
74bfbe9437
commit
7caa240c2e
17 changed files with 1012 additions and 423 deletions
|
|
@ -1,30 +1,22 @@
|
||||||
# La capa de identidad: verificación, reputación de IP y atestación
|
# La capa de identidad: verificación, reputación de IP y atestación
|
||||||
|
|
||||||
El documento central del proyecto. Explica **por qué la identidad, y no el cómputo, es el único
|
Por qué la identidad, y no el cómputo, es el cuello de botella de una granja, y cómo se integran
|
||||||
cuello de botella real** de una granja — y cómo las tres capas que la componen se integran entre
|
las capas que la componen.
|
||||||
sí para derrotarla.
|
|
||||||
|
|
||||||
> **Alcance.** Esto describe cómo funcionan los mecanismos y por qué las granjas pierden contra
|
Alcance: esto describe cómo funcionan los mecanismos y por qué las granjas pierden contra ellos.
|
||||||
> ellos. No es un manual operativo de alta masiva de cuentas: no hay proveedores de SIM, ni
|
No es un manual operativo de alta masiva de cuentas — no hay proveedores de SIM, ni técnicas de
|
||||||
> técnicas de evasión de fingerprint, ni calendarios de maduración. Esa parte es fraude de
|
evasión de fingerprint, ni calendarios de maduración. Esa parte es fraude de identidad a escala y
|
||||||
> identidad a escala y está bajo persecución activa en la UE — ver [legal_ue.md](legal_ue.md).
|
está bajo persecución activa en la UE; ver [legal_ue.md](legal_ue.md).
|
||||||
> Lo que sigue sirve para investigar, para defender y para dar la charla; para lo otro, no.
|
|
||||||
|
|
||||||
---
|
Una plataforma no pregunta quién eres. Comprueba tres cosas —si controlas un número, desde dónde
|
||||||
|
llegas y qué dispositivo eres— y luego una cuarta: en qué te pareces a las otras cuentas. Las tres
|
||||||
## 0 · La tesis en una frase
|
primeras se atacan con dinero. La cuarta no, y es la que hunde el negocio.
|
||||||
|
|
||||||
Una plataforma no te pregunta *quién eres*. Te pregunta tres cosas a la vez —
|
|
||||||
**¿controlas un número?**, **¿desde dónde llegas?**, **¿qué dispositivo eres?** — y luego,
|
|
||||||
la que de verdad mata: **¿en qué te pareces a los otros 44?**
|
|
||||||
|
|
||||||
Las tres primeras se pueden atacar con dinero. La cuarta no, y es la que hunde el negocio.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 1 · Verificación telefónica
|
## 1 · Verificación telefónica
|
||||||
|
|
||||||
### Qué se está comprobando de verdad
|
### Qué se comprueba
|
||||||
|
|
||||||
El OTP por SMS no verifica tu identidad. Verifica que **controlas un número en el momento del
|
El OTP por SMS no verifica tu identidad. Verifica que **controlas un número en el momento del
|
||||||
alta**. Es una prueba de posesión, no de identidad. Pero detrás del número hay una cadena que sí
|
alta**. Es una prueba de posesión, no de identidad. Pero detrás del número hay una cadena que sí
|
||||||
|
|
@ -49,8 +41,8 @@ evitable. Eso es lo que se revende como *número como servicio*.
|
||||||
|
|
||||||
### La eSIM: por qué NO es la respuesta
|
### La eSIM: por qué NO es la respuesta
|
||||||
|
|
||||||
Es la pregunta que más se repite y la respuesta es contraintuitiva. **La eSIM es peor para una
|
La eSIM es peor para una granja que la SIM física. Para ver por qué hay que mirar el
|
||||||
granja que la SIM física**, y hay que entender el aprovisionamiento para ver por qué.
|
aprovisionamiento.
|
||||||
|
|
||||||
Una eSIM no es un fichero que se copia. Es un **perfil** que se descarga a un chip concreto:
|
Una eSIM no es un fichero que se copia. Es un **perfil** que se descarga a un chip concreto:
|
||||||
|
|
||||||
|
|
@ -76,7 +68,7 @@ Tres consecuencias que lo descartan:
|
||||||
Resumen: la eSIM cambia un consumible anónimo y barato por un identificador de hardware trazable
|
Resumen: la eSIM cambia un consumible anónimo y barato por un identificador de hardware trazable
|
||||||
con contrato detrás. **Por eso el mercado sigue con plástico** — no por inercia, por diseño.
|
con contrato detrás. **Por eso el mercado sigue con plástico** — no por inercia, por diseño.
|
||||||
|
|
||||||
### Y aquí está el problema de fondo para un rack
|
### El problema para un rack
|
||||||
|
|
||||||
Un contenedor redroid **no tiene banda base**. No hay módem, no hay IMEI legítimo, no puede
|
Un contenedor redroid **no tiene banda base**. No hay módem, no hay IMEI legítimo, no puede
|
||||||
recibir un SMS. Nunca. Así que el número y el dispositivo están **necesariamente desacoplados**:
|
recibir un SMS. Nunca. Así que el número y el dispositivo están **necesariamente desacoplados**:
|
||||||
|
|
@ -99,7 +91,7 @@ el dinero de comprarlas deja rastro. Detalle en [legal_ue.md](legal_ue.md).
|
||||||
|
|
||||||
## 2 · Reputación de IP
|
## 2 · Reputación de IP
|
||||||
|
|
||||||
La segunda pregunta: *¿desde dónde llegas?*
|
La segunda pregunta: desde dónde llegas.
|
||||||
|
|
||||||
### Las tres clases de dirección
|
### Las tres clases de dirección
|
||||||
|
|
||||||
|
|
@ -125,14 +117,12 @@ bloqueo por daño colateral**.
|
||||||
|
|
||||||
### De dónde salen los proxies residenciales
|
### De dónde salen los proxies residenciales
|
||||||
|
|
||||||
Aquí está la parte turbia del sector, y es material de charla. La mayoría del inventario
|
La mayoría del inventario residencial no viene de servidores: viene de SDKs embebidos en apps y
|
||||||
residencial no viene de servidores: viene de **SDKs embebidos en apps gratuitas y VPNs
|
VPNs gratuitas, que convierten el móvil del usuario en nodo de salida a cambio de que la app sea
|
||||||
"gratuitas"**, que convierten el móvil del usuario en un nodo de salida a cambio de que la app sea
|
|
||||||
gratis. El consentimiento suele estar enterrado en unos términos que nadie lee.
|
gratis. El consentimiento suele estar enterrado en unos términos que nadie lee.
|
||||||
|
|
||||||
Es decir: cuando alguien compra tráfico residencial, muy probablemente está saliendo por la
|
Cuando alguien compra tráfico residencial, muy probablemente está saliendo por la conexión de una
|
||||||
conexión de una persona que no lo sabe. Eso ha generado litigios y es uno de los ángulos
|
persona que no lo sabe. Eso ha generado litigios.
|
||||||
periodísticos más fértiles del tema.
|
|
||||||
|
|
||||||
### Qué mira la plataforma, más allá de la clase
|
### Qué mira la plataforma, más allá de la clase
|
||||||
|
|
||||||
|
|
@ -148,13 +138,13 @@ MaxMind, IPQualityScore, Spur, IPinfo — que vende exactamente esto:
|
||||||
- **Huella de transporte**: JA3/JA4 (el fingerprint del handshake TLS), orden de cabeceras HTTP,
|
- **Huella de transporte**: JA3/JA4 (el fingerprint del handshake TLS), orden de cabeceras HTTP,
|
||||||
versión de la librería de red. Identifica al cliente por debajo de la aplicación
|
versión de la librería de red. Identifica al cliente por debajo de la aplicación
|
||||||
|
|
||||||
Ese último punto es el que sorprende: **no hace falta mirar la app para saber que no es la app.**
|
Con eso último no hace falta mirar la app para saber que no es la app.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3 · Atestación de dispositivo
|
## 3 · Atestación de dispositivo
|
||||||
|
|
||||||
La tercera pregunta: *¿qué dispositivo eres?* Y es donde la partida se decidió del todo.
|
La tercera pregunta: qué dispositivo eres. Es donde se decidió la partida.
|
||||||
|
|
||||||
### De SafetyNet a Play Integrity
|
### De SafetyNet a Play Integrity
|
||||||
|
|
||||||
|
|
@ -170,7 +160,7 @@ y la sustituyó por la **Play Integrity API**, que devuelve tres veredictos esca
|
||||||
|
|
||||||
### Qué significa "respaldada por hardware"
|
### Qué significa "respaldada por hardware"
|
||||||
|
|
||||||
Aquí está la clave técnica del proyecto entero, y merece entenderla bien.
|
Es la clave técnica del proyecto entero.
|
||||||
|
|
||||||
Un Android certificado sale de fábrica con una **clave privada de atestación grabada en su elemento
|
Un Android certificado sale de fábrica con una **clave privada de atestación grabada en su elemento
|
||||||
seguro** — el TEE, o StrongBox si hay chip dedicado. Esa clave nunca sale del hardware. Cuando la
|
seguro** — el TEE, o StrongBox si hay chip dedicado. Esa clave nunca sale del hardware. Cuando la
|
||||||
|
|
@ -192,7 +182,7 @@ real, sin sensor de luz que varíe.
|
||||||
|
|
||||||
### Por qué esto ya no es una carrera armamentística
|
### Por qué esto ya no es una carrera armamentística
|
||||||
|
|
||||||
Este es el punto que hay que subrayar, porque cambia la naturaleza del problema:
|
Esto cambia la naturaleza del problema:
|
||||||
|
|
||||||
> La detección de emulador dejó de ser **estadística** y pasó a ser **criptográfica**.
|
> La detección de emulador dejó de ser **estadística** y pasó a ser **criptográfica**.
|
||||||
|
|
||||||
|
|
@ -201,10 +191,8 @@ esquivar. Ahora es verificar una firma contra una raíz de confianza. **O tienes
|
||||||
tienes.** No hay evasión posible, solo robo de claves de dispositivos reales, que es otro delito y
|
tienes.** No hay evasión posible, solo robo de claves de dispositivos reales, que es otro delito y
|
||||||
otro mercado.
|
otro mercado.
|
||||||
|
|
||||||
Y ahí está la explicación de la pregunta que abrió toda esta investigación: **por qué GenFarmer te
|
Explica también por qué GenFarmer vende cajas con teléfonos físicos de 400 $ en vez de software
|
||||||
vende cajas con teléfonos físicos de 400 $ en vez de venderte software para tu servidor.** No es
|
para tu servidor: lo que venden no es cómputo, es el único sitio donde vive la clave.
|
||||||
que no sepan hacer software. Es que lo que venden no es cómputo, es **el único sitio donde vive la
|
|
||||||
clave**.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -230,7 +218,7 @@ Las aristas que unen el grafo:
|
||||||
- **Temporal**: cohortes de registro. 45 cuentas dadas de alta el mismo martes por la tarde ya son
|
- **Temporal**: cohortes de registro. 45 cuentas dadas de alta el mismo martes por la tarde ya son
|
||||||
un grupo, aunque todo lo demás esté impecable
|
un grupo, aunque todo lo demás esté impecable
|
||||||
|
|
||||||
### La trampa matemática
|
### El problema de escala
|
||||||
|
|
||||||
Fabricar **una** cuenta indistinguible de la de una persona real es caro pero factible.
|
Fabricar **una** cuenta indistinguible de la de una persona real es caro pero factible.
|
||||||
|
|
||||||
|
|
@ -252,23 +240,15 @@ proxies de los móviles de terceros. Que es exactamente **lo que persiguen y por
|
||||||
|
|
||||||
## 5 · Qué significa para este proyecto
|
## 5 · Qué significa para este proyecto
|
||||||
|
|
||||||
Sin rodeos, y es la conclusión que ordena todo el repositorio:
|
El rack no sirve para las plataformas sociales, y no por falta de potencia: no tiene la clave.
|
||||||
|
|
||||||
**El rack no sirve para las plataformas sociales, y no por falta de potencia.** No tiene la clave.
|
|
||||||
Ninguna cantidad de blades, RAM o ancho de banda produce una clave de atestación grabada en
|
Ninguna cantidad de blades, RAM o ancho de banda produce una clave de atestación grabada en
|
||||||
fábrica. La detección no es un umbral que se pueda esquivar, es una firma que no se puede
|
fábrica. La detección no es un umbral que se pueda esquivar, es una firma que no se puede
|
||||||
falsificar.
|
falsificar.
|
||||||
|
|
||||||
**El rack sí sirve, y muy bien, como laboratorio de QA propio.** Probar `oasis_mobile` en una
|
Sí sirve como laboratorio de QA propio. Probar `oasis_mobile` en una matriz de versiones de
|
||||||
matriz de versiones de Android, y el escenario multi-dispositivo de los dos APKs que se tienen que
|
Android, y el escenario multi-dispositivo de los dos APKs que se tienen que ver entre sí, es
|
||||||
ver entre sí, es exactamente para lo que 45 Android en red interna son inmejorables. Ahí no hay
|
exactamente para lo que 45 Android en red interna son buenos. Ahí no hay atestación que superar:
|
||||||
ninguna atestación que superar: es tu app en tus dispositivos.
|
es tu app en tus dispositivos.
|
||||||
|
|
||||||
**Y para la charla, esto es la tesis.** Ver [../03_charla/](../03_charla/):
|
|
||||||
|
|
||||||
> La granja de bots perdió la guerra técnica el día que la atestación pasó de estadística a
|
|
||||||
> criptográfica. Lo que queda no es un problema de cómputo, es un problema de identidad — y quien
|
|
||||||
> controla las SIMs controla el mercado. Por eso ahí es exactamente donde pega la policía.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
versiones nuevas de Android.
|
versiones nuevas de Android.
|
||||||
- Encima: **Appium/UIAutomator2** para conducir, **scrcpy** para ver, **ADB sobre TCP** para todo.
|
- Encima: **Appium/UIAutomator2** para conducir, **scrcpy** para ver, **ADB sobre TCP** para todo.
|
||||||
|
|
||||||
## El jarro de agua fría
|
## Lo que un rack no resuelve
|
||||||
|
|
||||||
Ese rack **no sirve** para el caso TikTok/Instagram, y esa es exactamente la razón por la que
|
Ese rack **no sirve** para el caso TikTok/Instagram, y esa es exactamente la razón por la que
|
||||||
GenFarmer vende cajas con teléfonos físicos de $400 en vez de vender software para tu servidor.
|
GenFarmer vende cajas con teléfonos físicos de $400 en vez de vender software para tu servidor.
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ kernel de una máquina Debian.
|
||||||
|
|
||||||
| | Para qué |
|
| | Para qué |
|
||||||
|---|---|
|
|---|---|
|
||||||
| **[ansible/](ansible/)** | **La granja de verdad**: los 16 blades del M1000e, provisionados y controlados desde un sitio. Es lo que hay que usar. |
|
| [ansible/](ansible/) | Los 16 blades del M1000e, provisionados y controlados desde un sitio. Es la vía principal. |
|
||||||
| Este documento | Un solo nodo, a mano. Sirve para entender las piezas y para trastear en el sobremesa. |
|
| Este documento | Un solo nodo, a mano. Sirve para entender las piezas y para trastear en el sobremesa. |
|
||||||
|
|
||||||
El hardware está descrito en [hardware_m1000e.md](hardware_m1000e.md).
|
El hardware está descrito en [hardware_m1000e.md](hardware_m1000e.md).
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@ del blade. Es la única forma sensata de hacer esto con el hardware que hay.
|
||||||
|
|
||||||
## La arquitectura
|
## La arquitectura
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
```
|
```
|
||||||
Dell PowerEdge M1000e — 16 blades
|
Dell PowerEdge M1000e — 16 blades
|
||||||
│
|
│
|
||||||
|
|
@ -45,6 +47,13 @@ sudo apt install ansible
|
||||||
- Salida a internet, o un mirror local de `download.docker.com` y `deb.debian.org`
|
- Salida a internet, o un mirror local de `download.docker.com` y `deb.debian.org`
|
||||||
- Kernel con `binder_linux.ko` (el estándar de Debian lo trae)
|
- Kernel con `binder_linux.ko` (el estándar de Debian lo trae)
|
||||||
|
|
||||||
|
**Chasis** — un módulo de I/O en **A1** como mínimo. La Fabric A es la Ethernet integrada (LOM) de
|
||||||
|
cada blade, así que **no hacen falta tarjetas intermedias**; las Fabrics B y C sí las exigirían y
|
||||||
|
no se usan aquí. Si en A1/A2 hay un módulo **switch**, la conmutación entre blades es interna al
|
||||||
|
chasis, que es lo que necesita `macvlan`. Si hay un módulo de **paso a través**, salen 16 RJ-45 al
|
||||||
|
exterior y la conmutación depende de un switch externo. Ver
|
||||||
|
[hardware_m1000e.md](../hardware_m1000e.md).
|
||||||
|
|
||||||
**Ejecuta siempre desde este directorio** (`ansible/`) — `ansible.cfg` y las rutas de roles son
|
**Ejecuta siempre desde este directorio** (`ansible/`) — `ansible.cfg` y las rutas de roles son
|
||||||
relativas a él.
|
relativas a él.
|
||||||
|
|
||||||
|
|
@ -121,6 +130,8 @@ Se controla con `redroid_network_mode` en `group_vars/all.yml`.
|
||||||
Cada Android detrás de NAT de Docker; adb en `<ip_blade>:<puerto>`, empezando en 5555.
|
Cada Android detrás de NAT de Docker; adb en `<ip_blade>:<puerto>`, empezando en 5555.
|
||||||
Funciona en cualquier sitio sin saber nada de la LAN. Es el modo con el que empezar.
|
Funciona en cualquier sitio sin saber nada de la LAN. Es el modo con el que empezar.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
### `macvlan` — el que quieres para `oasis_mobile`
|
### `macvlan` — el que quieres para `oasis_mobile`
|
||||||
|
|
||||||
Cada Android coge una **IP real de la LAN** a través del switch FlexIO del chasis. Los dos APKs
|
Cada Android coge una **IP real de la LAN** a través del switch FlexIO del chasis. Los dos APKs
|
||||||
|
|
|
||||||
|
|
@ -1,61 +1,235 @@
|
||||||
# El hardware: Dell PowerEdge M1000e
|
# El hardware: Dell PowerEdge M1000e
|
||||||
|
|
||||||
Identificado el 2026-08-08. Fuente: `~/Downloads/poweredge-m1000e-spec-sheet.pdf`
|
> **Fuente**: *Gabinete Dell PowerEdge M1000e — Manual del propietario*, modelo reglamentario
|
||||||
(spec sheet oficial Dell EMC, 6 de diciembre de 2016).
|
> **BMX01**, rev. A06, octubre 2019 (© 2014-2019 Dell Inc.), más el spec sheet de dic. 2016.
|
||||||
|
> Los datos de esta página vienen del manual oficial y **sustituyen a las estimaciones previas**.
|
||||||
|
|
||||||
No es un servidor suelto: es un **chasis de blades**. Cada blade es una máquina independiente
|
No es un servidor suelto: es un **chasis de blades**. Cada blade es una máquina independiente con
|
||||||
con su CPU y su RAM.
|
su CPU y su RAM. Los ventiladores, las fuentes, la CMC y los módulos de I/O son **recursos
|
||||||
|
compartidos** de todos los blades.
|
||||||
|
|
||||||
## Especificaciones del chasis
|
---
|
||||||
|
|
||||||
|
## Panel frontal — los blades
|
||||||
|
|
||||||
|
```
|
||||||
|
┌──────────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ │
|
||||||
|
│ ┌────┐┌────┐┌────┐┌────┐┌────┐┌────┐┌────┐┌────┐ ┌───────┐ │
|
||||||
|
│ │ 1 ││ 2 ││ 3 ││ 4 ││ 5 ││ 6 ││ 7 ││ 8 │ │ LCD │ │
|
||||||
|
│ │ ││ ││ ││ ││ ││ ││ ││ │ │ panel │ │
|
||||||
|
│ └────┘└────┘└────┘└────┘└────┘└────┘└────┘└────┘ │ ctrl │ │
|
||||||
|
│ ┌────┐┌────┐┌────┐┌────┐┌────┐┌────┐┌────┐┌────┐ │ │ │
|
||||||
|
│ │ 9 ││ 10 ││ 11 ││ 12 ││ 13 ││ 14 ││ 15 ││ 16 │ │ 2×USB │ │
|
||||||
|
│ │ ││ ││ ││ ││ ││ ││ ││ │ │ VGA │ │
|
||||||
|
│ └────┘└────┘└────┘└────┘└────┘└────┘└────┘└────┘ └───────┘ │
|
||||||
|
│ │
|
||||||
|
└──────────────────────────────────────────────────────────────────────────┘
|
||||||
|
16 blades de media altura — 8 arriba y 8 abajo
|
||||||
|
```
|
||||||
|
|
||||||
|
El chasis admite **16 blades de media altura**, u 8 de altura completa, u 8 fundas de cuarto de
|
||||||
|
altura, o una combinación.
|
||||||
|
|
||||||
|
> **Todos los compartimentos deben ir ocupados en todo momento**, con un blade o con un módulo de
|
||||||
|
> relleno. No es una recomendación estética: sin relleno, el aire se escapa por el hueco y la
|
||||||
|
> refrigeración del resto se degrada.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Panel posterior — la infraestructura compartida
|
||||||
|
|
||||||
|
```
|
||||||
|
┌──────────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ ┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐ │
|
||||||
|
│ │ V ││ V ││ V ││ V ││ V ││ V ││ V ││ V ││ V │ 9 módulos de ventilador │
|
||||||
|
│ └───┘└───┘└───┘└───┘└───┘└───┘└───┘└───┘└───┘ (los 9, obligatorios) │
|
||||||
|
│ │
|
||||||
|
│ ┌──────────────┐ ┌─────────┐ ┌──────────────┐ │
|
||||||
|
│ │ A1 B1 C1 │ │ CMC 1 │ │ C2 B2 A2 │ 6 módulos de I/O │
|
||||||
|
│ │ │ │ iKVM │ │ │ + 2 CMC │
|
||||||
|
│ │ (izquierda) │ │ CMC 2 │ │ (derecha) │ + iKVM opcional │
|
||||||
|
│ └──────────────┘ └─────────┘ └──────────────┘ │
|
||||||
|
│ │
|
||||||
|
│ ┌────┐┌────┐┌────┐┌────┐┌────┐┌────┐ │
|
||||||
|
│ │PSU ││PSU ││PSU ││PSU ││PSU ││PSU │ 6 fuentes de alimentación │
|
||||||
|
│ └────┘└────┘└────┘└────┘└────┘└────┘ (las 6, obligatorias) │
|
||||||
|
└──────────────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
Dos exigencias del manual que cambian el planteamiento del proyecto:
|
||||||
|
|
||||||
|
> **«El sistema requiere seis fuentes de alimentación para su funcionamiento habitual.»**
|
||||||
|
|
||||||
|
> **«Los nueve módulos de ventilador deben instalarse en todo momento para garantizar un
|
||||||
|
> enfriamiento adecuado.»**
|
||||||
|
|
||||||
|
No se puede arrancar este chasis a medias. Seis fuentes, nueve ventiladores y todas las bahías
|
||||||
|
tapadas, se usen 3 blades o 16. Es el motivo técnico de por qué **los pilotos parciales en el
|
||||||
|
chasis son mal negocio** — ver [../docs/costes.md](../docs/costes.md).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Fabrics: cómo se conecta un blade a la red
|
||||||
|
|
||||||
|
Esta es la parte del manual que más afecta al diseño del laboratorio. El M1000e tiene **tres
|
||||||
|
fabrics redundantes**, y no todas sirven para lo mismo:
|
||||||
|
|
||||||
|
```
|
||||||
|
blade-NN FABRICS exterior
|
||||||
|
┌──────────────┐
|
||||||
|
│ │ ┌──────────────────┐
|
||||||
|
│ LOM NIC1 ──┼───────────►│ A1 (switch) │──────────────► LAN
|
||||||
|
│ (integrado) │ ├──────────────────┤ (uplink)
|
||||||
|
│ NIC2 ──┼───────────►│ A2 (switch) │──────────────► LAN
|
||||||
|
│ │ └──────────────────┘ (redundante)
|
||||||
|
│ │ FABRIC A — Ethernet
|
||||||
|
│ │
|
||||||
|
│ mezz B ─────┼───────────► B1 / B2 1–40 Gb/s: FC, InfiniBand, 10 GbE
|
||||||
|
│ mezz C ─────┼───────────► C1 / C2 1–40 Gb/s: ídem
|
||||||
|
└──────────────┘ requieren tarjeta intermedia en el blade
|
||||||
|
```
|
||||||
|
|
||||||
|
**Para este proyecto solo importa la Fabric A**, y es una buena noticia:
|
||||||
|
|
||||||
|
- Fabric A es la **Ethernet integrada de cada blade** (la LOM). No hace falta comprar ni instalar
|
||||||
|
tarjetas intermedias.
|
||||||
|
- Soporta KR (10 Gbps estándar).
|
||||||
|
- Sus ranuras son **A1 y A2**. Con un módulo en A1 basta para arrancar; A1 + A2 da redundancia.
|
||||||
|
- Las Fabrics B y C **necesitan tarjeta intermedia en cada blade**. Si el chasis no las trae, no se
|
||||||
|
usan — y para 45 Android por adb no hacen ninguna falta.
|
||||||
|
|
||||||
|
**Lo que hay que verificar en el chasis real**: qué módulo hay en A1/A2. Un módulo de switch
|
||||||
|
(PowerConnect M6220 / M6348, Force10 MXL, M8024-k…) da conmutación interna entre blades, que es
|
||||||
|
justo lo que necesita el modo `macvlan`. Un **módulo de paso a través** en cambio saca 16 puertos
|
||||||
|
RJ-45 al exterior, uno por blade, y entonces la conmutación depende de un switch externo.
|
||||||
|
|
||||||
|
> Los módulos pensados para Fabric B o C **no entran físicamente** en A1/A2 — el manual dice que
|
||||||
|
> están codificados por color en la placa frontal para evitarlo.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Especificaciones oficiales
|
||||||
|
|
||||||
|
### Físicas
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Factor de forma | Modular 10U — 44,0 alto × 44,7 ancho × 75,4 cm fondo |
|
| Altura | 44,0 cm (17,3") — **10U** |
|
||||||
| Capacidad | **16 blades de media altura** (8 arriba + 8 abajo) · u 8 de altura completa · o 32 de cuarto |
|
| Anchura | 44,7 cm (17,6") |
|
||||||
| Alimentación | Hasta 6 fuentes de 3.000 W / 2.700 W (config 3+3, 2+2, 2+1…) |
|
| Profundidad | 75,5 cm (29,7") |
|
||||||
| Refrigeración | 9 módulos de ventiladores redundantes |
|
| **Peso máximo** | **200,5 kg** (442 lb) |
|
||||||
| Gestión | CMC (Chassis Management Controller) + iDRAC por blade; web SSL, SSH/Telnet, LDAP/AD |
|
| Peso vacío | 44,6 kg (98,1 lb) |
|
||||||
| Red interna | Hasta 6 módulos I/O FlexIO — los blades se ven entre sí a 1/10 GbE |
|
|
||||||
| Peso | 44 kg vacío · 179 kg cargado |
|
> El peso máximo corregido son **200,5 kg**, no los 179 kg del spec sheet comercial. El manual
|
||||||
|
> manda: el rack y el suelo tienen que ir sobrados.
|
||||||
|
|
||||||
|
### Alimentación
|
||||||
|
|
||||||
|
| | Fuente de 2.700 W | Fuente de 3.000 W |
|
||||||
|
|---|---|---|
|
||||||
|
| Conector | **CEI/IEC C20** | IEC 320 |
|
||||||
|
| Tensión de entrada | 100–240 V CA, **16 A** | **200–240 V CA**, 16 A |
|
||||||
|
| Frecuencia | 50/60 Hz | 50/60 Hz |
|
||||||
|
| Disipación propia | 353 W (1.205 BTU/h) máx. | 1.200 BTU/h máx. |
|
||||||
|
| **Corriente de irrupción** | **55 A durante ≤10 ms, por fuente** | ídem |
|
||||||
|
|
||||||
|
Tres consecuencias prácticas:
|
||||||
|
|
||||||
|
1. **La fuente de 3.000 W exige 200–240 V.** España a 230 V vale; una instalación a 110 V no.
|
||||||
|
2. **Seis entradas C19/C20.** Hace falta una PDU adecuada — los C13 domésticos no valen.
|
||||||
|
3. **La corriente de irrupción es el detalle que se olvida**: 55 A por fuente durante 10 ms. Con
|
||||||
|
seis fuentes arrancando a la vez, un magnetotérmico de curva C salta. Hace falta **curva D**, o
|
||||||
|
arranque escalonado de las fuentes.
|
||||||
|
|
||||||
|
### Ambientales — el requisito que muerde en verano
|
||||||
|
|
||||||
|
| | |
|
||||||
|
|---|---|
|
||||||
|
| **Funcionamiento continuo** | **10 °C a 35 °C**, humedad relativa 10–80 % |
|
||||||
|
| Ampliado, <10 % de las horas anuales | 5 °C a 40 °C |
|
||||||
|
| Ampliado, <1 % de las horas anuales | −5 °C a 45 °C |
|
||||||
|
| Almacenamiento | −40 °C a 65 °C |
|
||||||
|
| Derating por altitud | −1 °C cada 300 m por encima de 900 m |
|
||||||
|
|
||||||
|
**35 °C es el techo continuo.** Una habitación en Madrid en agosto, con 2,6 kW de calor dentro y
|
||||||
|
sin climatización, se pone por encima de eso sin dificultad. El rango ampliado cubre menos del
|
||||||
|
10 % de las horas del año: no es una solución, es un margen para incidencias.
|
||||||
|
|
||||||
|
### Modo de refrigeración mejorado (ECM)
|
||||||
|
|
||||||
|
La CMC permite activar **ECM**, que exige los nueve ventiladores de tercera generación. El manual
|
||||||
|
lo declara **obligatorio** en tres casos:
|
||||||
|
|
||||||
|
- Blades **M630 con procesadores de 120 W o más**
|
||||||
|
- Blades **M630 en entornos por encima de 30 °C**
|
||||||
|
- Cualquier configuración con aire fresco
|
||||||
|
|
||||||
|
ECM significa más caudal, y por tanto **más consumo y más ruido**. Si los blades resultan ser M630
|
||||||
|
y el sitio pasa de 30 °C, hay que contarlo.
|
||||||
|
|
||||||
|
### Gestión — CMC
|
||||||
|
|
||||||
|
| | |
|
||||||
|
|---|---|
|
||||||
|
| Módulos | CMC 1 (principal) + CMC 2 (secundaria, a prueba de fallos) |
|
||||||
|
| Puertos | Dos RJ-45 10/100/1000: **Gb** a la red de gestión, **STK** para encadenar chasis contiguos |
|
||||||
|
| Serie | 9 patas DTE, compatible 16550 |
|
||||||
|
| Vídeo | VGA 15 patas |
|
||||||
|
| Batería | CR2032 |
|
||||||
|
| Interfaces | Web (SSL), **RACADM** por CLI, SSH/Telnet |
|
||||||
|
|
||||||
|
La CMC **reasigna energía entre módulos según la demanda** y expone presupuesto de alimentación y
|
||||||
|
política de redundancia en *Chassis → Power Management → Configuración*. Es también donde se lee el
|
||||||
|
**consumo real**, que es lo que sustituye a las estimaciones de [../docs/costes.md](../docs/costes.md).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Configuración de esta máquina
|
## Configuración de esta máquina
|
||||||
|
|
||||||
Según lo que recuerda el usuario:
|
| | |
|
||||||
|
|---|---|
|
||||||
|
| Blades | 16, 8 arriba y 8 abajo |
|
||||||
|
| RAM por blade | 8 GB → 128 GB totales, **repartidos, no agrupados** |
|
||||||
|
| Modelo de blade | **desconocido** — M610 / M620 / M630. Lo resuelve `preflight.yml` leyendo DMI |
|
||||||
|
| Módulo en A1/A2 | **desconocido** — switch o paso a través. Determina si `macvlan` funciona sin switch externo |
|
||||||
|
| Estado del CMC | **desconocido** |
|
||||||
|
|
||||||
- **16 blades**, 8 arriba y 8 abajo
|
El manual menciona explícitamente compatibilidad con **M610x**, **M630** y **M710HD**, así que el
|
||||||
- **8 GB de RAM por blade** → 128 GB totales, pero **repartidos, no agrupados**
|
abanico de blades posibles es amplio y la generación no se puede inferir del chasis.
|
||||||
- Modelo de blade: **desconocido** (M610 / M620 / M630 — pendiente de confirmar en el frontal)
|
|
||||||
- Estado / ubicación / accesibilidad de red: **pendiente**
|
---
|
||||||
|
|
||||||
## Qué implica para el device lab
|
## Qué implica para el device lab
|
||||||
|
|
||||||
### A favor
|
### A favor
|
||||||
|
|
||||||
- 16 máquinas independientes con **red interna de chasis**. Mejor topología que un solo host para
|
- 16 máquinas independientes con **conmutación interna por Fabric A**, sin comprar tarjetas
|
||||||
el escenario de `oasis_mobile` con **dos APKs que se tienen que ver entre sí**: el switch FlexIO
|
intermedias. Es la topología ideal para el escenario de `oasis_mobile` con **dos APKs que se
|
||||||
los pone en la misma L2 sin montar nada.
|
tienen que ver entre sí**: quedan en la misma L2 sin montar nada.
|
||||||
- Con 8 GB por blade menos Debian + Docker (~1–1,5 GB), salen **~3 instancias redroid por blade**
|
- Con 8 GB por blade menos Debian y Docker, **~3 instancias redroid por blade → ~45 en total**.
|
||||||
→ **~48 instancias totales**. Casi el triple que el sobremesa (12–20).
|
|
||||||
|
|
||||||
### En contra
|
### En contra
|
||||||
|
|
||||||
- **Consumo: 1,5–2,5 kW en marcha.** A precio doméstico en España, del orden de **160–350 €/mes**
|
- **Seis fuentes y nueve ventiladores obligatorios**, se usen 3 blades o 16. El coste fijo no baja
|
||||||
si está 24/7. Este es el factor que decide la viabilidad, no los cores.
|
al usar menos.
|
||||||
- **Ruido**: no es máquina de casa. Necesita sala con extracción.
|
- **Consumo 2,6–3,6 kW**, del orden de 360 €/mes a 24/7.
|
||||||
- **Sin GPU** en los blades → `redroid_gpu_mode=guest` (render por software). Vale para test
|
- **Techo térmico de 35 °C** continuos.
|
||||||
funcional, no para nada gráfico.
|
- **Sin GPU** en los blades → `redroid_gpu_mode=guest`, render por software.
|
||||||
- **16 provisiones separadas**: cada blade necesita su Debian + Docker + módulo binder. A partir de
|
- **16 provisiones separadas** — de ahí el Ansible.
|
||||||
4-5 blades esto pide Ansible o netboot, no hacerlo a mano.
|
|
||||||
|
|
||||||
### La palanca real
|
### La palanca sigue siendo la misma
|
||||||
|
|
||||||
El cuello de botella son **los 8 GB por blade, no la CPU**. Si los blades son M620 (DDR3 ECC),
|
El cuello de botella son **los 8 GB por blade, no la CPU**. Ampliar a 32 GB sube de ~3 a
|
||||||
ampliar a 32 GB por blade cuesta poco en segunda mano y sube de ~3 a **~14 instancias por blade**.
|
~14 instancias por blade: de 45 a 210 Android por el mismo recibo de la luz.
|
||||||
Eso multiplica por 4-5 la capacidad del proyecto entero por menos de lo que cuesta un mes de luz.
|
|
||||||
|
---
|
||||||
|
|
||||||
## Pendiente de averiguar
|
## Pendiente de averiguar
|
||||||
|
|
||||||
- [ ] **Modelo de blade** (serigrafiado en el frontal) → determina CPU, generación y tipo de RAM
|
- [ ] **Modelo de blade** → `ansible-playbook playbooks/preflight.yml`
|
||||||
- [ ] ¿Está encendido y accesible el CMC en red? Si responde, da el inventario completo
|
- [ ] **Qué módulo hay en A1/A2** (switch o paso a través) → determina si `macvlan` necesita switch externo
|
||||||
- [ ] Ubicación física y quién asume el coste eléctrico
|
- [ ] ¿Están las 6 fuentes y los 9 ventiladores? ¿Y los rellenos en las bahías vacías?
|
||||||
- [ ] Con eso: decidir si se levantan los 16 blades o solo 2-3 como piloto
|
- [ ] ¿Responde el CMC? Da inventario completo y **consumo real**
|
||||||
|
- [ ] ¿Hay ventiladores de 3.ª generación, por si hace falta ECM?
|
||||||
|
- [ ] Ubicación: potencia, PDU con 6 tomas C19, magnetotérmico de curva D y temperatura bajo 35 °C
|
||||||
|
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
# Charla: la economía de las granjas de bots
|
|
||||||
|
|
||||||
Vía 2. Ángulo defensivo/periodístico, no operativo. Hay demanda real de esto y encaja con
|
|
||||||
HackMadrid, los hacklabs y **Hackmeeting València (9–12 oct 2026)**.
|
|
||||||
|
|
||||||
## Tesis
|
|
||||||
|
|
||||||
La granja de bots perdió la guerra técnica y la ganó la económica. La detección de emulador es
|
|
||||||
determinista desde 2025 (Play Integrity con atestación por hardware), así que el negocio se vio
|
|
||||||
forzado a volver al hardware físico, caro y lento. Lo que queda no es un problema de cómputo sino
|
|
||||||
de identidad: **quien controla las SIMs controla el mercado** — y por eso ahí es donde pega la
|
|
||||||
policía.
|
|
||||||
|
|
||||||
## Guion propuesto
|
|
||||||
|
|
||||||
1. **Las tres cosas que llamamos "phone farm"** — reward farming / device lab / account farming.
|
|
||||||
Desmontar la confusión de entrada.
|
|
||||||
2. **El catálogo real** — GenFarmer y PhoneFarmBox como material de clase: qué venden, a qué
|
|
||||||
precio, qué revela su marketing (Zalo, Telegram-only, "300+ dispositivos").
|
|
||||||
3. **Por qué no puedes hacerlo con un servidor** — atestación por hardware, sensores, baseband.
|
|
||||||
El momento en que el cómputo dejó de ser el cuello de botella.
|
|
||||||
4. **La capa SIM** — el eslabón débil, con KYC en origen y rastro de dinero.
|
|
||||||
5. **SIMCARTEL** — 1.200 SIM-boxes, 40.000 SIMs, 49 millones de cuentas falsas, 7 detenidos.
|
|
||||||
El caso que cierra el argumento.
|
|
||||||
6. **Qué significa para quien defiende** — cómo se ve una granja desde el otro lado y qué señales
|
|
||||||
deja.
|
|
||||||
|
|
||||||
## Material
|
|
||||||
|
|
||||||
El sustrato de los puntos 3, 4 y 5 está entero en
|
|
||||||
**[../01_investigacion/capa_identidad.md](../01_investigacion/capa_identidad.md)** — verificación
|
|
||||||
telefónica, por qué la eSIM no vale, reputación de IP, atestación por hardware y la correlación
|
|
||||||
entre cuentas. Es el documento del que sale la tesis.
|
|
||||||
|
|
||||||
El resto en [../01_investigacion/](../01_investigacion/); las fuentes citables en
|
|
||||||
[../01_investigacion/fuentes.md](../01_investigacion/fuentes.md).
|
|
||||||
|
|
||||||
## Pendiente
|
|
||||||
|
|
||||||
- [ ] Decidir formato y duración
|
|
||||||
- [ ] Contactar HackMadrid / CFP de Hackmeeting València
|
|
||||||
- [ ] Buscar cifras actualizadas de 2026 (los datos son de oct 2025)
|
|
||||||
- [ ] ¿Demo en vivo? El device lab de [../02_device_lab/](../02_device_lab/) sirve para enseñar
|
|
||||||
cómo se detecta un emulador
|
|
||||||
156
GUIA.md
156
GUIA.md
|
|
@ -1,137 +1,91 @@
|
||||||
# Guía de trabajo
|
# Guía de trabajo
|
||||||
|
|
||||||
Cómo seguir con esto. Estado real, qué está verificado y qué no, y por dónde continuar.
|
## Estado
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Estado a 2026-08-08
|
|
||||||
|
|
||||||
| Parte | Estado |
|
| Parte | Estado |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Investigación | **Cerrada.** Cinco documentos en `01_investigacion/` |
|
| Investigación | Cerrada, en `01_investigacion/` |
|
||||||
| Automatización Ansible | **Escrita, sin ejecutar** contra hardware |
|
| Automatización Ansible | Escrita, sin ejecutar contra hardware |
|
||||||
| Documentación de requisitos, costes y seguridad | **Cerrada** |
|
| Requisitos, costes y seguridad | Cerrados |
|
||||||
| Hardware | **Sin acceso.** Modelo de blade sin confirmar |
|
| Hardware | Sin acceso. Modelo de blade sin confirmar |
|
||||||
| Decisión de qué vía se ejecuta | **Pendiente** |
|
|
||||||
|
|
||||||
### Qué está verificado
|
### Verificado
|
||||||
|
|
||||||
- Los 18 ficheros YAML parsean correctamente
|
- Los 19 ficheros YAML parsean
|
||||||
- La plantilla de `docker-compose` renderiza YAML válido en **los dos modos de red**, con puertos
|
- La plantilla de `docker-compose` renderiza YAML válido en los dos modos de red, con puertos e
|
||||||
e IPs bien asignados
|
IPs bien asignados
|
||||||
- `fleet.sh` pasa `bash -n` una vez renderizado, sin Jinja pendiente
|
- `fleet.sh` pasa `bash -n` una vez renderizado
|
||||||
- El M1000e está identificado por su spec sheet oficial (Dell EMC, dic 2016)
|
- Los 4 diagramas SVG parsean y renderizan sin desbordes
|
||||||
|
- Las especificaciones del chasis vienen del manual del propietario (Dell, BMX01, rev. A06,
|
||||||
|
oct. 2019), no de estimaciones
|
||||||
|
|
||||||
### Qué NO está verificado
|
### Sin verificar
|
||||||
|
|
||||||
Y conviene tenerlo claro antes de fiarse de nada:
|
- Nada se ha ejecutado contra hardware real
|
||||||
|
- Que las imágenes x86_64 de Android arranquen en la generación de CPU de estos blades. Es el
|
||||||
- **Nada se ha ejecutado contra hardware real.** Ni un blade, ni el sobremesa
|
riesgo si resultan ser M610 (Xeon 2009–2011)
|
||||||
- Que las imágenes x86_64 de Android arranquen en la generación de CPU de estos blades —
|
- El comportamiento de `macvlan` sobre los módulos de I/O concretos del chasis
|
||||||
el riesgo real si resultan ser **M610** (Xeon 2009–2011)
|
- Que 3 instancias por blade sean cómodas con 8 GB en carga real
|
||||||
- El comportamiento de `macvlan` sobre los switches FlexIO concretos del chasis
|
- Las cifras de consumo son estimaciones. El CMC da el dato real
|
||||||
- Que 3 instancias por blade sean cómodas con 8 GB en carga real, no solo en el papel
|
|
||||||
- **Las cifras de consumo son estimaciones.** El CMC da el dato real; media hora ahí sustituye
|
|
||||||
todo `docs/costes.md` por medidas
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Las tres vías
|
|
||||||
|
|
||||||
Ninguna elegida todavía.
|
|
||||||
|
|
||||||
### 1 · Device lab en el rack
|
|
||||||
|
|
||||||
Infra legal y reutilizable. Primer uso real: probar `oasis_mobile` a escala, incluido el escenario
|
|
||||||
de **dos APKs que se tienen que ver entre sí**. La automatización ya está escrita.
|
|
||||||
|
|
||||||
**Bloqueante**: sitio con 2,6–3,6 kW, extracción y tolerancia a 70–85 dB. Ver
|
|
||||||
[docs/requisitos.md](docs/requisitos.md).
|
|
||||||
|
|
||||||
### 2 · Charla sobre la economía de los bots
|
|
||||||
|
|
||||||
Ángulo defensivo y periodístico, con demanda real. HackMadrid, hacklabs, **Hackmeeting València
|
|
||||||
(9–12 oct 2026)**. El material está entero en `01_investigacion/`; el guion en
|
|
||||||
[03_charla/](03_charla/).
|
|
||||||
|
|
||||||
**Es la vía con menos fricción**: no necesita encender nada.
|
|
||||||
|
|
||||||
### 3 · Reward farming
|
|
||||||
|
|
||||||
Ingreso pasivo, legal-gris. Márgenes malos en 2026. Documentado por completitud, no recomendado.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Preguntas abiertas
|
## Preguntas abiertas
|
||||||
|
|
||||||
Por orden de lo que más desbloquea:
|
1. **Modelo de blade**: M610 / M620 / M630. Determina CPU, generación y tipo de RAM.
|
||||||
|
→ `ansible-playbook playbooks/preflight.yml`
|
||||||
|
2. **Qué módulo hay en A1/A2**: un switch conmuta entre blades dentro del chasis, que es lo que
|
||||||
|
necesita `macvlan`; un módulo de paso a través saca 16 RJ-45 y deja la conmutación a un switch
|
||||||
|
externo. Cambia el montaje de red por completo
|
||||||
|
3. **¿Responde el CMC?** Da el inventario completo y el consumo real
|
||||||
|
4. **Dónde va el chasis y quién paga la luz.** El sitio tiene que estar por debajo de 35 °C todo
|
||||||
|
el año
|
||||||
|
5. **Utilización prevista.** Por debajo del ~12 %, la nube sale más barata que tenerlo 24/7
|
||||||
|
|
||||||
1. **¿Qué modelo de blade hay en el chasis?** M610 / M620 / M630. Determina CPU, generación y tipo
|
## Siguientes pasos
|
||||||
de RAM — y si el proyecto es viable. → `ansible-playbook playbooks/preflight.yml`
|
|
||||||
2. **¿Responde el CMC en red?** Si sí, da el inventario completo y el **consumo real**
|
|
||||||
3. **¿Dónde va el chasis y quién asume la factura?** Es lo que decide, más que ninguna
|
|
||||||
consideración técnica
|
|
||||||
4. **¿Cuánta utilización real va a tener?** Por debajo del ~11 % la nube sale más barata que
|
|
||||||
tenerlo 24/7. Ver [docs/costes.md](docs/costes.md)
|
|
||||||
|
|
||||||
---
|
### Sin hardware
|
||||||
|
|
||||||
## Siguientes pasos concretos
|
- [ ] Lanzar el piloto de un nodo en un sobremesa. El bloque está comentado en
|
||||||
|
`02_device_lab/ansible/inventory/hosts.yml.example`
|
||||||
|
- [ ] Confirmar que redroid arranca, que `fleet` habla con los contenedores y que un APK de
|
||||||
|
`oasis_mobile` se instala en toda la flota
|
||||||
|
|
||||||
### Sin tocar el hardware (se puede hacer hoy)
|
### Con acceso al chasis
|
||||||
|
|
||||||
- [ ] Lanzar el **piloto de un nodo** en un sobremesa: valida el pipeline entero por ~20 €/mes.
|
- [ ] Cambiar credenciales de fábrica del CMC y de los 16 iDRAC (`root`/`calvin`) — S2
|
||||||
El bloque está comentado en `02_device_lab/ansible/inventory/hosts.yml.example`
|
- [ ] VLAN aislada para la granja y otra para gestión — S1 y S3
|
||||||
- [ ] Con eso, confirmar que redroid arranca, que `fleet` habla con los contenedores y que un APK
|
- [ ] `preflight.yml` sobre los 16 blades
|
||||||
de `oasis_mobile` se instala en toda la flota
|
|
||||||
- [ ] Preparar la charla — el material ya está
|
|
||||||
|
|
||||||
### Cuando haya acceso al chasis
|
|
||||||
|
|
||||||
- [ ] Credenciales de fábrica del **CMC y de los 16 iDRAC** (`root`/`calvin`) —
|
|
||||||
[docs/seguridad.md](docs/seguridad.md) S2
|
|
||||||
- [ ] VLAN aislada para la granja y **otra** para gestión — S1 y S3
|
|
||||||
- [ ] `preflight.yml` sobre los 16 blades → informe en `ansible/reports/`
|
|
||||||
- [ ] Medir consumo real en el CMC y corregir `docs/costes.md`
|
- [ ] Medir consumo real en el CMC y corregir `docs/costes.md`
|
||||||
- [ ] Decidir sobre la ampliación de RAM: es lo único que cambia la economía del proyecto
|
- [ ] Decidir la ampliación de RAM: es lo único que cambia la economía (8,0 € → 1,8 € por
|
||||||
(7,6 € → 1,7 € por dispositivo/mes)
|
dispositivo y mes)
|
||||||
|
|
||||||
### Mejoras pendientes en el código
|
### Pendiente en el código
|
||||||
|
|
||||||
- [ ] Fijar la imagen de redroid **por digest** en vez de por tag mutable — S6
|
- [ ] Fijar la imagen de redroid por digest en vez de por tag mutable — S6
|
||||||
- [ ] Cortafuegos (nftables) en los blades: 5555+ solo desde el coordinador — S1
|
- [ ] nftables en los blades: 5555+ solo desde el coordinador — S1
|
||||||
- [ ] `ansible-vault` para secretos — S7
|
- [ ] `ansible-vault` para secretos — S7
|
||||||
- [ ] Rol de GADS, cuando la flota pase de una decena de dispositivos. No está automatizado a
|
- [ ] Script de encendido y apagado por ventanas contra el CMC vía RACADM
|
||||||
propósito: montar un despliegue de Node sin poder probarlo es complejidad sin verificar
|
- [ ] Rol de GADS cuando la flota pase de una decena de dispositivos
|
||||||
- [ ] Provisión de Debian por PXE, para no instalar 16 blades a mano
|
- [ ] Provisión de Debian por PXE, para no instalar 16 blades a mano
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Convenciones
|
## Convenciones
|
||||||
|
|
||||||
**Documentación en castellano.** Es un repo de trabajo, no un producto.
|
Documentación en castellano.
|
||||||
|
|
||||||
**Todo lo verificable, verificado, y lo demás dicho.** Si algo no se ha ejecutado, el documento lo
|
Lo verificable se verifica y lo demás se dice. Si algo no se ha ejecutado, el documento lo indica.
|
||||||
dice. Las estimaciones van etiquetadas como estimaciones y con sus supuestos a la vista. Si
|
Las estimaciones van con sus supuestos a la vista.
|
||||||
encuentras una afirmación sin respaldo, es un fallo — corrígela o márcala.
|
|
||||||
|
|
||||||
**Los hallazgos de seguridad se numeran** (S1…S11 en [docs/seguridad.md](docs/seguridad.md)) y se
|
Los hallazgos de seguridad se numeran (S1…S11 en [docs/seguridad.md](docs/seguridad.md)) y se
|
||||||
referencian por número desde el resto del repositorio.
|
referencian por número.
|
||||||
|
|
||||||
**Nada operativo de alta masiva de cuentas.** Ni proveedores de SIM, ni evasión de fingerprint, ni
|
Nada de operativa de alta masiva de cuentas: está bajo persecución activa en la UE y no funciona
|
||||||
maduración. No es una postura moral: es que está bajo persecución activa en la UE y **no funciona**
|
|
||||||
con este hardware, por lo que explica
|
con este hardware, por lo que explica
|
||||||
[01_investigacion/capa_identidad.md](01_investigacion/capa_identidad.md).
|
[01_investigacion/capa_identidad.md](01_investigacion/capa_identidad.md).
|
||||||
|
|
||||||
---
|
## Fuera del repositorio
|
||||||
|
|
||||||
## Qué NO se sube al repositorio
|
|
||||||
|
|
||||||
Está en `.gitignore`, pero conviene saber por qué:
|
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `inventory/hosts.yml` | IPs reales de los blades y posibles credenciales. Solo va el `.example` |
|
| `inventory/hosts.yml` | IPs reales y posibles credenciales. Solo se versiona el `.example` |
|
||||||
| `ansible/reports/` | Informes de preflight con el inventario real del hardware |
|
| `ansible/reports/` | Informes de preflight con el inventario real |
|
||||||
| `*.apk` | Binarios |
|
| `*.apk` | Binarios |
|
||||||
| `vault.yml`, `*.vault` | Secretos de ansible-vault |
|
| `vault.yml`, `*.vault` | Secretos de ansible-vault |
|
||||||
|
|
|
||||||
177
README.md
177
README.md
|
|
@ -1,151 +1,114 @@
|
||||||
# Rebelión en la granja
|
# Rebelión en la granja
|
||||||
|
|
||||||
Investigación y laboratorio sobre **granjas de dispositivos**: qué son realmente, quién las
|
Laboratorio de dispositivos Android sobre un chasis de blades Dell PowerEdge M1000e, más la
|
||||||
fabrica, qué se puede montar con hardware propio y qué no, y por qué la partida técnica ya está
|
investigación sobre granjas de dispositivos que llevó a montarlo así.
|
||||||
decidida.
|
|
||||||
|
|
||||||
Incluye la automatización completa para levantar un **laboratorio de dispositivos Android** sobre
|
Sin móviles físicos: cada dispositivo es un contenedor
|
||||||
un chasis de blades Debian — legal, reutilizable y sin un solo móvil físico.
|
[redroid](https://github.com/remote-android/redroid-doc) — Android real sobre el kernel del blade.
|
||||||
|
|
||||||
Arrancado el 2026-08-07 a raíz de dos webs del sector:
|
## Arquitectura
|
||||||
[phonefarmbox.com](https://www.phonefarmbox.com/) y [genfarmer.com](https://genfarmer.com/).
|
|
||||||
|
|
||||||
---
|

|
||||||
|
|
||||||
## La conclusión, por delante
|
|
||||||
|
|
||||||
> **El cuello de botella nunca fue el cómputo. Fue la identidad.**
|
|
||||||
>
|
|
||||||
> Desde que la atestación de dispositivo pasó de ser estadística a ser **criptográfica**, un
|
|
||||||
> servidor no puede hacerse pasar por un teléfono: le falta una clave grabada en fábrica que
|
|
||||||
> ningún software produce. Por eso el mercado vende cajas con teléfonos físicos de 400 $ en lugar
|
|
||||||
> de software para tu rack.
|
|
||||||
>
|
|
||||||
> Lo que queda es un problema de SIMs, de reputación de IP y de correlación entre cuentas. Y ahí es
|
|
||||||
> exactamente donde pega la policía.
|
|
||||||
|
|
||||||
El desarrollo está en **[01_investigacion/capa_identidad.md](01_investigacion/capa_identidad.md)**,
|
|
||||||
que es el documento central del repositorio.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Qué hay aquí
|
|
||||||
|
|
||||||
### 📄 [docs/](docs/) — léelo antes de encender nada
|
|
||||||
|
|
||||||
| | |
|
|
||||||
|---|---|
|
|
||||||
| [requisitos.md](docs/requisitos.md) | Eléctrico, físico, hardware, red, tiempo. Con checklist de bloqueantes |
|
|
||||||
| [costes.md](docs/costes.md) | La luz es el coste real: ~340 €/mes 24/7, ~56 €/mes por ventanas |
|
|
||||||
| [seguridad.md](docs/seguridad.md) | 11 hallazgos, uno crítico. Incluye los que introduce este propio código |
|
|
||||||
|
|
||||||
### 🔍 [01_investigacion/](01_investigacion/) — el análisis
|
|
||||||
|
|
||||||
| | |
|
|
||||||
|---|---|
|
|
||||||
| [capa_identidad.md](01_investigacion/capa_identidad.md) | **El documento central.** Verificación telefónica, por qué la eSIM no vale, reputación de IP, atestación por hardware y la correlación entre cuentas |
|
|
||||||
| [mercado_y_players.md](01_investigacion/mercado_y_players.md) | Los tres negocios bajo el mismo nombre, quién juega en Europa, TikTok vs Instagram |
|
|
||||||
| [stack_tecnico.md](01_investigacion/stack_tecnico.md) | redroid, Cuttlefish, Waydroid, GADS — y por qué el rack no resuelve el caso social |
|
|
||||||
| [legal_ue.md](01_investigacion/legal_ue.md) | DSA, Operación SIMCARTEL, riesgo penal en España |
|
|
||||||
| [fuentes.md](01_investigacion/fuentes.md) | Enlaces |
|
|
||||||
|
|
||||||
### 🔧 [02_device_lab/](02_device_lab/) — el laboratorio
|
|
||||||
|
|
||||||
| | |
|
|
||||||
|---|---|
|
|
||||||
| [ansible/](02_device_lab/ansible/) | **La automatización completa**: preflight, despliegue de los 16 blades y control de flota |
|
|
||||||
| [hardware_m1000e.md](02_device_lab/hardware_m1000e.md) | El chasis, sus límites y la palanca (RAM) |
|
|
||||||
| [README.md](02_device_lab/README.md) | Montaje de un solo nodo, a mano, para entender las piezas |
|
|
||||||
|
|
||||||
### 🎤 [03_charla/](03_charla/) — divulgación
|
|
||||||
|
|
||||||
Guion de 6 puntos para HackMadrid / Hackmeeting València.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Especificaciones
|
|
||||||
|
|
||||||
### Arquitectura
|
|
||||||
|
|
||||||
```
|
```
|
||||||
Dell PowerEdge M1000e — chasis de blades, 16 slots (8 arriba + 8 abajo)
|
Dell PowerEdge M1000e — 16 blades (8 arriba + 8 abajo)
|
||||||
│
|
│
|
||||||
├── blade-01 ................ COORDINADOR
|
├── blade-01 ................ coordinador: adb + fleet
|
||||||
│ └── adb + fleet único punto de control de toda la flota
|
|
||||||
│
|
│
|
||||||
└── blade-02 .. blade-16 .... NODOS DE CARGA (15)
|
└── blade-02 .. blade-16 .... nodos de carga
|
||||||
└── Debian 12 pelado
|
└── Debian 12
|
||||||
└── Docker
|
└── Docker
|
||||||
└── N × redroid Android 13 en contenedor
|
└── N × redroid
|
||||||
|
|
||||||
8 GB/blade → 3 instancias → ~45 Android
|
8 GB/blade → 3 instancias → 45 Android
|
||||||
32 GB/blade → 14 instancias → ~210 Android
|
32 GB/blade → 14 instancias → 210 Android
|
||||||
```
|
```
|
||||||
|
|
||||||
**No hay móviles físicos.** Cada "dispositivo" es un contenedor
|
Debian va directo sobre el hierro. Sin Proxmox, sin VMs, sin LXC anidado: con 8 GB por blade cada
|
||||||
[redroid](https://github.com/remote-android/redroid-doc): Android real sobre el kernel del blade.
|
capa de hipervisor se come una instancia entera.
|
||||||
|
|
||||||
Debian va **directo sobre el hierro**. Sin Proxmox, sin VMs, sin LXC anidado — con 8 GB por blade,
|
## Hardware
|
||||||
cada capa de hipervisor se come una instancia Android entera.
|
|
||||||
|
|
||||||
### Stack
|

|
||||||
|
|
||||||
|
Datos del manual del propietario del M1000e (Dell, modelo BMX01, rev. A06, oct. 2019). Dos
|
||||||
|
exigencias del manual condicionan el proyecto entero: las seis fuentes y los nueve ventiladores son
|
||||||
|
obligatorios, se usen 3 blades o 16. No se puede arrancar el chasis a medias.
|
||||||
|
|
||||||
|
Detalle en [02_device_lab/hardware_m1000e.md](02_device_lab/hardware_m1000e.md).
|
||||||
|
|
||||||
|
## Software
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
| Capa | Tecnología |
|
| Capa | Tecnología |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Hardware | Dell PowerEdge M1000e, 16 blades, 8 GB/blade |
|
|
||||||
| SO | Debian 12 bookworm |
|
| SO | Debian 12 bookworm |
|
||||||
| Kernel | `binder_linux` con devices `binder,hwbinder,vndbinder` (Debian no trae binderfs) |
|
| Kernel | `binder_linux` con devices `binder,hwbinder,vndbinder` (Debian no trae binderfs) |
|
||||||
| Contenedores | Docker CE + Compose v2 |
|
| Contenedores | Docker CE + Compose v2 |
|
||||||
| Android | redroid 13 (memfd, sin ashmem) |
|
| Android | redroid 13 |
|
||||||
| Orquestación | Ansible — solo `ansible.builtin`, sin colecciones externas |
|
| Orquestación | Ansible, solo `ansible.builtin` |
|
||||||
| Control | adb sobre TCP + `fleet` |
|
| Control | adb sobre TCP + `fleet` |
|
||||||
| Red | `portmap` (NAT) o `macvlan` (IP real de LAN por el switch FlexIO) |
|
| Red | `portmap` (NAT) o `macvlan` (IP real de LAN por Fabric A) |
|
||||||
|
|
||||||
### Números
|
## Red
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Números
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Capacidad | ~45 Android (~210 con la RAM ampliada) |
|
| Capacidad | 45 Android; 210 con la RAM ampliada |
|
||||||
| Consumo | 2,6–3,6 kW · 70–85 dB · 179 kg · 10U |
|
| Chasis | 10U · 44,0 × 44,7 × 75,5 cm · 200,5 kg cargado |
|
||||||
| Coste 24/7 | ~340 €/mes (~4.100 €/año) |
|
| Consumo | 2,6–3,6 kW · 70–85 dB · 6 fuentes C20 · 9 ventiladores |
|
||||||
| Coste por ventanas de 4 h/día | ~56 €/mes |
|
| Térmico | 10–35 °C en continuo |
|
||||||
| Coste por dispositivo | 7,6 €/mes → **1,7 €/mes** con la RAM ampliada |
|
| Coste 24/7 | ~360 €/mes |
|
||||||
|
| Coste por ventanas de 4 h/día | ~59 €/mes |
|
||||||
|
| Coste por dispositivo | 8,0 €/mes; 1,8 €/mes con la RAM ampliada |
|
||||||
|
|
||||||
---
|
## Arranque
|
||||||
|
|
||||||
## Arranque rápido
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://gitea.laenre.net/hacklab/REBELION_EN_LA_GRANJA.git
|
git clone https://gitea.laenre.net/hacklab/REBELION_EN_LA_GRANJA.git
|
||||||
cd REBELION_EN_LA_GRANJA/02_device_lab/ansible
|
cd REBELION_EN_LA_GRANJA/02_device_lab/ansible
|
||||||
|
|
||||||
sudo apt install ansible
|
sudo apt install ansible
|
||||||
cp inventory/hosts.yml.example inventory/hosts.yml # pon las IPs reales
|
cp inventory/hosts.yml.example inventory/hosts.yml # poner las IPs reales
|
||||||
|
|
||||||
ansible-playbook playbooks/preflight.yml # SOLO LECTURA — no toca nada
|
ansible-playbook playbooks/preflight.yml # solo lectura, no toca nada
|
||||||
ansible-playbook site.yml # monta la granja
|
ansible-playbook site.yml
|
||||||
ansible-playbook playbooks/status.yml
|
ansible-playbook playbooks/status.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
**Empieza por el preflight siempre.** Te dice qué blades hay dentro del chasis leyéndolo del DMI,
|
El preflight va primero. Identifica el modelo de blade leyéndolo del DMI, comprueba si esas CPUs
|
||||||
si esas CPUs pueden con Android x86_64, y cuántas instancias caben. Antes de gastar un minuto.
|
sirven para Android x86_64 y calcula cuántas instancias caben.
|
||||||
|
|
||||||
**Y antes de encender el chasis**, el inventario trae un bloque de **piloto de un nodo** para
|
Para probar sin encender el chasis, el inventario incluye un bloque de piloto de un nodo que
|
||||||
probar el pipeline entero en un sobremesa, por 20 €/mes y sin ruido.
|
levanta todo el pipeline en un sobremesa.
|
||||||
|
|
||||||
Guía de trabajo y siguientes pasos: **[GUIA.md](GUIA.md)**.
|
## Contenido
|
||||||
|
|
||||||
---
|
| | |
|
||||||
|
|---|---|
|
||||||
|
| [GUIA.md](GUIA.md) | Estado, qué está verificado y qué no, siguientes pasos |
|
||||||
|
| [docs/requisitos.md](docs/requisitos.md) | Eléctrico, físico, red, tiempo. Checklist de bloqueantes |
|
||||||
|
| [docs/costes.md](docs/costes.md) | Consumo y coste por escenario |
|
||||||
|
| [docs/seguridad.md](docs/seguridad.md) | 11 hallazgos, uno crítico |
|
||||||
|
| [docs/usabilidad.md](docs/usabilidad.md) | Cómo se opera la flota |
|
||||||
|
| [02_device_lab/ansible/](02_device_lab/ansible/) | La automatización |
|
||||||
|
| [02_device_lab/hardware_m1000e.md](02_device_lab/hardware_m1000e.md) | El chasis según el manual |
|
||||||
|
| [01_investigacion/](01_investigacion/) | Mercado, stack, capa de identidad, marco legal |
|
||||||
|
|
||||||
## Aviso
|
## Por qué esto no sirve para plataformas sociales
|
||||||
|
|
||||||
Este repositorio documenta cómo funcionan las granjas de dispositivos y **por qué fracasan** contra
|
La atestación de dispositivo dejó de ser estadística y pasó a ser criptográfica. Un Android
|
||||||
las plataformas. La automatización que contiene levanta un laboratorio de QA para probar apps
|
certificado lleva una clave privada grabada en el TEE de fábrica, con cadena de certificados hasta
|
||||||
propias.
|
una raíz de Google. Un contenedor no la tiene y no puede tenerla: no hay software que la produzca.
|
||||||
|
|
||||||
No contiene, ni va a contener, operativa de alta masiva de cuentas: proveedores de SIM, evasión de
|
Por eso el mercado vende teléfonos físicos de 400 $ en lugar de software para racks, y por eso este
|
||||||
fingerprint o maduración de cuentas. Eso es fraude de identidad a escala, en la UE está bajo
|
laboratorio sirve para probar apps propias y no para otra cosa. El desarrollo está en
|
||||||
persecución activa, y además **no funcionaría** con este hardware por lo que se explica en
|
[01_investigacion/capa_identidad.md](01_investigacion/capa_identidad.md).
|
||||||
[capa_identidad.md](01_investigacion/capa_identidad.md).
|
|
||||||
|
|
||||||
Contexto legal: [legal_ue.md](01_investigacion/legal_ue.md).
|
Este repositorio no contiene operativa de alta masiva de cuentas. Contexto legal en
|
||||||
|
[01_investigacion/legal_ue.md](01_investigacion/legal_ue.md).
|
||||||
|
|
|
||||||
103
assets/arquitectura.svg
Normal file
103
assets/arquitectura.svg
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 620" width="960" height="620" font-family="ui-monospace, 'DejaVu Sans Mono', Menlo, monospace">
|
||||||
|
<rect width="960" height="620" fill="#0f1720"/>
|
||||||
|
|
||||||
|
<text x="32" y="44" fill="#e6edf3" font-size="22" font-weight="bold" font-family="system-ui, sans-serif">Arquitectura de la granja</text>
|
||||||
|
<text x="32" y="68" fill="#7d8590" font-size="13">Dell PowerEdge M1000e · 16 blades Debian · ~45 Android en contenedor</text>
|
||||||
|
|
||||||
|
<!-- Chasis -->
|
||||||
|
<rect x="32" y="92" width="590" height="490" rx="8" fill="#161b22" stroke="#30363d" stroke-width="1.5"/>
|
||||||
|
<text x="52" y="118" fill="#58a6ff" font-size="13" font-weight="bold">CHASIS M1000e · 10U · 200,5 kg · 2,6–3,6 kW</text>
|
||||||
|
|
||||||
|
<!-- Coordinador -->
|
||||||
|
<rect x="52" y="134" width="550" height="72" rx="6" fill="#1c2128" stroke="#d29922" stroke-width="1.5"/>
|
||||||
|
<text x="68" y="158" fill="#d29922" font-size="13" font-weight="bold">blade-01 · COORDINADOR</text>
|
||||||
|
<text x="68" y="178" fill="#adbac7" font-size="11.5">Debian 12 · adb · fleet.sh · devices.txt</text>
|
||||||
|
<text x="68" y="196" fill="#7d8590" font-size="11">No corre Android. Único punto de control de la flota.</text>
|
||||||
|
|
||||||
|
<!-- Nodos de carga: header -->
|
||||||
|
<text x="52" y="238" fill="#3fb950" font-size="13" font-weight="bold">blade-02 … blade-16 · NODOS DE CARGA (15)</text>
|
||||||
|
|
||||||
|
<!-- Detalle de un blade -->
|
||||||
|
<rect x="52" y="252" width="270" height="240" rx="6" fill="#1c2128" stroke="#3fb950" stroke-width="1.5"/>
|
||||||
|
<text x="68" y="274" fill="#3fb950" font-size="12" font-weight="bold">blade-NN · 8 GB RAM</text>
|
||||||
|
|
||||||
|
<rect x="68" y="286" width="238" height="38" rx="4" fill="#22272e" stroke="#444c56"/>
|
||||||
|
<text x="80" y="303" fill="#adbac7" font-size="11">Debian 12 · sobre el hierro</text>
|
||||||
|
<text x="80" y="317" fill="#7d8590" font-size="9.5">binder · hwbinder · vndbinder</text>
|
||||||
|
|
||||||
|
<rect x="68" y="330" width="238" height="26" rx="4" fill="#22272e" stroke="#444c56"/>
|
||||||
|
<text x="80" y="347" fill="#adbac7" font-size="11">Docker CE + Compose v2</text>
|
||||||
|
|
||||||
|
<rect x="80" y="364" width="214" height="26" rx="4" fill="#1f6feb" fill-opacity="0.18" stroke="#1f6feb"/>
|
||||||
|
<text x="92" y="381" fill="#79c0ff" font-size="10.5">redroid-NN-01 · Android 13</text>
|
||||||
|
<rect x="80" y="394" width="214" height="26" rx="4" fill="#1f6feb" fill-opacity="0.18" stroke="#1f6feb"/>
|
||||||
|
<text x="92" y="411" fill="#79c0ff" font-size="10.5">redroid-NN-02 · Android 13</text>
|
||||||
|
<rect x="80" y="424" width="214" height="26" rx="4" fill="#1f6feb" fill-opacity="0.18" stroke="#1f6feb"/>
|
||||||
|
<text x="92" y="441" fill="#79c0ff" font-size="10.5">redroid-NN-03 · Android 13</text>
|
||||||
|
|
||||||
|
<text x="68" y="472" fill="#7d8590" font-size="10">Sin VM ni LXC anidado: cada capa</text>
|
||||||
|
<text x="68" y="485" fill="#7d8590" font-size="10">se comería una instancia entera.</text>
|
||||||
|
|
||||||
|
<!-- Los otros blades apilados -->
|
||||||
|
<g fill="#1c2128" stroke="#2d5a3d">
|
||||||
|
<rect x="342" y="252" width="260" height="34" rx="5"/>
|
||||||
|
<rect x="342" y="292" width="260" height="34" rx="5"/>
|
||||||
|
<rect x="342" y="332" width="260" height="34" rx="5"/>
|
||||||
|
<rect x="342" y="372" width="260" height="34" rx="5"/>
|
||||||
|
</g>
|
||||||
|
<text x="356" y="274" fill="#7d8590" font-size="11">blade-03 → 3 Android</text>
|
||||||
|
<text x="356" y="314" fill="#7d8590" font-size="11">blade-04 → 3 Android</text>
|
||||||
|
<text x="356" y="354" fill="#7d8590" font-size="11">blade-05 → 3 Android</text>
|
||||||
|
<text x="356" y="394" fill="#7d8590" font-size="11">…</text>
|
||||||
|
<text x="356" y="428" fill="#7d8590" font-size="11">blade-16 → 3 Android</text>
|
||||||
|
|
||||||
|
<rect x="342" y="444" width="260" height="48" rx="5" fill="#1f6feb" fill-opacity="0.12" stroke="#1f6feb"/>
|
||||||
|
<text x="356" y="464" fill="#79c0ff" font-size="13" font-weight="bold">15 × 3 = 45 Android</text>
|
||||||
|
<text x="356" y="482" fill="#7d8590" font-size="10.5">con RAM a 32 GB → 15 × 14 = 210</text>
|
||||||
|
|
||||||
|
<!-- Fabric A -->
|
||||||
|
<rect x="52" y="504" width="550" height="60" rx="6" fill="#1c2128" stroke="#a371f7" stroke-width="1.5"/>
|
||||||
|
<text x="68" y="526" fill="#a371f7" font-size="12" font-weight="bold">FABRIC A · ranuras A1 / A2 · Ethernet integrada (LOM) de cada blade</text>
|
||||||
|
<text x="68" y="546" fill="#7d8590" font-size="10.5">Conmutación interna entre blades, sin tarjetas intermedias. Hace posible macvlan.</text>
|
||||||
|
<text x="68" y="559" fill="#7d8590" font-size="10.5">Fabrics B y C (FC / InfiniBand) no se usan aquí.</text>
|
||||||
|
|
||||||
|
<!-- Flechas hacia el control -->
|
||||||
|
<path d="M 622 170 L 700 170" stroke="#d29922" stroke-width="2" fill="none" marker-end="url(#a)"/>
|
||||||
|
<path d="M 622 534 L 700 534" stroke="#a371f7" stroke-width="2" fill="none" marker-end="url(#p)"/>
|
||||||
|
|
||||||
|
<defs>
|
||||||
|
<marker id="a" markerWidth="9" markerHeight="9" refX="8" refY="4.5" orient="auto">
|
||||||
|
<path d="M0,0 L9,4.5 L0,9 z" fill="#d29922"/>
|
||||||
|
</marker>
|
||||||
|
<marker id="p" markerWidth="9" markerHeight="9" refX="8" refY="4.5" orient="auto">
|
||||||
|
<path d="M0,0 L9,4.5 L0,9 z" fill="#a371f7"/>
|
||||||
|
</marker>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<!-- Panel derecho: control -->
|
||||||
|
<rect x="700" y="92" width="228" height="200" rx="8" fill="#161b22" stroke="#30363d" stroke-width="1.5"/>
|
||||||
|
<text x="716" y="118" fill="#e6edf3" font-size="13" font-weight="bold" font-family="system-ui, sans-serif">Nodo de control</text>
|
||||||
|
<text x="716" y="142" fill="#adbac7" font-size="11">Ansible (solo builtin)</text>
|
||||||
|
<text x="716" y="162" fill="#7d8590" font-size="10.5">preflight.yml → reconocer</text>
|
||||||
|
<text x="716" y="178" fill="#7d8590" font-size="10.5">site.yml → desplegar</text>
|
||||||
|
<text x="716" y="194" fill="#7d8590" font-size="10.5">apk.yml → instalar APK</text>
|
||||||
|
<text x="716" y="210" fill="#7d8590" font-size="10.5">status.yml → comprobar</text>
|
||||||
|
<text x="716" y="234" fill="#adbac7" font-size="11">SSH → los 16 blades</text>
|
||||||
|
<text x="716" y="256" fill="#7d8590" font-size="10.5">forks = 20: la flota entera</text>
|
||||||
|
<text x="716" y="272" fill="#7d8590" font-size="10.5">en paralelo</text>
|
||||||
|
|
||||||
|
<rect x="700" y="308" width="228" height="130" rx="8" fill="#161b22" stroke="#30363d" stroke-width="1.5"/>
|
||||||
|
<text x="716" y="332" fill="#e6edf3" font-size="13" font-weight="bold" font-family="system-ui, sans-serif">Control de flota</text>
|
||||||
|
<text x="716" y="356" fill="#79c0ff" font-size="11">fleet connect</text>
|
||||||
|
<text x="716" y="374" fill="#79c0ff" font-size="11">fleet list</text>
|
||||||
|
<text x="716" y="392" fill="#79c0ff" font-size="11">fleet install app.apk</text>
|
||||||
|
<text x="716" y="410" fill="#79c0ff" font-size="11">fleet shell '<cmd>'</text>
|
||||||
|
<text x="716" y="428" fill="#79c0ff" font-size="11">fleet ip</text>
|
||||||
|
|
||||||
|
<rect x="700" y="454" width="228" height="110" rx="8" fill="#161b22" stroke="#f85149" stroke-width="1.5"/>
|
||||||
|
<text x="716" y="478" fill="#f85149" font-size="12" font-weight="bold" font-family="system-ui, sans-serif">Sin móviles físicos</text>
|
||||||
|
<text x="716" y="500" fill="#7d8590" font-size="10.5">Cada dispositivo es un</text>
|
||||||
|
<text x="716" y="515" fill="#7d8590" font-size="10.5">contenedor redroid sobre</text>
|
||||||
|
<text x="716" y="530" fill="#7d8590" font-size="10.5">el kernel del blade.</text>
|
||||||
|
<text x="716" y="551" fill="#7d8590" font-size="10.5">Detectables como emulador.</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 7 KiB |
106
assets/chasis.svg
Normal file
106
assets/chasis.svg
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 560" width="960" height="560" font-family="ui-monospace, 'DejaVu Sans Mono', Menlo, monospace">
|
||||||
|
<rect width="960" height="560" fill="#0f1720"/>
|
||||||
|
|
||||||
|
<text x="32" y="42" fill="#e6edf3" font-size="22" font-weight="bold" font-family="system-ui, sans-serif">Dell PowerEdge M1000e</text>
|
||||||
|
<text x="32" y="65" fill="#7d8590" font-size="12.5">Manual del propietario, modelo BMX01, rev. A06 (oct. 2019) · 44,0 × 44,7 × 75,5 cm · 10U · 200,5 kg cargado</text>
|
||||||
|
|
||||||
|
<!-- FRONTAL -->
|
||||||
|
<text x="32" y="102" fill="#58a6ff" font-size="14" font-weight="bold">PANEL FRONTAL — los blades</text>
|
||||||
|
|
||||||
|
<rect x="32" y="114" width="890" height="170" rx="8" fill="#161b22" stroke="#30363d" stroke-width="1.5"/>
|
||||||
|
|
||||||
|
<!-- fila superior -->
|
||||||
|
<g>
|
||||||
|
<rect x="52" y="134" width="82" height="60" rx="4" fill="#1c2128" stroke="#d29922" stroke-width="1.5"/>
|
||||||
|
<text x="86" y="170" fill="#d29922" font-size="15" font-weight="bold" text-anchor="middle">1</text>
|
||||||
|
<text x="86" y="186" fill="#7d8590" font-size="8.5" text-anchor="middle">coord.</text>
|
||||||
|
</g>
|
||||||
|
<g fill="#1c2128" stroke="#3fb950" stroke-width="1.2">
|
||||||
|
<rect x="142" y="134" width="82" height="60" rx="4"/>
|
||||||
|
<rect x="232" y="134" width="82" height="60" rx="4"/>
|
||||||
|
<rect x="322" y="134" width="82" height="60" rx="4"/>
|
||||||
|
<rect x="412" y="134" width="82" height="60" rx="4"/>
|
||||||
|
<rect x="502" y="134" width="82" height="60" rx="4"/>
|
||||||
|
<rect x="592" y="134" width="82" height="60" rx="4"/>
|
||||||
|
<rect x="682" y="134" width="82" height="60" rx="4"/>
|
||||||
|
</g>
|
||||||
|
<g fill="#adbac7" font-size="15" text-anchor="middle" font-weight="bold">
|
||||||
|
<text x="183" y="170">2</text><text x="273" y="170">3</text><text x="363" y="170">4</text>
|
||||||
|
<text x="453" y="170">5</text><text x="543" y="170">6</text><text x="633" y="170">7</text><text x="723" y="170">8</text>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- fila inferior -->
|
||||||
|
<g fill="#1c2128" stroke="#3fb950" stroke-width="1.2">
|
||||||
|
<rect x="52" y="202" width="82" height="60" rx="4"/>
|
||||||
|
<rect x="142" y="202" width="82" height="60" rx="4"/>
|
||||||
|
<rect x="232" y="202" width="82" height="60" rx="4"/>
|
||||||
|
<rect x="322" y="202" width="82" height="60" rx="4"/>
|
||||||
|
<rect x="412" y="202" width="82" height="60" rx="4"/>
|
||||||
|
<rect x="502" y="202" width="82" height="60" rx="4"/>
|
||||||
|
<rect x="592" y="202" width="82" height="60" rx="4"/>
|
||||||
|
<rect x="682" y="202" width="82" height="60" rx="4"/>
|
||||||
|
</g>
|
||||||
|
<g fill="#adbac7" font-size="15" text-anchor="middle" font-weight="bold">
|
||||||
|
<text x="93" y="238">9</text><text x="183" y="238">10</text><text x="273" y="238">11</text><text x="363" y="238">12</text>
|
||||||
|
<text x="453" y="238">13</text><text x="543" y="238">14</text><text x="633" y="238">15</text><text x="723" y="238">16</text>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- LCD -->
|
||||||
|
<rect x="790" y="134" width="112" height="128" rx="5" fill="#1c2128" stroke="#a371f7" stroke-width="1.5"/>
|
||||||
|
<text x="846" y="168" fill="#a371f7" font-size="12" font-weight="bold" text-anchor="middle">LCD</text>
|
||||||
|
<text x="846" y="190" fill="#7d8590" font-size="9.5" text-anchor="middle">panel control</text>
|
||||||
|
<text x="846" y="208" fill="#7d8590" font-size="9.5" text-anchor="middle">asistente config</text>
|
||||||
|
<text x="846" y="226" fill="#7d8590" font-size="9.5" text-anchor="middle">2 × USB</text>
|
||||||
|
<text x="846" y="244" fill="#7d8590" font-size="9.5" text-anchor="middle">VGA</text>
|
||||||
|
|
||||||
|
<text x="52" y="300" fill="#7d8590" font-size="11">16 blades de media altura — 8 arriba y 8 abajo. Toda bahía vacía necesita módulo de relleno o se degrada la refrigeración.</text>
|
||||||
|
|
||||||
|
<!-- POSTERIOR -->
|
||||||
|
<text x="32" y="342" fill="#58a6ff" font-size="14" font-weight="bold">PANEL POSTERIOR — infraestructura compartida</text>
|
||||||
|
|
||||||
|
<rect x="32" y="354" width="890" height="180" rx="8" fill="#161b22" stroke="#30363d" stroke-width="1.5"/>
|
||||||
|
|
||||||
|
<!-- ventiladores -->
|
||||||
|
<g fill="#1c2128" stroke="#f85149" stroke-width="1.2">
|
||||||
|
<rect x="52" y="372" width="86" height="34" rx="4"/><rect x="146" y="372" width="86" height="34" rx="4"/>
|
||||||
|
<rect x="240" y="372" width="86" height="34" rx="4"/><rect x="334" y="372" width="86" height="34" rx="4"/>
|
||||||
|
<rect x="428" y="372" width="86" height="34" rx="4"/><rect x="522" y="372" width="86" height="34" rx="4"/>
|
||||||
|
<rect x="616" y="372" width="86" height="34" rx="4"/><rect x="710" y="372" width="86" height="34" rx="4"/>
|
||||||
|
<rect x="804" y="372" width="86" height="34" rx="4"/>
|
||||||
|
</g>
|
||||||
|
<g fill="#f85149" font-size="10.5" text-anchor="middle">
|
||||||
|
<text x="95" y="394">VENT 1</text><text x="189" y="394">VENT 2</text><text x="283" y="394">VENT 3</text>
|
||||||
|
<text x="377" y="394">VENT 4</text><text x="471" y="394">VENT 5</text><text x="565" y="394">VENT 6</text>
|
||||||
|
<text x="659" y="394">VENT 7</text><text x="753" y="394">VENT 8</text><text x="847" y="394">VENT 9</text>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- IO + CMC -->
|
||||||
|
<rect x="52" y="418" width="256" height="52" rx="5" fill="#1c2128" stroke="#a371f7" stroke-width="1.5"/>
|
||||||
|
<text x="180" y="440" fill="#a371f7" font-size="13" font-weight="bold" text-anchor="middle">A1 B1 C1</text>
|
||||||
|
<text x="180" y="459" fill="#7d8590" font-size="10" text-anchor="middle">módulos de I/O (izquierda)</text>
|
||||||
|
|
||||||
|
<rect x="320" y="418" width="150" height="52" rx="5" fill="#1c2128" stroke="#d29922" stroke-width="1.5"/>
|
||||||
|
<text x="395" y="437" fill="#d29922" font-size="11.5" font-weight="bold" text-anchor="middle">CMC 1 · iKVM</text>
|
||||||
|
<text x="395" y="455" fill="#d29922" font-size="11.5" font-weight="bold" text-anchor="middle">CMC 2</text>
|
||||||
|
|
||||||
|
<rect x="482" y="418" width="256" height="52" rx="5" fill="#1c2128" stroke="#a371f7" stroke-width="1.5"/>
|
||||||
|
<text x="610" y="440" fill="#a371f7" font-size="13" font-weight="bold" text-anchor="middle">C2 B2 A2</text>
|
||||||
|
<text x="610" y="459" fill="#7d8590" font-size="10" text-anchor="middle">módulos de I/O (derecha)</text>
|
||||||
|
|
||||||
|
<rect x="750" y="418" width="140" height="52" rx="5" fill="#1c2128" stroke="#444c56"/>
|
||||||
|
<text x="820" y="440" fill="#7d8590" font-size="10" text-anchor="middle">Fabric A → Ethernet</text>
|
||||||
|
<text x="820" y="456" fill="#7d8590" font-size="10" text-anchor="middle">B/C → FC · IB</text>
|
||||||
|
|
||||||
|
<!-- PSU -->
|
||||||
|
<g fill="#1c2128" stroke="#3fb950" stroke-width="1.2">
|
||||||
|
<rect x="52" y="482" width="132" height="34" rx="4"/><rect x="192" y="482" width="132" height="34" rx="4"/>
|
||||||
|
<rect x="332" y="482" width="132" height="34" rx="4"/><rect x="472" y="482" width="132" height="34" rx="4"/>
|
||||||
|
<rect x="612" y="482" width="132" height="34" rx="4"/><rect x="752" y="482" width="138" height="34" rx="4"/>
|
||||||
|
</g>
|
||||||
|
<g fill="#3fb950" font-size="10.5" text-anchor="middle">
|
||||||
|
<text x="118" y="504">PSU 1</text><text x="258" y="504">PSU 2</text><text x="398" y="504">PSU 3</text>
|
||||||
|
<text x="538" y="504">PSU 4</text><text x="678" y="504">PSU 5</text><text x="821" y="504">PSU 6</text>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<text x="32" y="550" fill="#f85149" font-size="11.5">Obligatorio por manual: las 6 fuentes y los 9 ventiladores instalados en todo momento — con 3 blades o con 16.</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 6.8 KiB |
67
assets/red-modos.svg
Normal file
67
assets/red-modos.svg
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 470" width="960" height="470" font-family="ui-monospace, 'DejaVu Sans Mono', Menlo, monospace">
|
||||||
|
<rect width="960" height="470" fill="#0f1720"/>
|
||||||
|
|
||||||
|
<text x="32" y="42" fill="#e6edf3" font-size="22" font-weight="bold" font-family="system-ui, sans-serif">Los dos modos de red</text>
|
||||||
|
<text x="32" y="65" fill="#7d8590" font-size="12.5">redroid_network_mode en group_vars/all.yml</text>
|
||||||
|
|
||||||
|
<!-- PORTMAP -->
|
||||||
|
<rect x="32" y="88" width="432" height="300" rx="8" fill="#161b22" stroke="#3fb950" stroke-width="1.5"/>
|
||||||
|
<text x="52" y="116" fill="#3fb950" font-size="15" font-weight="bold">portmap · por defecto</text>
|
||||||
|
<text x="52" y="136" fill="#7d8590" font-size="11">NAT de Docker. Funciona en cualquier sitio.</text>
|
||||||
|
|
||||||
|
<rect x="52" y="152" width="392" height="120" rx="5" fill="#1c2128" stroke="#444c56"/>
|
||||||
|
<text x="68" y="174" fill="#adbac7" font-size="11.5">blade-02 · 10.0.0.12</text>
|
||||||
|
|
||||||
|
<rect x="68" y="186" width="170" height="24" rx="3" fill="#1f6feb" fill-opacity="0.18" stroke="#1f6feb"/>
|
||||||
|
<text x="78" y="203" fill="#79c0ff" font-size="10.5">redroid-01 (interno)</text>
|
||||||
|
<rect x="68" y="214" width="170" height="24" rx="3" fill="#1f6feb" fill-opacity="0.18" stroke="#1f6feb"/>
|
||||||
|
<text x="78" y="231" fill="#79c0ff" font-size="10.5">redroid-02 (interno)</text>
|
||||||
|
<rect x="68" y="242" width="170" height="24" rx="3" fill="#1f6feb" fill-opacity="0.18" stroke="#1f6feb"/>
|
||||||
|
<text x="78" y="259" fill="#79c0ff" font-size="10.5">redroid-03 (interno)</text>
|
||||||
|
|
||||||
|
<g stroke="#3fb950" stroke-width="1.3" fill="none">
|
||||||
|
<path d="M 238 198 L 288 198"/><path d="M 238 226 L 288 226"/><path d="M 238 254 L 288 254"/>
|
||||||
|
</g>
|
||||||
|
<text x="296" y="202" fill="#adbac7" font-size="10.5">:5555</text>
|
||||||
|
<text x="296" y="230" fill="#adbac7" font-size="10.5">:5556</text>
|
||||||
|
<text x="296" y="258" fill="#adbac7" font-size="10.5">:5557</text>
|
||||||
|
<text x="296" y="180" fill="#7d8590" font-size="10">puertos del blade</text>
|
||||||
|
|
||||||
|
<text x="52" y="298" fill="#adbac7" font-size="11">adb → 10.0.0.12:5555, :5556, :5557</text>
|
||||||
|
<text x="52" y="320" fill="#3fb950" font-size="10.5">✓ No hace falta saber nada de la LAN</text>
|
||||||
|
<text x="52" y="336" fill="#3fb950" font-size="10.5">✓ redroid_adb_bind_ip limita la escucha</text>
|
||||||
|
<text x="52" y="356" fill="#d29922" font-size="10.5">✗ Los Android están tras NAT: no son</text>
|
||||||
|
<text x="52" y="371" fill="#d29922" font-size="10.5"> pares de red entre sí</text>
|
||||||
|
|
||||||
|
<!-- MACVLAN -->
|
||||||
|
<rect x="496" y="88" width="432" height="300" rx="8" fill="#161b22" stroke="#a371f7" stroke-width="1.5"/>
|
||||||
|
<text x="516" y="116" fill="#a371f7" font-size="15" font-weight="bold">macvlan · para oasis_mobile</text>
|
||||||
|
<text x="516" y="136" fill="#7d8590" font-size="11">IP real de LAN por el switch de Fabric A.</text>
|
||||||
|
|
||||||
|
<rect x="516" y="152" width="392" height="120" rx="5" fill="#1c2128" stroke="#444c56"/>
|
||||||
|
<text x="532" y="174" fill="#adbac7" font-size="11.5">blade-02 · 10.0.0.12</text>
|
||||||
|
|
||||||
|
<rect x="532" y="186" width="200" height="24" rx="3" fill="#a371f7" fill-opacity="0.18" stroke="#a371f7"/>
|
||||||
|
<text x="542" y="203" fill="#d2a8ff" font-size="10.5">redroid-01 → 10.0.0.20</text>
|
||||||
|
<rect x="532" y="214" width="200" height="24" rx="3" fill="#a371f7" fill-opacity="0.18" stroke="#a371f7"/>
|
||||||
|
<text x="542" y="231" fill="#d2a8ff" font-size="10.5">redroid-02 → 10.0.0.21</text>
|
||||||
|
<rect x="532" y="242" width="200" height="24" rx="3" fill="#a371f7" fill-opacity="0.18" stroke="#a371f7"/>
|
||||||
|
<text x="542" y="259" fill="#d2a8ff" font-size="10.5">redroid-03 → 10.0.0.22</text>
|
||||||
|
|
||||||
|
<g stroke="#a371f7" stroke-width="1.3" fill="none">
|
||||||
|
<path d="M 732 198 L 800 198"/><path d="M 732 226 L 800 226"/><path d="M 732 254 L 800 254"/>
|
||||||
|
</g>
|
||||||
|
<text x="808" y="230" fill="#adbac7" font-size="10.5">LAN</text>
|
||||||
|
<text x="790" y="180" fill="#7d8590" font-size="10">directo a la red</text>
|
||||||
|
|
||||||
|
<text x="516" y="298" fill="#adbac7" font-size="11">adb → 10.0.0.20:5555, .21:5555, .22:5555</text>
|
||||||
|
<text x="516" y="320" fill="#3fb950" font-size="10.5">✓ Los dos APKs se ven como pares reales</text>
|
||||||
|
<text x="516" y="336" fill="#3fb950" font-size="10.5">✓ Lo más cerca de "dos móviles en la misma wifi"</text>
|
||||||
|
<text x="516" y="356" fill="#f85149" font-size="10.5">✗ El anfitrión NO habla con sus propios</text>
|
||||||
|
<text x="516" y="371" fill="#f85149" font-size="10.5"> contenedores macvlan → coordinador aparte</text>
|
||||||
|
|
||||||
|
<!-- Aviso -->
|
||||||
|
<rect x="32" y="404" width="896" height="48" rx="6" fill="#161b22" stroke="#f85149" stroke-width="1.5"/>
|
||||||
|
<text x="52" y="424" fill="#f85149" font-size="11.5" font-weight="bold">S1 · adb no tiene autenticación y los contenedores son privilegiados</text>
|
||||||
|
<text x="52" y="442" fill="#7d8590" font-size="10.5">Quien alcance el puerto 5555 acaba siendo root en el blade. En macvlan, bind_ip no aplica: la única defensa es una VLAN aislada.</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.8 KiB |
61
assets/stack-software.svg
Normal file
61
assets/stack-software.svg
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 520" width="960" height="520" font-family="ui-monospace, 'DejaVu Sans Mono', Menlo, monospace">
|
||||||
|
<rect width="960" height="520" fill="#0f1720"/>
|
||||||
|
|
||||||
|
<text x="32" y="42" fill="#e6edf3" font-size="22" font-weight="bold" font-family="system-ui, sans-serif">Stack de software</text>
|
||||||
|
<text x="32" y="65" fill="#7d8590" font-size="12.5">Todo software libre. Sin colecciones externas de Ansible, sin dependencias de pago.</text>
|
||||||
|
|
||||||
|
<!-- Capas -->
|
||||||
|
<rect x="32" y="88" width="560" height="58" rx="6" fill="#1f6feb" fill-opacity="0.18" stroke="#1f6feb" stroke-width="1.5"/>
|
||||||
|
<text x="52" y="114" fill="#79c0ff" font-size="15" font-weight="bold">redroid 13</text>
|
||||||
|
<text x="52" y="134" fill="#adbac7" font-size="11">Android 13 en contenedor · memfd (sin ashmem) · ~2 GB por instancia</text>
|
||||||
|
|
||||||
|
<rect x="32" y="154" width="560" height="52" rx="6" fill="#1c2128" stroke="#444c56" stroke-width="1.5"/>
|
||||||
|
<text x="52" y="180" fill="#e6edf3" font-size="15" font-weight="bold">Docker CE + Compose v2</text>
|
||||||
|
<text x="52" y="198" fill="#7d8590" font-size="11">Repo oficial de Docker · compose generado por plantilla Jinja</text>
|
||||||
|
|
||||||
|
<rect x="32" y="214" width="560" height="66" rx="6" fill="#1c2128" stroke="#f85149" stroke-width="1.5"/>
|
||||||
|
<text x="52" y="240" fill="#f85149" font-size="15" font-weight="bold">binder_linux</text>
|
||||||
|
<text x="52" y="258" fill="#adbac7" font-size="11">devices: binder, hwbinder, vndbinder</text>
|
||||||
|
<text x="52" y="273" fill="#7d8590" font-size="10.5">Debian trae el módulo pero SIN binderfs → hay que cargarlos a mano. Aquí es donde esto se atasca.</text>
|
||||||
|
|
||||||
|
<rect x="32" y="288" width="560" height="52" rx="6" fill="#1c2128" stroke="#a371f7" stroke-width="1.5"/>
|
||||||
|
<text x="52" y="314" fill="#a371f7" font-size="15" font-weight="bold">Debian 12 bookworm</text>
|
||||||
|
<text x="52" y="332" fill="#7d8590" font-size="11">Directo sobre el blade. Sin Proxmox, sin VM, sin LXC anidado.</text>
|
||||||
|
|
||||||
|
<rect x="32" y="348" width="560" height="52" rx="6" fill="#1c2128" stroke="#3fb950" stroke-width="1.5"/>
|
||||||
|
<text x="52" y="374" fill="#3fb950" font-size="15" font-weight="bold">Blade Dell · Fabric A</text>
|
||||||
|
<text x="52" y="392" fill="#7d8590" font-size="11">Ethernet integrada (LOM) → ranuras A1 / A2 del chasis</text>
|
||||||
|
|
||||||
|
<!-- Llave lateral -->
|
||||||
|
<path d="M 604 88 L 616 88 L 616 400 L 604 400" stroke="#30363d" stroke-width="1.5" fill="none"/>
|
||||||
|
<text x="628" y="238" fill="#7d8590" font-size="11">×15 nodos</text>
|
||||||
|
<text x="628" y="254" fill="#7d8590" font-size="11">de carga</text>
|
||||||
|
|
||||||
|
<!-- Panel derecho: orquestación -->
|
||||||
|
<rect x="712" y="88" width="216" height="312" rx="8" fill="#161b22" stroke="#d29922" stroke-width="1.5"/>
|
||||||
|
<text x="730" y="114" fill="#d29922" font-size="14" font-weight="bold" font-family="system-ui, sans-serif">Orquestación</text>
|
||||||
|
|
||||||
|
<text x="730" y="142" fill="#e6edf3" font-size="12" font-weight="bold">Ansible</text>
|
||||||
|
<text x="730" y="160" fill="#7d8590" font-size="10.5">solo ansible.builtin</text>
|
||||||
|
<text x="730" y="176" fill="#7d8590" font-size="10.5">6 roles · 7 playbooks</text>
|
||||||
|
|
||||||
|
<text x="730" y="204" fill="#e6edf3" font-size="12" font-weight="bold">adb sobre TCP</text>
|
||||||
|
<text x="730" y="222" fill="#7d8590" font-size="10.5">del coordinador a</text>
|
||||||
|
<text x="730" y="237" fill="#7d8590" font-size="10.5">toda la flota</text>
|
||||||
|
|
||||||
|
<text x="730" y="265" fill="#e6edf3" font-size="12" font-weight="bold">fleet.sh</text>
|
||||||
|
<text x="730" y="283" fill="#7d8590" font-size="10.5">connect · list · install</text>
|
||||||
|
<text x="730" y="298" fill="#7d8590" font-size="10.5">shell · ip · reboot</text>
|
||||||
|
|
||||||
|
<text x="730" y="326" fill="#e6edf3" font-size="12" font-weight="bold">scrcpy</text>
|
||||||
|
<text x="730" y="344" fill="#7d8590" font-size="10.5">ver y tocar una</text>
|
||||||
|
<text x="730" y="359" fill="#7d8590" font-size="10.5">instancia concreta</text>
|
||||||
|
|
||||||
|
<text x="730" y="386" fill="#484f58" font-size="10.5">GADS · Appium (pendiente)</text>
|
||||||
|
|
||||||
|
<!-- Nota inferior -->
|
||||||
|
<rect x="32" y="418" width="896" height="70" rx="6" fill="#161b22" stroke="#30363d"/>
|
||||||
|
<text x="52" y="442" fill="#e6edf3" font-size="12" font-weight="bold">Lo que este stack NO puede hacer</text>
|
||||||
|
<text x="52" y="462" fill="#7d8590" font-size="11">Ninguna instancia pasa la atestación por hardware: no hay TEE, ni arranque verificado, ni banda base, ni clave de fábrica.</text>
|
||||||
|
<text x="52" y="478" fill="#7d8590" font-size="11">Sirve para probar tus propias apps. Para plataformas con atestación, no — y no es cuestión de potencia. Ver capa_identidad.md</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.5 KiB |
|
|
@ -1,25 +1,23 @@
|
||||||
# Docs
|
# Docs
|
||||||
|
|
||||||
Lo que hay que leer antes de encender nada.
|
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
|---|---|
|
|---|---|
|
||||||
| **[requisitos.md](requisitos.md)** | Qué hace falta: eléctrico, físico, hardware, software, red, accesos y tiempo. Con checklist de bloqueantes. |
|
| [requisitos.md](requisitos.md) | Eléctrico, físico, hardware, red, accesos y tiempo. Checklist de bloqueantes |
|
||||||
| **[costes.md](costes.md)** | Lo que cuesta tenerlo en marcha, por escenario y por dispositivo. La luz es el coste real del proyecto. |
|
| [costes.md](costes.md) | Consumo y coste por escenario y por dispositivo |
|
||||||
| **[seguridad.md](seguridad.md)** | Repaso de seguridad con 11 hallazgos, incluidos los que introduce el código de este proyecto. |
|
| [seguridad.md](seguridad.md) | 11 hallazgos, incluidos los que introduce el código de este proyecto |
|
||||||
|
| [usabilidad.md](usabilidad.md) | Cómo se opera la flota una vez montada |
|
||||||
|
|
||||||
## Las tres conclusiones, en corto
|
## Resumen
|
||||||
|
|
||||||
**Requisitos** — el bloqueante no es técnico: el chasis pide 2,6–3,6 kW, más de lo que tiene
|
**Requisitos.** El bloqueante no es técnico. El chasis pide 2,6–3,6 kW —más de lo que tiene
|
||||||
contratado una vivienda española, y hace 70–85 dB. Sin un sitio con potencia, extracción y
|
contratado una vivienda española—, hace 70–85 dB y su techo térmico continuo son 35 °C. El manual
|
||||||
tolerancia al ruido, la vía es el piloto en el sobremesa.
|
obliga además a las seis fuentes y los nueve ventiladores, se usen 3 blades o 16.
|
||||||
|
|
||||||
**Costes** — la granja completa 24/7 son **~340 €/mes**, unos 4.100 € al año: entre tres y ocho
|
**Costes.** La granja completa 24/7 son ~360 €/mes, unos 4.300 € al año: más de lo que vale el
|
||||||
veces lo que vale el hierro de segunda mano. Encendida **por ventanas** baja a ~56 €/mes. Y con
|
hierro de segunda mano. Por ventanas de 4 h/día baja a ~59 €/mes. Con 8 GB por blade el sobremesa
|
||||||
8 GB por blade, el sobremesa sale más barato por dispositivo que el chasis; solo la ampliación de
|
sale más barato por dispositivo que el chasis; solo la ampliación de RAM invierte eso.
|
||||||
RAM invierte eso.
|
|
||||||
|
|
||||||
**Seguridad** — hay un hallazgo **crítico**: adb no tiene autenticación y los contenedores son
|
**Seguridad.** Un hallazgo crítico: adb no tiene autenticación y los contenedores son
|
||||||
privilegiados, así que quien alcance el puerto 5555 de un blade acaba siendo root en él. Se ha
|
privilegiados, así que quien alcance el puerto 5555 de un blade acaba siendo root en él. Mitigado a
|
||||||
mitigado a medias en el código (`redroid_adb_bind_ip`); lo que lo cierra de verdad es una **VLAN
|
medias con `redroid_adb_bind_ip`; lo cierra una VLAN aislada. Antes de eso, cambiar las
|
||||||
aislada**. Y antes de eso, cambiar las credenciales de fábrica del CMC y de los 16 iDRAC.
|
credenciales de fábrica del CMC y de los 16 iDRAC.
|
||||||
|
|
|
||||||
110
docs/costes.md
110
docs/costes.md
|
|
@ -3,8 +3,8 @@
|
||||||
El hardware ya está. El coste real de este proyecto es **la luz**, y no es pequeño.
|
El hardware ya está. El coste real de este proyecto es **la luz**, y no es pequeño.
|
||||||
|
|
||||||
> **Todas las cifras de consumo son estimaciones.** El M1000e reporta consumo real por chasis y por
|
> **Todas las cifras de consumo son estimaciones.** El M1000e reporta consumo real por chasis y por
|
||||||
> blade desde el CMC — antes de comprometerse con nada, hay que mirar ahí. Es media hora de trabajo
|
> blade desde el CMC (*Chassis → Power Management*) — antes de comprometerse con nada, hay que
|
||||||
> y sustituye todo este documento por datos.
|
> mirar ahí. Es media hora de trabajo y sustituye todo este documento por datos.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -12,12 +12,28 @@ El hardware ya está. El coste real de este proyecto es **la luz**, y no es pequ
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Consumo fijo del chasis | 350 W (ventiladores, CMC, switches, pérdidas de las fuentes) — rango 250–500 W |
|
| **Consumo fijo del chasis** | **500 W** — rango 350–700 W |
|
||||||
| Consumo por blade con Android en marcha | 140 W — rango 100–200 W |
|
| Consumo por blade con Android en marcha | 140 W — rango 100–200 W |
|
||||||
| Precio de la electricidad | **0,18 €/kWh** — rango 0,15–0,22 según tarifa y tramo |
|
| Precio de la electricidad | **0,18 €/kWh** — rango 0,15–0,22 según tarifa y tramo |
|
||||||
| Horas al mes | 730 |
|
| Horas al mes | 730 |
|
||||||
| Reparto | 1 blade coordinador + N de carga × 3 instancias |
|
| Reparto | 1 blade coordinador + N de carga × 3 instancias |
|
||||||
|
|
||||||
|
### De dónde sale el consumo fijo
|
||||||
|
|
||||||
|
El manual del M1000e obliga a tener **las seis fuentes y los nueve ventiladores instalados en todo
|
||||||
|
momento**, se use un blade o dieciséis. Ese suelo lo componen:
|
||||||
|
|
||||||
|
- **9 módulos de ventilador**, con clasificación de 12 V a 5,0–6,3 A cada uno. A régimen moderado,
|
||||||
|
del orden de 150–250 W en conjunto; a plena velocidad, mucho más
|
||||||
|
- **Módulos de I/O** — un switch de fabric consume del orden de 50–150 W, y hay al menos uno
|
||||||
|
- **CMC** (una o dos) e iKVM
|
||||||
|
- **Pérdidas de conversión de las seis fuentes** — el manual da 353 W de disipación máxima por
|
||||||
|
fuente de 2.700 W
|
||||||
|
|
||||||
|
Si los blades resultan ser **M630 y el sitio pasa de 30 °C**, el manual exige activar **ECM**
|
||||||
|
(modo de refrigeración mejorado), que sube el caudal de los ventiladores — y con él, el consumo y
|
||||||
|
el ruido. Ese caso se iría al extremo alto del rango.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Coste mensual por escenario, 24/7
|
## Coste mensual por escenario, 24/7
|
||||||
|
|
@ -25,43 +41,45 @@ El hardware ya está. El coste real de este proyecto es **la luz**, y no es pequ
|
||||||
| Escenario | Blades | Potencia | kWh/mes | **€/mes** | Android | **€/Android/mes** |
|
| Escenario | Blades | Potencia | kWh/mes | **€/mes** | Android | **€/Android/mes** |
|
||||||
|---|---|---|---|---|---|---|
|
|---|---|---|---|---|---|---|
|
||||||
| Solo sobremesa, chasis apagado | 0 | 150 W | 110 | **20 €** | 8 | **2,5 €** |
|
| Solo sobremesa, chasis apagado | 0 | 150 W | 110 | **20 €** | 8 | **2,5 €** |
|
||||||
| Piloto en el chasis | 3 | 770 W | 562 | **101 €** | 6 | **16,9 €** |
|
| Piloto en el chasis | 3 | 920 W | 672 | **121 €** | 6 | **20,2 €** |
|
||||||
| Media granja | 8 | 1.470 W | 1.073 | **193 €** | 21 | **9,2 €** |
|
| Media granja | 8 | 1.620 W | 1.183 | **213 €** | 21 | **10,1 €** |
|
||||||
| Granja completa | 16 | 2.590 W | 1.891 | **340 €** | 45 | **7,6 €** |
|
| Granja completa | 16 | 2.740 W | 2.000 | **360 €** | 45 | **8,0 €** |
|
||||||
| Completa + RAM a 32 GB | 16 | 2.750 W | 2.008 | **361 €** | **210** | **1,7 €** |
|
| Completa + RAM a 32 GB | 16 | 2.900 W | 2.117 | **381 €** | **210** | **1,8 €** |
|
||||||
|
|
||||||
Granja completa 24/7: **~4.100 €/año**.
|
Granja completa 24/7: **~4.300 €/año**.
|
||||||
|
|
||||||
### Tres cosas que dice esta tabla
|
Tres lecturas:
|
||||||
|
|
||||||
**El sobremesa gana al chasis por dispositivo — hasta que se amplíe la RAM.** 2,5 €/Android en el
|
- **El sobremesa gana al chasis por dispositivo** hasta que se amplíe la RAM: 2,5 € contra 8,0 €.
|
||||||
sobremesa contra 7,6 € en el chasis completo. Con 8 GB por blade, encender el M1000e para hacer lo
|
Con 8 GB por blade, encender el M1000e para hacer lo que ya hace el sobremesa es pagar tres veces
|
||||||
que ya hace el sobremesa es pagar tres veces más por dispositivo.
|
más por dispositivo.
|
||||||
|
- **Los pilotos parciales son el peor caso.** El manual obliga a las seis fuentes y los nueve
|
||||||
**Los pilotos en el chasis son el peor negocio de todos.** Los 350 W fijos se pagan igual con 3
|
ventiladores estén los blades que estén, así que el suelo de ~500 W se paga con 3 blades igual
|
||||||
blades que con 16, así que el piloto sale a 16,9 € por Android — casi siete veces el sobremesa. Si
|
que con 16: el piloto sale a 20 € por Android. Si se enciende el chasis, se enciende entero; para
|
||||||
se enciende el chasis, se enciende entero; y para probar, se usa el sobremesa.
|
probar se usa el sobremesa.
|
||||||
|
- **La ampliación de RAM es lo único que cambia la ecuación**: de 8,0 € a 1,8 € por Android con
|
||||||
**La ampliación de RAM es lo único que cambia la ecuación.** De 7,6 € a 1,7 € por Android, por el
|
prácticamente el mismo recibo. No ahorra dinero, multiplica por 4,4 lo que se obtiene por el que
|
||||||
mismo recibo de la luz. No ahorra dinero: multiplica por 4,7 lo que se obtiene por el dinero que ya
|
ya se gasta.
|
||||||
se está gastando.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## El modo que sí sale a cuenta: encendido bajo demanda
|
## El modo que sí sale a cuenta: encendido bajo demanda
|
||||||
|
|
||||||
El CMC permite encender y apagar blades individualmente. Un laboratorio de QA no necesita 45
|
La CMC permite encender y apagar blades individualmente y fijar presupuesto de alimentación. Un
|
||||||
Android a las cuatro de la mañana.
|
laboratorio de QA no necesita 45 Android a las cuatro de la mañana.
|
||||||
|
|
||||||
| Uso | Potencia | kWh/mes | €/mes | €/Android/mes |
|
| Uso | kWh/mes | €/mes | €/Android/mes |
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|
|
||||||
| 24/7 | 2.590 W | 1.891 | 340 € | 7,6 € |
|
| 24/7 | 2.000 | 360 € | 8,0 € |
|
||||||
| **4 h/día** | 2.590 W | 311 | **56 €** | **1,2 €** |
|
| **4 h/día** | 329 | **59 €** | **1,3 €** |
|
||||||
| 8 h/día laborables | 2.590 W | 456 | 82 € | 1,8 € |
|
| 8 h/día laborables | 482 | 87 € | 1,9 € |
|
||||||
|
|
||||||
**Ventanas de prueba en vez de servicio permanente**: el coste cae seis veces y el proyecto pasa de
|
**Ventanas de prueba en vez de servicio permanente**: el coste cae seis veces y el proyecto pasa de
|
||||||
inviable a trivial. Es como debería operarse esto salvo que aparezca una razón para lo contrario.
|
inviable a trivial. Es como debería operarse esto salvo que aparezca una razón para lo contrario.
|
||||||
|
|
||||||
|
Ojo: apagar blades **no ahorra el suelo de ~500 W** si el chasis sigue encendido. El ahorro de
|
||||||
|
verdad es apagar el chasis entero entre ventanas.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Costes de una vez
|
## Costes de una vez
|
||||||
|
|
@ -69,10 +87,12 @@ inviable a trivial. Es como debería operarse esto salvo que aparezca una razón
|
||||||
| Concepto | Coste | Notas |
|
| Concepto | Coste | Notas |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| **RAM 8 → 32 GB × 16 blades** | **320–640 €** | Si son M620 (DDR3 ECC): ~10–20 € el módulo de 16 GB de segunda mano, 2 por blade. Si son M630 (DDR4): 800–1.300 € |
|
| **RAM 8 → 32 GB × 16 blades** | **320–640 €** | Si son M620 (DDR3 ECC): ~10–20 € el módulo de 16 GB de segunda mano, 2 por blade. Si son M630 (DDR4): 800–1.300 € |
|
||||||
|
| **PDU con 6 tomas C19** | 80–250 € | Las fuentes usan **CEI/IEC C20**; los C13 domésticos no valen |
|
||||||
|
| **Magnetotérmico de curva D** | 20–60 € | La irrupción es de **55 A por fuente durante 10 ms**; una curva C salta |
|
||||||
|
| Módulos de relleno para bahías vacías | 5–15 €/ud. | Obligatorios según el manual. Si faltan, se compran |
|
||||||
| SSD por blade, si faltan | ~400 € | 16 × ~25 € |
|
| SSD por blade, si faltan | ~400 € | 16 × ~25 € |
|
||||||
| PDU con tomas C19 + cableado | 50–150 € | Las fuentes del M1000e no usan C13 |
|
|
||||||
| Subida de potencia contratada | 10–50 € | Derecho de cambio, una vez |
|
| Subida de potencia contratada | 10–50 € | Derecho de cambio, una vez |
|
||||||
| **Total realista** | **~400–1.200 €** | Sin contar los SSD si los blades ya tienen disco |
|
| **Total realista** | **~450–1.400 €** | Sin contar los SSD si los blades ya tienen disco |
|
||||||
|
|
||||||
Coste fijo adicional: subir de 3,45 a 6,9 kW contratados añade **~130 €/año** solo en término de
|
Coste fijo adicional: subir de 3,45 a 6,9 kW contratados añade **~130 €/año** solo en término de
|
||||||
potencia, se use o no.
|
potencia, se use o no.
|
||||||
|
|
@ -83,26 +103,23 @@ potencia, se use o no.
|
||||||
|
|
||||||
| Opción | Coste | Cuándo tiene sentido |
|
| Opción | Coste | Cuándo tiene sentido |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| **Sobremesa, 8 Android** | ~20 €/mes | Desarrollo diario y pruebas de `oasis_mobile`. Silencioso, ya encendido. |
|
| **Sobremesa, 8 Android** | ~20 €/mes | Desarrollo diario y pruebas de `oasis_mobile`. Silencioso, ya encendido |
|
||||||
| **Chasis bajo demanda, 45 Android** | ~56 €/mes + 400–1.200 € de entrada | Matrices de prueba grandes, escenarios multi-dispositivo |
|
| **Chasis bajo demanda, 45 Android** | ~59 €/mes + 450–1.400 € de entrada | Matrices de prueba grandes, escenarios multi-dispositivo |
|
||||||
| **Chasis 24/7, 45 Android** | ~340 €/mes | Solo si algo tiene que estar servido permanentemente |
|
| **Chasis 24/7, 45 Android** | ~360 €/mes | Solo si algo tiene que estar servido permanentemente |
|
||||||
| **Device farm en la nube** | ~0,09 €/dispositivo-hora | Uso esporádico. 45 dispositivos 24/7 saldrían por ~2.950 €/mes: diez veces el chasis |
|
| **Device farm en la nube** | ~0,09 €/dispositivo-hora | Uso esporádico. 45 dispositivos 24/7 saldrían por ~2.950 €/mes: ocho veces el chasis |
|
||||||
| **Teléfonos físicos tipo GenFarmer** | 396–1.364 $/dispositivo | Otro producto: son los únicos que pasan atestación de hardware. 45 dispositivos = 17.800–61.400 $ |
|
| **Teléfonos físicos tipo GenFarmer** | 396–1.364 $/dispositivo | Otro producto: son los únicos que pasan atestación de hardware. 45 dispositivos = 17.800–61.400 $ |
|
||||||
|
|
||||||
**El punto de equilibrio con la nube** está en torno al **11 % de utilización**: si cada dispositivo
|
**El punto de equilibrio con la nube** está en torno al **12 % de utilización**: si cada dispositivo
|
||||||
se usa más de ~84 horas al mes, el chasis 24/7 sale más barato. Por debajo, la nube gana. Y por
|
se usa más de ~89 horas al mes, el chasis 24/7 sale más barato. Por debajo, la nube gana. Y por
|
||||||
debajo del 11 %, lo que gana de verdad es encender el chasis solo cuando haga falta.
|
debajo de eso, lo que gana de verdad es encender el chasis solo cuando haga falta.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## El dato incómodo
|
## Hierro contra electricidad
|
||||||
|
|
||||||
Un M1000e con 16 blades vale hoy de segunda mano entre **500 y 1.500 €**.
|
Un M1000e con 16 blades vale hoy de segunda mano entre 500 y 1.500 €. Tenerlo encendido 24/7
|
||||||
|
durante un año cuesta unos 4.300 € de luz: entre tres y nueve veces lo que vale el hardware. No es
|
||||||
Tenerlo encendido 24/7 durante un año cuesta **~4.100 € de luz**.
|
argumento para tirarlo, sino para no dejarlo encendido por defecto.
|
||||||
|
|
||||||
**La electricidad de un año cuesta entre tres y ocho veces lo que vale el hierro.** Eso no es un
|
|
||||||
argumento para tirarlo — es un argumento para no dejarlo encendido por defecto.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -113,7 +130,8 @@ argumento para tirarlo — es un argumento para no dejarlo encendido por defecto
|
||||||
ruido. Ver [ansible/README.md](../02_device_lab/ansible/README.md).
|
ruido. Ver [ansible/README.md](../02_device_lab/ansible/README.md).
|
||||||
3. **Encender el chasis solo con un caso concreto que el sobremesa no cubra** — matriz de versiones
|
3. **Encender el chasis solo con un caso concreto que el sobremesa no cubra** — matriz de versiones
|
||||||
de Android, o el escenario multi-dispositivo de los dos APKs a escala real.
|
de Android, o el escenario multi-dispositivo de los dos APKs a escala real.
|
||||||
4. **Si se enciende, encenderlo entero y por ventanas.** Los 350 W fijos hacen que los pilotos
|
4. **Si se enciende, encenderlo entero y por ventanas.** Las seis fuentes y los nueve ventiladores
|
||||||
parciales sean el peor negocio.
|
son obligatorios por manual: el suelo de ~500 W hace que los pilotos parciales sean el peor
|
||||||
5. **La RAM antes que nada más.** 400 € que multiplican por 4,7 la capacidad sin tocar el recibo.
|
negocio posible.
|
||||||
|
5. **La RAM antes que nada más.** ~400 € que multiplican por 4,4 la capacidad sin tocar el recibo.
|
||||||
Pero primero hay que saber qué blades son — lo dice `playbooks/preflight.yml`.
|
Pero primero hay que saber qué blades son — lo dice `playbooks/preflight.yml`.
|
||||||
|
|
|
||||||
|
|
@ -5,21 +5,44 @@ es lo que descarta el proyecto antes que ninguna consideración técnica.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 1 · Eléctrico y físico — lee esto primero
|
## 1 · Eléctrico y físico
|
||||||
|
|
||||||
|
Datos del *Manual del propietario del M1000e* (Dell, rev. A06, oct. 2019).
|
||||||
|
|
||||||
| Requisito | Detalle |
|
| Requisito | Detalle |
|
||||||
|---|---|
|
|---|---|
|
||||||
| **Potencia contratada** | El chasis completo tira **2,6–3,6 kW**. Un domicilio español típico tiene **3,45 kW contratados**: no da. Hace falta subir a 6,9 kW o más, o un local con suministro trifásico. |
|
| **Potencia contratada** | El chasis completo tira **2,6–3,6 kW**. Un domicilio español típico tiene **3,45 kW contratados**: no da. Hace falta subir a 6,9 kW o más, o un local con suministro trifásico. |
|
||||||
|
| **Fuentes** | **Seis, obligatorias.** El manual: *«El sistema requiere seis fuentes de alimentación para su funcionamiento habitual.»* No es opcional ni escalable. |
|
||||||
|
| **Tensión** | Fuente de 3.000 W: **200–240 V CA, 16 A**. Fuente de 2.700 W: 100–240 V, 16 A. España a 230 V vale. |
|
||||||
|
| **Conectores** | **CEI/IEC C20** — hace falta una **PDU con 6 tomas C19**. Los C13 domésticos no valen. |
|
||||||
|
| **Corriente de irrupción** | **55 A por fuente durante ≤10 ms.** Con seis arrancando a la vez, un magnetotérmico de **curva C salta**: hace falta **curva D** o arranque escalonado. |
|
||||||
| **Circuito** | Dedicado. Nada de compartir con el resto de la instalación. |
|
| **Circuito** | Dedicado. Nada de compartir con el resto de la instalación. |
|
||||||
| **Tensión y conectores** | Dell recomienda **208–240 V** para el M1000e. España a 230 V vale. Fuentes con conectores **C19/C20**, no los C13 normales. |
|
| **Espacio** | **10U** de rack (44,0 × 44,7 × 75,5 cm) |
|
||||||
| **Espacio** | **10U** de rack, con raíles capaces de aguantar el peso. |
|
| **Peso** | **200,5 kg cargado** (44,6 kg vacío). Dato del manual — el spec sheet comercial decía 179 kg y se queda corto. Raíles y suelo tienen que ir sobrados. |
|
||||||
| **Peso** | **179 kg cargado.** El rack tiene que soportarlo y el suelo también. |
|
| **Temperatura** | **10 °C a 35 °C en continuo.** Ampliado a 40 °C solo <10 % de las horas del año, y a 45 °C solo <1 %. |
|
||||||
| **Refrigeración** | 2,6 kW de consumo son 2,6 kW de calor: como dos radiadores eléctricos a tope. Necesita extracción real, no una ventana. |
|
| **Refrigeración** | **Nueve módulos de ventilador, obligatorios los nueve.** 2,6 kW de consumo son 2,6 kW de calor: como dos radiadores eléctricos a tope. Extracción real, no una ventana. |
|
||||||
| **Ruido** | 70–85 dB con los 9 ventiladores en marcha. **No es una máquina de vivienda.** |
|
| **Bahías vacías** | **Todas tapadas con módulo de relleno.** Sin ellos el aire se escapa por el hueco y se degrada la refrigeración del resto. |
|
||||||
|
| **Ruido** | 70–85 dB con los 9 ventiladores. **No es una máquina de vivienda.** |
|
||||||
|
|
||||||
> **Esto es lo que decide.** Si no hay sitio con potencia, extracción y tolerancia al ruido, el
|
> **Esto es lo que decide.** Si no hay sitio con potencia, extracción y tolerancia al ruido, el
|
||||||
> resto de este documento no importa: la vía es el piloto en el sobremesa.
|
> resto de este documento no importa: la vía es el piloto en el sobremesa.
|
||||||
|
|
||||||
|
### Consecuencias
|
||||||
|
|
||||||
|
**Seis fuentes y nueve ventiladores, siempre.** No se puede arrancar el chasis a medias para
|
||||||
|
"probar con tres blades": el coste fijo se paga igual. O entero, o nada — y para probar está el
|
||||||
|
sobremesa.
|
||||||
|
|
||||||
|
**35 °C es el techo continuo.** Una habitación en Madrid en agosto, con 2,6 kW de calor dentro y
|
||||||
|
sin climatización, se pasa de ahí sin dificultad. El rango ampliado cubre menos del 10 % de las
|
||||||
|
horas del año: es margen para incidencias, no una solución.
|
||||||
|
|
||||||
|
### ECM — modo de refrigeración mejorado
|
||||||
|
|
||||||
|
El manual lo exige si los blades son **M630 con CPUs de 120 W o más**, o si el entorno pasa de
|
||||||
|
**30 °C**. Requiere los nueve ventiladores de tercera generación, y significa **más consumo y más
|
||||||
|
ruido**. Depende del modelo de blade, que aún no está confirmado.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2 · Hardware
|
## 2 · Hardware
|
||||||
|
|
@ -29,10 +52,16 @@ es lo que descarta el proyecto antes que ninguna consideración técnica.
|
||||||
Dell PowerEdge M1000e — ver [hardware_m1000e.md](../02_device_lab/hardware_m1000e.md).
|
Dell PowerEdge M1000e — ver [hardware_m1000e.md](../02_device_lab/hardware_m1000e.md).
|
||||||
|
|
||||||
- 16 blades de media altura (8 arriba + 8 abajo)
|
- 16 blades de media altura (8 arriba + 8 abajo)
|
||||||
- Al menos 2 fuentes (mejor 3+3 en redundancia)
|
- **Las 6 fuentes** y **los 9 ventiladores**, más rellenos en toda bahía vacía
|
||||||
- Módulos de I/O FlexIO con conectividad entre blades y hacia la LAN
|
- **Un módulo de I/O en A1** como mínimo (A1 + A2 para redundancia). Fabric A es la Ethernet
|
||||||
|
integrada de los blades, así que **no hacen falta tarjetas intermedias**
|
||||||
- CMC accesible
|
- CMC accesible
|
||||||
|
|
||||||
|
> **Ojo con qué módulo hay en A1/A2.** Un módulo **switch** (M6220, M6348, MXL, M8024-k…) conmuta
|
||||||
|
> entre blades dentro del chasis, que es justo lo que necesita el modo `macvlan`. Un módulo de
|
||||||
|
> **paso a través** saca 16 RJ-45 al exterior y deja la conmutación en manos de un switch externo.
|
||||||
|
> Cambia el montaje de red por completo.
|
||||||
|
|
||||||
### Por blade
|
### Por blade
|
||||||
|
|
||||||
| | Mínimo | Recomendado |
|
| | Mínimo | Recomendado |
|
||||||
|
|
@ -124,9 +153,12 @@ Mantenimiento posterior: 2–4 h al mes.
|
||||||
|
|
||||||
**Bloqueantes** — si alguno falla, el proyecto no sale:
|
**Bloqueantes** — si alguno falla, el proyecto no sale:
|
||||||
|
|
||||||
- [ ] Sitio con potencia suficiente, extracción y tolerancia al ruido
|
- [ ] Sitio con potencia suficiente, extracción y **temperatura por debajo de 35 °C todo el año**
|
||||||
|
- [ ] Tolerancia a 70–85 dB
|
||||||
- [ ] Alguien asume la factura eléctrica (ver [costes.md](costes.md))
|
- [ ] Alguien asume la factura eléctrica (ver [costes.md](costes.md))
|
||||||
- [ ] Rack de 10U que aguante 179 kg
|
- [ ] Rack de 10U que aguante **200,5 kg**
|
||||||
|
- [ ] **PDU con 6 tomas C19** y magnetotérmico de **curva D** (irrupción de 55 A por fuente)
|
||||||
|
- [ ] Las 6 fuentes, los 9 ventiladores y los rellenos, presentes
|
||||||
- [ ] Los blades arrancan y el CMC responde
|
- [ ] Los blades arrancan y el CMC responde
|
||||||
|
|
||||||
**Antes de encender**:
|
**Antes de encender**:
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ Incluye los fallos que introduce el propio código de este proyecto, no solo los
|
||||||
|
|
||||||
## S1 · adb sin autenticación sobre contenedor privilegiado — **crítico**
|
## S1 · adb sin autenticación sobre contenedor privilegiado — **crítico**
|
||||||
|
|
||||||
El fallo más serio, y es una cadena de tres eslabones que por separado parecen asumibles:
|
Una cadena de tres eslabones que por separado parecen asumibles:
|
||||||
|
|
||||||
1. **adb no tiene autenticación** cuando escucha en TCP. Quien llega al puerto, entra.
|
1. **adb no tiene autenticación** cuando escucha en TCP. Quien llega al puerto, entra.
|
||||||
2. **Las imágenes de redroid son `userdebug`**, así que `adb root` funciona: shell de root dentro
|
2. **Las imágenes de redroid son `userdebug`**, así que `adb root` funciona: shell de root dentro
|
||||||
|
|
@ -33,19 +33,17 @@ El fallo más serio, y es una cadena de tres eslabones que por separado parecen
|
||||||
3. **El contenedor es `privileged: true`** — redroid lo exige para acceder a binder. Un privilegiado
|
3. **El contenedor es `privileged: true`** — redroid lo exige para acceder a binder. Un privilegiado
|
||||||
ve los devices del anfitrión y puede montar su sistema de ficheros.
|
ve los devices del anfitrión y puede montar su sistema de ficheros.
|
||||||
|
|
||||||
Encadenado: **cualquiera que alcance el puerto 5555 de un blade acaba siendo root en ese blade.**
|
Encadenado: cualquiera que alcance el puerto 5555 de un blade acaba siendo root en ese blade, sin
|
||||||
No hace falta ningún exploit, solo `adb connect`.
|
exploit, solo con `adb connect`. Con 45 dispositivos son 45 puertas.
|
||||||
|
|
||||||
Y con 45 dispositivos son 45 puertas.
|
Corregido en parte: el compose ataba adb a `0.0.0.0`. Ahora hay `redroid_adb_bind_ip`, que permite
|
||||||
|
atarlo solo a la interfaz interna del chasis:
|
||||||
**Qué se ha corregido hoy.** El compose ataba adb a `0.0.0.0` — todas las interfaces. Ahora hay
|
|
||||||
`redroid_adb_bind_ip`, así que se puede atar solo a la interfaz interna del chasis:
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
blade-02: { ansible_host: 10.0.0.12, redroid_adb_bind_ip: 10.0.0.12 }
|
blade-02: { ansible_host: 10.0.0.12, redroid_adb_bind_ip: 10.0.0.12 }
|
||||||
```
|
```
|
||||||
|
|
||||||
**Qué falta, y es lo que de verdad cierra el agujero:**
|
**Lo que cierra el agujero:**
|
||||||
|
|
||||||
- **Red de laboratorio aislada.** VLAN propia para la granja, sin ruta hacia la LAN de casa ni
|
- **Red de laboratorio aislada.** VLAN propia para la granja, sin ruta hacia la LAN de casa ni
|
||||||
hacia internet salvo lo imprescindible. Es la medida que importa; el resto son parches.
|
hacia internet salvo lo imprescindible. Es la medida que importa; el resto son parches.
|
||||||
|
|
@ -84,7 +82,7 @@ cada Android **con IP real en la red**, cada uno con S1 encima.
|
||||||
|
|
||||||
- VLAN dedicada para la granja, con el coordinador como único puente.
|
- VLAN dedicada para la granja, con el coordinador como único puente.
|
||||||
- Reservar el rango de IPs en el DHCP, o habrá colisiones con máquinas reales.
|
- Reservar el rango de IPs en el DHCP, o habrá colisiones con máquinas reales.
|
||||||
- No usar la LAN de casa. Nunca.
|
- No usar la LAN doméstica.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
168
docs/usabilidad.md
Normal file
168
docs/usabilidad.md
Normal file
|
|
@ -0,0 +1,168 @@
|
||||||
|
# Usabilidad
|
||||||
|
|
||||||
|
Cómo se trabaja con esto en el día a día. No la instalación —eso está en
|
||||||
|
[ansible/README.md](../02_device_lab/ansible/README.md)— sino **cómo se usa una vez montado**, y
|
||||||
|
qué decisiones de diseño hacen que sea llevadero o insufrible.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Un solo punto de control
|
||||||
|
|
||||||
|
45 dispositivos son ingobernables si hay que entrar a cada blade. Por eso **todo pasa por el
|
||||||
|
coordinador**:
|
||||||
|
|
||||||
|
```
|
||||||
|
tú coordinador 45 Android
|
||||||
|
┌────┐ ssh ┌──────────────────┐ adb ┌───┬───┬───┐
|
||||||
|
│ │ ──────────► │ fleet · adb │ ─────────► │ · │ · │ · │
|
||||||
|
└────┘ │ devices.txt │ └───┴───┴───┘
|
||||||
|
└──────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
`devices.txt` lo genera Ansible a partir del inventario y de la RAM real de cada blade. Nunca se
|
||||||
|
edita a mano: si cambia la flota, se relanza `playbooks/coordinator.yml` y se regenera.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Órdenes
|
||||||
|
|
||||||
|
```bash
|
||||||
|
fleet connect # conecta adb a toda la flota
|
||||||
|
fleet list # qué hay conectado, y cuántos faltan
|
||||||
|
fleet install app.apk # instala en todos
|
||||||
|
fleet shell '<cmd>' # ejecuta en todos
|
||||||
|
fleet ip # IP de cada Android
|
||||||
|
fleet reboot # reinicia todo
|
||||||
|
```
|
||||||
|
|
||||||
|
Todas son **idempotentes o inocuas**. `connect` se puede lanzar mil veces. Ninguna borra nada.
|
||||||
|
La única destructiva del proyecto es `playbooks/destroy.yml`, y exige `-e confirmar=si`.
|
||||||
|
|
||||||
|
### Por qué `fleet list` dice "declarados" y "conectados"
|
||||||
|
|
||||||
|
```
|
||||||
|
declarados: 45 · conectados: 43
|
||||||
|
```
|
||||||
|
|
||||||
|
Esa resta es el diagnóstico más útil del sistema. Si no cuadra, hay dos contenedores caídos y se
|
||||||
|
sabe al instante, sin mirar 15 blades. El siguiente paso es `playbooks/status.yml`, que dice en
|
||||||
|
qué nodo.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Flujos de trabajo reales
|
||||||
|
|
||||||
|
### Probar una APK nueva en toda la flota
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible-playbook playbooks/apk.yml -e apk_local_path=~/oasis-0.9.1.apk
|
||||||
|
```
|
||||||
|
|
||||||
|
Un solo comando desde el portátil: copia el APK al coordinador, conecta la flota e instala en los
|
||||||
|
45. Sale un recuento de `ok` / `FALLO` por dispositivo.
|
||||||
|
|
||||||
|
### El caso de los dos APKs que se tienen que ver
|
||||||
|
|
||||||
|
Es el que motivó el proyecto. Con `redroid_network_mode: macvlan`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
fleet ip # cada Android con su IP real de LAN
|
||||||
|
fleet install oasis-A.apk # ...o instalar distinto en cada mitad
|
||||||
|
adb -s 10.0.0.20:5555 install oasis-B.apk
|
||||||
|
```
|
||||||
|
|
||||||
|
Los dos se ven como **pares de red de verdad**, no a través de traducciones. Es lo más cerca de
|
||||||
|
"dos móviles en la misma wifi" sin tener dos móviles.
|
||||||
|
|
||||||
|
### Mirar una instancia concreta
|
||||||
|
|
||||||
|
```bash
|
||||||
|
scrcpy -s 10.0.0.20:5555
|
||||||
|
```
|
||||||
|
|
||||||
|
Ventana con la pantalla del Android, ratón y teclado. Para depurar algo visual no hay nada mejor.
|
||||||
|
|
||||||
|
### Comprobar una propiedad en toda la flota
|
||||||
|
|
||||||
|
```bash
|
||||||
|
fleet shell 'getprop ro.build.version.release'
|
||||||
|
fleet shell 'pm list packages | grep oasis'
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Decisiones de diseño
|
||||||
|
|
||||||
|
| Decisión | Por qué |
|
||||||
|
|---|---|
|
||||||
|
| **Preflight de solo lectura** | Se puede lanzar contra hardware ajeno sin miedo. Contesta "¿qué hay aquí y sirve?" sin tocar nada |
|
||||||
|
| **Instancias automáticas por RAM** | No hay que calcular ni mantener un número por blade. Se amplía la RAM y el siguiente despliegue se ajusta solo |
|
||||||
|
| **`fleet` en el PATH** | `fleet list`, no `/opt/granja/fleet.sh list` |
|
||||||
|
| **Playbooks pequeños y con nombre obvio** | `preflight`, `provision`, `devices`, `apk`, `status`, `destroy`. Se adivina cuál usar |
|
||||||
|
| **Todo relanzable** | `site.yml` es idempotente. Ante la duda, se relanza |
|
||||||
|
| **Errores que dicen qué hacer** | El fallo de binder no dice "error": dice que el módulo estaba en uso, que la config persistente ya está escrita y que basta reiniciar ese blade |
|
||||||
|
| **`destroy.yml` conserva los datos** | Borrar `/data` exige un segundo flag. Lo destructivo nunca es el camino por defecto |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Problemas conocidos
|
||||||
|
|
||||||
|
Ordenados por probabilidad. Están documentados porque son inevitables, no porque sean fallos.
|
||||||
|
|
||||||
|
### 1 · Binder, la primera vez
|
||||||
|
|
||||||
|
**Síntoma**: el playbook falla con "faltan devices binder tras el modprobe".
|
||||||
|
|
||||||
|
**Causa**: el módulo ya estaba cargado y en uso, así que no se pudo recargar con los parámetros
|
||||||
|
nuevos.
|
||||||
|
|
||||||
|
**Solución**: la configuración persistente ya quedó escrita. Reinicia ese blade y relanza. Pasa una
|
||||||
|
sola vez por máquina.
|
||||||
|
|
||||||
|
### 2 · macvlan: el anfitrión no ve a sus propios contenedores
|
||||||
|
|
||||||
|
**Síntoma**: adb desde un blade no encuentra los Android de ese mismo blade.
|
||||||
|
|
||||||
|
**Causa**: limitación del driver macvlan, no un error de configuración.
|
||||||
|
|
||||||
|
**Solución**: no es un problema en este diseño — el coordinador es un blade **distinto** y desde
|
||||||
|
fuera sí se llega. Por eso `apk.yml` se ejecuta siempre desde el coordinador. Si algún día montas
|
||||||
|
adb en un nodo de carga, es esto.
|
||||||
|
|
||||||
|
### 3 · El primer arranque de redroid tarda
|
||||||
|
|
||||||
|
**Síntoma**: `fleet connect` falla justo después de `site.yml`.
|
||||||
|
|
||||||
|
**Causa**: un Android recién creado tarda en levantar por primera vez, sobre todo con render por
|
||||||
|
software y 45 a la vez.
|
||||||
|
|
||||||
|
**Solución**: esperar y reintentar. `fleet connect` es inocuo y se puede repetir.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Ergonomía del hardware
|
||||||
|
|
||||||
|
Cosas que no son software pero deciden si esto se usa o se abandona:
|
||||||
|
|
||||||
|
**El ruido manda.** 70–85 dB significa que no se puede estar en la misma habitación sin protección.
|
||||||
|
Todo el trabajo tiene que ser remoto — de ahí que no haya nada en el diseño que exija tocar el
|
||||||
|
chasis en marcha.
|
||||||
|
|
||||||
|
**El LCD frontal es el mejor amigo en el arranque.** Configura la red de la CMC con su asistente,
|
||||||
|
sin cable serie ni portátil enganchado. Es el camino corto la primera vez.
|
||||||
|
|
||||||
|
**Encender por ventanas cambia el hábito.** Si el chasis no está siempre en marcha (y no debería,
|
||||||
|
ver [costes.md](costes.md)), el flujo pasa a ser: encender → esperar arranque → `fleet connect` →
|
||||||
|
trabajar → apagar. Merece la pena tener eso en un script y no en la cabeza.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pendiente
|
||||||
|
|
||||||
|
- **GADS** — UI web con la flota, vista de pantallas y Appium integrado. Es el salto de calidad
|
||||||
|
cuando se pasa de una decena de dispositivos. No está automatizado a propósito: montar un
|
||||||
|
despliegue de Node sin poder probarlo sería complejidad sin verificar
|
||||||
|
- **Script de encendido/apagado por ventanas** contra la CMC vía RACADM
|
||||||
|
- **`fleet watch`** — un panel de estado que se refresque solo
|
||||||
|
- **Registro de auditoría en `fleet`** — hoy no deja rastro de quién hizo qué (hallazgo S10 en
|
||||||
|
[seguridad.md](seguridad.md))
|
||||||
Loading…
Add table
Add a link
Reference in a new issue