Skip to content

lablink_allocator_service.client_session

Per-session preparation: rotate the VNC password on the assigned client and persist per-session state on the clients row.

Called from /api/request_vm inside the seat-assignment transaction so rotation failure rolls back the assignment.

Bases: RuntimeError

Raised when the per-session password rotation cannot be completed.

Rotate the assigned client's VNC password and persist per-session columns on the VM row. Must be called inside the seat-assignment transaction so failures roll back.

agent_token is the deployment agent-control token (main.AGENT_TOKEN); the client agent receives the same value as its AGENT_TOKEN env via the OpenTofu user_data and validates it on every /api/session/start call. Passed explicitly rather than read from env so this function has no hidden global dependency for tests.

fallback_fn is an optional callable (hostname: str) -> str that resolves the private IP when no stored LAN IP is found in the database. Provider-specific connectivity strategies supply this (e.g. AllocatorProxiedClientConnectivity passes an EC2 tag lookup). When omitted and no stored IP exists, :exc:RotationFailed is raised.

Source code in packages/allocator/src/lablink_allocator_service/client_session.py
def prepare_browser_session(
    *,
    database,
    hostname: str,
    session_id: uuid.UUID,
    browser_token: str,
    agent_token: str,
    fallback_fn: Callable[[str], str] | None = None,
) -> BrowserSessionTarget:
    """Rotate the assigned client's VNC password and persist per-session
    columns on the VM row. Must be called inside the seat-assignment
    transaction so failures roll back.

    `agent_token` is the deployment agent-control token (`main.AGENT_TOKEN`);
    the client agent receives the same value as its AGENT_TOKEN env via the
    OpenTofu user_data and validates it on every /api/session/start call.
    Passed explicitly rather than read from env so this function has no
    hidden global dependency for tests.

    `fallback_fn` is an optional callable ``(hostname: str) -> str`` that
    resolves the private IP when no stored LAN IP is found in the database.
    Provider-specific connectivity strategies supply this (e.g.
    ``AllocatorProxiedClientConnectivity`` passes an EC2 tag lookup).
    When omitted and no stored IP exists, :exc:`RotationFailed` is raised.
    """
    private_ip = _lookup_private_ip(hostname, database, fallback_fn=fallback_fn)
    password = secrets.token_urlsafe(24)
    upstream = f"{private_ip}:6080"

    # Body shape matches the agent's contract (packages/client/.../agent/api.py):
    # a single `password` field. session_id and browser_token are bookkeeping
    # the *allocator* persists in its own DB; the agent doesn't need either.
    _post_rotate(
        f"http://{private_ip}:7070/api/session/start",
        {"password": password},
        bearer=agent_token,
    )

    ws_url = f"proxy/{browser_token}"
    with database._cursor as cursor:
        cursor.execute(
            f"UPDATE {database.table_name} "
            f"SET sessionid = %s, "
            f"    browsertoken = %s, "
            f"    vncpassword = %s, "
            f"    upstream = %s, "
            f"    browser_ws_url = %s, "
            f"    browser_credential = NULL, "
            f"    sessionstartedat = NOW() "
            f"WHERE hostname = %s",
            (str(session_id), browser_token, password, upstream,
             ws_url, hostname),
        )

    return BrowserSessionTarget(ws_url=ws_url, browser_credential=None)