/**
 * CIDR IP allocator for Firecracker VM networking.
 *
 * Two implementations behind a shared interface:
 *
 * - `DbIpAllocator` — persists allocations to PostgreSQL. Used by
 *   coordinators where the cluster Postgres is reachable. Allocations
 *   survive orchestrator restarts so a long-lived VM keeps its IP across
 *   coord bounces.
 *
 * - `InMemoryIpAllocator` — Map-backed, no persistence. Used by worker
 *   peers where the cluster DB is not reachable. The firecracker backend's
 *   existing `cleanupOrphans()` Pass-2/Pass-3 walks the jailer chroot
 *   tree + host TAP devices on every spawn and during the leak sweep, so
 *   any worker-orch restart starts the allocator empty and the next
 *   cleanup pass reaps the leftover chroots and TAPs naturally — no
 *   recovery state needs to live in the allocator itself.
 *
 * Each orch has its own bridge with its own subnet (coord A: `kici`,
 * coord B: `kici_b`, Pi worker: `kici-br0`), so allocator state is
 * per-orch by design. No two orchs share an IP space.
 */
import type { Kysely } from 'kysely';
import type { Database } from '../db/types.js';
/**
 * Result of a successful IP allocation.
 */
export interface IpAllocationResult {
    /** Allocated IP address */
    ip: string;
    /** Gateway IP for guest networking */
    gateway: string;
    /** Subnet mask for guest networking */
    netmask: string;
    /** Deterministic MAC address derived from IP */
    mac: string;
    /** TAP device name on the host */
    tapDevice: string;
}
/**
 * Parsed CIDR range.
 */
export interface CidrRange {
    /** Network address as a 32-bit number */
    networkAddress: number;
    /** Prefix length (e.g. 24 for /24) */
    prefixLength: number;
    /** First usable IP (network address + 1) as a 32-bit number */
    startIp: number;
    /** Last usable IP (broadcast - 1) as a 32-bit number */
    endIp: number;
}
/**
 * Parse an IPv4 address string to a 32-bit unsigned integer.
 */
export declare function ipToNumber(ip: string): number;
/**
 * Convert a 32-bit unsigned integer back to an IPv4 address string.
 */
export declare function numberToIp(n: number): string;
/**
 * Parse a CIDR notation string into a CidrRange.
 *
 * @example parseCidr('10.0.0.0/24')
 * // => { networkAddress: 167772160, prefixLength: 24, startIp: 167772161, endIp: 167772414 }
 */
export declare function parseCidr(cidr: string): CidrRange;
/**
 * Generate a deterministic MAC address from an IP address.
 *
 * Uses the locally-administered unicast prefix 06:00:AC followed by
 * the last 3 octets of the IP address encoded as hex.
 *
 * @example generateMac('10.0.0.5')  // => '06:00:AC:00:00:05'
 * @example generateMac('10.0.1.42') // => '06:00:AC:00:01:2A'
 */
export declare function generateMac(ip: string): string;
/**
 * Generate a TAP device name from a VM ID.
 * Linux interface names are limited to 15 characters (IFNAMSIZ).
 * Format: kici-XXXXXXXX (5 + 8 = 13 chars, well within limit).
 *
 * Uses the LAST 8 characters of the vmId to avoid collisions.
 * VM IDs have format "scaler-firecracker-XXXXXXXX" where the unique
 * random suffix is at the end. Using slice(0, 8) would always produce
 * "scaler-f" for all Firecracker VMs.
 */
export declare function generateTapName(vmId: string): string;
/**
 * Shape of one row returned by `IpAllocator.getAllocations()` /
 * `getAllocationForVm()`. Matches the `ip_allocations` table columns so
 * the firecracker-backend's `cleanupOrphans()` can read both impls
 * uniformly.
 */
export interface IpAllocationRecord {
    ip: string;
    vm_id: string;
    scaler_name: string;
    tap_device: string;
    mac_address: string;
}
/**
 * Per-orch CIDR IP allocator interface.
 *
 * Two implementations: `DbIpAllocator` (Postgres, coordinator) and
 * `InMemoryIpAllocator` (Map-backed, worker). The firecracker-backend
 * depends only on this interface — never on the concrete class — so a
 * single backend implementation works in both deploy modes.
 */
export interface IpAllocator {
    allocate(vmId: string, scalerName: string): Promise<IpAllocationResult>;
    release(vmId: string): Promise<void>;
    releaseByIp(ip: string): Promise<void>;
    getAllocations(): Promise<IpAllocationRecord[]>;
    getAllocationForVm(vmId: string): Promise<IpAllocationRecord | null>;
}
/**
 * DB-backed CIDR IP allocator.
 *
 * Allocates IPs from a configurable range, skipping the gateway.
 * All allocations are persisted in PostgreSQL — used by coordinators
 * where the cluster DB is reachable. Allocations survive orch restarts
 * so a long-lived VM keeps its IP across coord bounces.
 */
export declare class DbIpAllocator implements IpAllocator {
    private readonly db;
    private readonly range;
    private readonly gateway;
    private readonly gatewayNum;
    private readonly netmask;
    constructor(opts: {
        db: Kysely<Database>;
        cidr: string;
        gateway: string;
        netmask: string;
    });
    allocate(vmId: string, scalerName: string): Promise<IpAllocationResult>;
    release(vmId: string): Promise<void>;
    releaseByIp(ip: string): Promise<void>;
    getAllocations(): Promise<IpAllocationRecord[]>;
    getAllocationForVm(vmId: string): Promise<IpAllocationRecord | null>;
}
/**
 * In-memory CIDR IP allocator.
 *
 * Used by worker peers where the cluster Postgres is not reachable. State
 * lives in a `Map<vmId, IpAllocationRecord>` for the lifetime of the
 * orch process; on restart the allocator starts empty and the
 * firecracker-backend's existing `cleanupOrphans()` Pass-2/Pass-3 walks
 * the jailer chroot tree + host TAP devices (matching `VM_TAP_PATTERN`)
 * to reap any leftover state. No persistence and no chroot recovery
 * inside the allocator — the filesystem is the source of truth, and the
 * cleanup pass already consults it.
 *
 * Each orch has its own bridge with its own subnet, so per-process
 * state is by design. No locking needed: every method is synchronous on
 * the in-memory Map and only awaits to satisfy the async interface.
 */
export declare class InMemoryIpAllocator implements IpAllocator {
    private readonly range;
    private readonly gateway;
    private readonly gatewayNum;
    private readonly netmask;
    private readonly byVmId;
    private readonly allocatedIps;
    constructor(opts: {
        cidr: string;
        gateway: string;
        netmask: string;
    });
    allocate(vmId: string, scalerName: string): Promise<IpAllocationResult>;
    release(vmId: string): Promise<void>;
    releaseByIp(ip: string): Promise<void>;
    getAllocations(): Promise<IpAllocationRecord[]>;
    getAllocationForVm(vmId: string): Promise<IpAllocationRecord | null>;
}
//# sourceMappingURL=ip-allocator.d.ts.map