feat: adicionar drbit-new-client.sh (espelho do repo Dashboard)

This commit is contained in:
drbit-admin 2026-06-12 15:32:21 -03:00
commit ea90025ff8

271
drbit-new-client.sh Executable file
View file

@ -0,0 +1,271 @@
#!/usr/bin/env bash
#
# drbit-new-client.sh — provisiona uma VM nova para um cliente DRBIT
#
# Roda no shell do HOST PROXMOX. Não depende de nenhuma VM/template
# pré-existente: baixa a imagem cloud oficial do Ubuntu 24.04, cria a VM
# do zero (qm create + qm importdisk) e anexa um drive de cloud-init que,
# no primeiro boot, clona o repo da intranet e roda install.sh.
#
# Ver wiki/projetos/intranet/provisionamento-novo-cliente.md para o
# contexto arquitetural completo.
#
# Uso:
# ./drbit-new-client.sh --nome ecp [--ip 192.168.1.80 --gw 192.168.1.1] [opções]
#
# Por padrão a VM sobe com DHCP (igual ao modelo community-scripts — fica a
# critério de quem provisiona definir IP fixo depois). Se --ip for informado,
# a VM já sobe com IP estático.
#
# ⚠️ Para clientes que vão virar Domínio AD (Samba 4 AD DC), o IP PRECISA
# ser fixo — defina --ip/--gw aqui, ou configure manualmente depois via
# netplan (ver wiki/infraestrutura/template-vm.md) antes do Setup Wizard
# provisionar o AD.
#
# Opções:
# --nome <slug> obrigatório — vira hostname srv-<slug> e nome da VM
# --ip <ip> opcional — IP estático da VM (ex: 192.168.1.80). Sem isso, usa DHCP
# --gw <gateway> default: 192.168.1.1 (só usado com --ip)
# --vmid <id> default: próximo livre (pvesh get /cluster/nextid)
# --cores <n> default: 2
# --ram <mb> default: 2048
# --disk <gb> default: 32
# --bridge <nome> default: vmbr0
# --storage <nome> default: local-lvm
# --ssh-key <path> default: ~/.ssh/id_drbit_lab.pub
# --repo-url <url> default: https://git.drbit.tec.br/drbit/Dashboard.git
# Repo privado — passe a URL com o token de provisionamento
# embutido (usuário drbit-provisioning, token read-only):
# https://drbit-provisioning:<token>@git.drbit.tec.br/drbit/Dashboard.git
#
set -euo pipefail
# ── defaults ──────────────────────────────────────────────────────────────
GW="192.168.1.1"
VMID=""
CORES=2
RAM=2048
DISK=32
BRIDGE="vmbr0"
STORAGE="local-lvm"
SSH_KEY_FILE="$HOME/.ssh/id_drbit_lab.pub"
UBUNTU_RELEASE="noble"
IMG_URL="https://cloud-images.ubuntu.com/releases/${UBUNTU_RELEASE}/release/ubuntu-24.04-server-cloudimg-amd64.img"
IMG_CACHE="/var/lib/vz/template/iso/ubuntu-24.04-server-cloudimg-amd64.img"
REPO_URL="https://git.drbit.tec.br/drbit/Dashboard.git"
NOME=""
IP=""
# ── helpers ───────────────────────────────────────────────────────────────
msg_info() { echo -e " \033[1;34m➜\033[0m $*"; }
msg_ok() { echo -e " \033[1;32m✓\033[0m $*"; }
msg_error() { echo -e " \033[1;31m✗\033[0m $*" >&2; }
# ── parse args ────────────────────────────────────────────────────────────
while [[ $# -gt 0 ]]; do
case "$1" in
--nome) NOME="$2"; shift 2 ;;
--ip) IP="$2"; shift 2 ;;
--gw) GW="$2"; shift 2 ;;
--vmid) VMID="$2"; shift 2 ;;
--cores) CORES="$2"; shift 2 ;;
--ram) RAM="$2"; shift 2 ;;
--disk) DISK="$2"; shift 2 ;;
--bridge) BRIDGE="$2"; shift 2 ;;
--storage) STORAGE="$2"; shift 2 ;;
--ssh-key) SSH_KEY_FILE="$2"; shift 2 ;;
--repo-url) REPO_URL="$2"; shift 2 ;;
*) msg_error "Argumento desconhecido: $1"; exit 1 ;;
esac
done
# ── validações ────────────────────────────────────────────────────────────
if [[ -z "$NOME" ]]; then
msg_error "Uso: $0 --nome <slug> [--ip <ip> --gw <gateway>] [opções]"
exit 1
fi
if ! command -v qm &>/dev/null; then
msg_error "Comando 'qm' não encontrado — este script roda no host Proxmox."
exit 1
fi
if [[ ! -f "$SSH_KEY_FILE" ]]; then
msg_error "Chave pública SSH não encontrada em: $SSH_KEY_FILE (use --ssh-key)"
exit 1
fi
HOSTNAME="srv-${NOME}"
if [[ -z "$VMID" ]]; then
VMID=$(pvesh get /cluster/nextid)
fi
if [[ -n "$IP" ]]; then
msg_info "Provisionando VM '$HOSTNAME' (VMID $VMID, IP estático $IP)"
else
msg_info "Provisionando VM '$HOSTNAME' (VMID $VMID, IP via DHCP)"
fi
# ── 1. cache da imagem cloud oficial ─────────────────────────────────────
if [[ -f "$IMG_CACHE" ]]; then
msg_ok "Imagem Ubuntu 24.04 cloud já em cache: $IMG_CACHE"
else
msg_info "Baixando imagem Ubuntu 24.04 cloud (cloud-images.ubuntu.com)..."
mkdir -p "$(dirname "$IMG_CACHE")"
curl -fsSL -o "$IMG_CACHE" "$IMG_URL"
msg_ok "Imagem baixada: $IMG_CACHE"
fi
# ── 2. garantir que a storage 'local' suporta snippets ───────────────────
CONTENT=$(awk '/^dir: local$/{f=1; next} f && /^\tcontent/ {print $2; exit} /^[a-z]/{f=0}' /etc/pve/storage.cfg)
if [[ "$CONTENT" != *snippets* ]]; then
msg_info "Habilitando 'snippets' na storage local..."
pvesm set local --content "${CONTENT},snippets"
msg_ok "Storage 'local' agora aceita snippets"
else
msg_ok "Storage 'local' já aceita snippets"
fi
# ── 3. gerar cloud-init user-data ────────────────────────────────────────
SSH_PUBKEY=$(cat "$SSH_KEY_FILE")
SNIPPET_PATH="/var/lib/vz/snippets/drbit-${VMID}.yaml"
mkdir -p /var/lib/vz/snippets
msg_info "Gerando cloud-init user-data ($SNIPPET_PATH)..."
cat > "$SNIPPET_PATH" <<EOF
#cloud-config
hostname: ${HOSTNAME}
manage_etc_hosts: true
users:
- name: drbit
sudo: ALL=(ALL) NOPASSWD:ALL
shell: /bin/bash
ssh_authorized_keys:
- ${SSH_PUBKEY}
chpasswd:
list: |
drbit:b1tadmin
expire: false
package_update: true
packages:
- git
runcmd:
- until getent hosts git.drbit.tec.br >/dev/null 2>&1; do sleep 5; done
- git clone ${REPO_URL} /opt/drbit-intranet
- bash /opt/drbit-intranet/install.sh
EOF
msg_ok "user-data gerado"
# ── 4. criar VM ───────────────────────────────────────────────────────────
msg_info "Criando VM $VMID..."
qm create "$VMID" \
-name "$HOSTNAME" \
-memory "$RAM" \
-cores "$CORES" \
-net0 "virtio,bridge=${BRIDGE}" \
-ostype l26 \
-scsihw virtio-scsi-pci \
-agent 1
msg_ok "VM criada"
# ── 5. importar disco ────────────────────────────────────────────────────
msg_info "Importando imagem como disco..."
qm importdisk "$VMID" "$IMG_CACHE" "$STORAGE"
# o disco importado fica como "unused0" na config da VM
DISK_REF=$(qm config "$VMID" | grep -oP '^unused0:\s*\K.*')
if [[ -z "$DISK_REF" ]]; then
msg_error "Não foi possível identificar o disco importado (unused0 não encontrado)."
qm config "$VMID"
exit 1
fi
msg_info "Anexando disco ($DISK_REF)..."
qm set "$VMID" -scsi0 "$DISK_REF"
msg_ok "Disco anexado"
msg_info "Redimensionando disco para ${DISK}G..."
qm resize "$VMID" scsi0 "${DISK}G"
msg_ok "Disco redimensionado (cloud-init faz growpart/resizefs no primeiro boot)"
# ── 6. cloud-init drive + boot + rede ────────────────────────────────────
if [[ -n "$IP" ]]; then
IPCONFIG="ip=${IP}/24,gw=${GW}"
msg_info "Configurando cloud-init e rede (IP estático ${IP}/24, gw ${GW})..."
else
IPCONFIG="ip=dhcp"
msg_info "Configurando cloud-init e rede (DHCP)..."
fi
qm set "$VMID" \
-ide2 "${STORAGE}:cloudinit" \
-boot order=scsi0 \
-serial0 socket -vga serial0 \
-ipconfig0 "$IPCONFIG" \
-nameserver "1.1.1.1 8.8.8.8" \
-cicustom "user=local:snippets/drbit-${VMID}.yaml"
msg_ok "Cloud-init configurado"
# ── 7. iniciar ────────────────────────────────────────────────────────────
msg_info "Iniciando VM..."
qm start "$VMID"
msg_ok "VM iniciada"
# ── 8. descobrir IP (DHCP) e aguardar Setup Wizard responder ─────────────
FINAL_IP="$IP"
if [[ -z "$FINAL_IP" ]]; then
msg_info "Aguardando guest agent informar o IP (DHCP, até 5min)..."
DEADLINE=$((SECONDS + 300))
while (( SECONDS < DEADLINE )); do
FINAL_IP=$(qm guest cmd "$VMID" network-get-interfaces 2>/dev/null \
| grep -oP '"ip-address"\s*:\s*"\K[0-9.]+' \
| grep -vE '^(127\.|169\.254\.)' \
| head -1 || true)
[[ -n "$FINAL_IP" ]] && break
sleep 10
done
if [[ -z "$FINAL_IP" ]]; then
msg_error "Não foi possível descobrir o IP via guest agent. Verifique com: qm guest cmd $VMID network-get-interfaces"
exit 1
fi
msg_ok "IP detectado via DHCP: $FINAL_IP"
fi
msg_info "Aguardando o Setup Wizard subir em http://${FINAL_IP}/setup (até 10min)..."
DEADLINE=$((SECONDS + 600))
while (( SECONDS < DEADLINE )); do
if curl -sf -o /dev/null "http://${FINAL_IP}/setup"; then
msg_ok "Setup Wizard respondendo!"
break
fi
sleep 10
done
if ! curl -sf -o /dev/null "http://${FINAL_IP}/setup"; then
msg_error "Timeout aguardando o Setup Wizard. Verifique a VM (qm terminal $VMID) e o cloud-init (/var/log/cloud-init-output.log)."
exit 1
fi
# ── 9. resumo ─────────────────────────────────────────────────────────────
echo ""
echo "──────────────────────────────────────────"
echo " VM $VMID ($HOSTNAME) pronta!"
echo ""
echo " Acesse o Setup Wizard:"
echo " http://${FINAL_IP}/setup"
echo ""
echo " SSH: ssh drbit@${FINAL_IP} (chave $SSH_KEY_FILE ou senha b1tadmin)"
echo " ⚠️ Trocar a senha padrão 'b1tadmin' em produção."
if [[ -z "$IP" ]]; then
echo ""
echo " ⚠️ IP via DHCP ($FINAL_IP). Para Domínio AD (Samba 4 AD DC), defina"
echo " IP fixo antes de provisionar o AD pelo Setup Wizard:"
echo " editar /etc/netplan/50-cloud-init.yaml (ou criar 99-static.yaml)"
echo " → sudo netplan apply"
fi
echo "──────────────────────────────────────────"