Skip to content

Instantly share code, notes, and snippets.

@seia-soto
Created May 31, 2023 23:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save seia-soto/a11f55755b7e612f361830023a133ee5 to your computer and use it in GitHub Desktop.
Save seia-soto/a11f55755b7e612f361830023a133ee5 to your computer and use it in GitHub Desktop.
TypeScript definition set for LXD API (Server and Instance)
export type LxdInstanceArchitectureType = 'x86_64' | 'arm64';
export type LxdInstanceType = 'container' | 'virtual-machine';
export type LxdInstanceEntity = {
id: string;
project: string;
};
export type LxdInstanceCpuUsage = {
usage: number;
};
export type LxdInstanceDiskUsage = {
total: number;
usage: number;
};
export type LxdInstanceMemoryUsage = {
swap_usage: number;
swap_usage_peak: number;
total: number;
usage: number;
usage_peak: number;
};
export type LxdInstanceNetworkDeviceAddress = {
address: string;
family: string;
network: string;
scope: string;
};
export type LxdInstanceNetworkDeviceUsage = {
addresses: LxdInstanceNetworkDeviceAddress[];
counters: {
bytes_received: number;
bytes_sent: number;
errors_received: number;
errors_sent: number;
packets_dropped_inbound: number;
packets_dropped_outbound: number;
packets_received: number;
packets_sent: number;
};
host_name: string;
hwaddr: string;
mtu: number;
state: 'up' | 'down';
type: string;
};
export type LxdInstanceState = {
cpu: LxdInstanceCpuUsage;
disk: Record<string, LxdInstanceDiskUsage>;
memory: LxdInstanceMemoryUsage;
network: Record<string, LxdInstanceNetworkDeviceUsage>;
pid: number;
processes: number;
status: 'Running' | 'Stopped' | 'Frozen' | 'Error';
status_code: LxdStatusCode;
};
/**
* ==== Lxd API Transaction ====
*/
export enum LxdStatusCode {
OpCreated = 100,
OpStarted,
OpStopped,
OpRunning,
OpCanceling,
OpPending,
OpStarting,
OpStopping,
OpAborting,
OpFreezing,
OpFrozen,
OpThawed,
OpError,
OpReady,
Success = 200,
Failure = 400,
Canceled,
}
export type LxdResponseMetadata = Record<string, unknown> | string[];
export type LxdOperationMetadataBase<O extends LxdResponseMetadata = LxdResponseMetadata> = {
id: string;
class: 'task' | 'token' | 'websocket';
description: string;
created_at: string;
updated_at: string;
status: string;
status_code: LxdStatusCode;
resources: {
containers?: string[];
instances?: string[];
};
metadata: O;
may_cancel: boolean;
err: string;
location: string;
};
export type LxdAsyncResponseMetadata = LxdOperationMetadataBase<{
command: string[];
environment: Record<string, string>;
fds: Record<string, string>;
interactive: boolean;
}>;
export type LxdResponseBase<T = LxdResponseMetadata> = {
type: string;
status: string;
status_code: LxdStatusCode;
metadata: T;
};
export type LxdSyncResponse<T = LxdResponseMetadata> = {
type: 'sync';
} & LxdResponseBase<T>;
export type LxdAsyncResponse<T = LxdAsyncResponseMetadata> = {
type: 'async';
operation: string;
} & LxdResponseBase<T>;
export type LxdErrorResponse = {
type: 'error';
error: string;
error_code: number;
};
export type LxdResponse<T = LxdResponseMetadata> = LxdSyncResponse<T> | LxdAsyncResponse<T> | LxdErrorResponse;
export type LxdPossibleSyncResponse<T = LxdResponseMetadata> = LxdSyncResponse<T> | LxdErrorResponse;
export type LxdPossibleAsyncResponse<T = LxdAsyncResponseMetadata> = LxdAsyncResponse<T> | LxdErrorResponse;
export type LxdBooleanMap = Record<string, 'true' | 'false'>;
export const booleanMapToObject = (map: LxdBooleanMap) => {
const generated: Record<keyof typeof map, boolean> = {};
for (const [name, booleanString] of Object.entries(map)) {
generated[name] = booleanString === 'true';
}
return generated;
};
export type LxdVerticalDividendMap = string;
export const verticalDividendMapToEntries = (maps: LxdVerticalDividendMap[]) => {
const entries: string[][] = [];
for (const map of maps) {
const values = map.split(' | ');
for (let i = 0; i < values.length; i++) {
entries[i] ??= [];
entries[i].push(values[i]);
}
}
return entries;
};
export const cleanIdMap = (ids: string[]) => ids.map(id => id.split('/').pop()!);
/**
* ==== LXD Images ====
*/
export type LxdImageAlias = {
description: string;
name: string;
};
export type LxdImageSource = {
alias: string;
certificate: string;
image_type: string;
protocol: string;
server: string;
};
export type LxdImage = {
aliases: LxdImageAlias[];
architecture: string;
auto_update: boolean;
cached: boolean;
created_at: string;
expires_at: string;
filename: string;
fingerprint: string;
last_used_at: string;
profiles: string[];
properties: Record<string, string>;
public: boolean;
size: number;
type: LxdInstanceType;
update_source: LxdImageSource;
uploaded_at: string;
};
/**
* ==== LXD Instance Devices ====
*/
export enum LxdDeviceType {
None = 0,
Nic,
Disk,
UnixChar,
UnixBlock,
Usb,
Gpu,
Infiniband,
Proxy,
UnixHotplug,
Tpm,
Pci,
}
export type LxdDeviceBase<
T extends LxdDeviceType,
O extends Record<string, unknown>,
> = {
type: T;
} & O;
export enum LxdNicDeviceType {
Bridged = 'bridged',
Macvlan = 'macvlan',
Sriov = 'sriov',
Physical = 'physical',
// -- nictype only
Ipvlan = 'ipvlan',
P2p = 'p2p',
Routed = 'routed',
// -- network only
Ovn = 'ovn',
}
export type LxdNicBridgedDevice = LxdDeviceBase<
LxdDeviceType.Nic,
{
nictype: LxdNicDeviceType.Bridged;
} & Partial<{
name: string;
'boot.priority': number;
host_name: string;
hwaddr: string;
'ipv4.address': string;
'ipv4.routes': string;
'ipv4.routes.external': string;
'ipv6.address': string;
'ipv6.routes': string;
'ipv6.routes.external': string;
'limits.egress': string;
'limits.ingress': string;
'limits.max': string;
'maas.subnet.ipv4': string;
'maas.subnet.ipv6': string;
mtu: number;
network: string;
parent: string;
'queue.tx.length': number;
'security.ipv4_filtering': boolean;
'security.ipv6_filtering': boolean;
'security.mac_filtering': boolean;
'security.port_isolation': boolean;
vlan: number;
'vlan.tagged': number;
}>
>;
export type LxdNicMacvlanDevice = LxdDeviceBase<
LxdDeviceType.Nic,
{
nictype: LxdNicDeviceType.Macvlan;
} & Partial<{
name: string;
'boot.priority': number;
gvrp: boolean;
hwaddr: string;
'maas.subnet.ipv4': string;
'maas.subnet.ipv6': string;
mtu: number;
network: string;
parent: string;
vlan: number;
}>
>;
export type LxdNicSriovDevice = LxdDeviceBase<
LxdDeviceType.Nic,
{
nictype: LxdNicDeviceType.Sriov;
} & Partial<{
name: string;
'boot.priority': number;
hwaddr: string;
'maas.subnet.ipv4': string;
'maas.subnet.ipv6': string;
mtu: number;
network: string;
parent: string;
'security.mac_filtering': boolean;
vlan: number;
}>
>;
export type LxdNicOvnDevice = LxdDeviceBase<
LxdDeviceType.Nic,
{
nictype: LxdNicDeviceType.Ovn;
} & Partial<{
name: string;
acceleration: string;
'boot.priority': number;
host_name: string;
hwaddr: string;
'ipv4.address': string;
'ipv4.routes': string;
'ipv4.routes.external': string;
'ipv6.address': string;
'ipv6.routes': string;
'ipv6.routes.external': string;
nested: string;
network: string;
'security.acls': string;
'security.acls.default.egress.action': string;
'security.acls.default.egress.logged': boolean;
'security.acls.default.ingress.action': string;
'security.acls.default.ingress.logged': boolean;
vlan: number;
}>
>;
export type LxdNicPhysicalDevice = LxdDeviceBase<
LxdDeviceType.Nic,
{
nictype: LxdNicDeviceType.Physical;
} & Partial<{
name: string;
'boot.priority': number;
gvrp: boolean;
hwaddr: string;
'maas.subnet.ipv4': string;
'maas.subnet.ipv6': string;
mtu: number;
network: string;
parent: string;
vlan: number;
}>
>;
export type LxdNicIpvlanGatewayType = 'none' | 'auto' | 'l3s' | 'l2';
export type LxdNicIpvlanDevice = LxdDeviceBase<
LxdDeviceType.Nic,
{
nictype: LxdNicDeviceType.Ipvlan;
} & Partial<{
name: string;
gvrp: boolean;
hwaddr: string;
'ipv4.address': string;
'ipv4.gateway': LxdNicIpvlanGatewayType;
'ipv4.host_table': number;
'ipv6.address': string;
'ipv6.gateway': LxdNicIpvlanGatewayType;
'ipv6.host_table': number;
mode: 'l2' | 'l3s';
mtu: number;
parent: string;
vlan: number;
}>
>;
export type LxdNicP2pDevice = LxdDeviceBase<
LxdDeviceType.Nic,
{
nictype: LxdNicDeviceType.P2p;
} & Partial<{
name: string;
'boot.priority': number;
host_name: string;
hwaddr: string;
'ipv4.routes': string;
'ipv6.routes': string;
'limits.egress': string;
'limits.ingress': string;
'limits.max': string;
mtu: number;
'queue.tx.length': number;
}>
>;
export type LxdNicRoutedDevice = LxdDeviceBase<
LxdDeviceType.Nic,
{
nictype: LxdNicDeviceType.Routed;
} & Partial<{
name: string;
gvrp: boolean;
host_name: string;
hwaddr: string;
'ipv4.address': string;
'ipv4.gateway': 'auto' | 'none';
'ipv4.host_address': string;
'ipv4.host_table': number;
'ipv4.neighbor_probe': boolean;
'ipv4.routes': string;
'ipv6.address': string;
'ipv6.gateway': 'auto' | 'none';
'ipv6.host_address': string;
'ipv6.host_table': number;
'ipv6.neighbor_probe': boolean;
'ipv6.routes': string;
'limits.egress': string;
'limits.ingress': string;
'limits.max': string;
mtu: number;
parent: string;
'queue.tx.length': number;
vlan: number;
}>
>;
export type LxdNicDevice = LxdNicBridgedDevice
| LxdNicIpvlanDevice
| LxdNicMacvlanDevice
| LxdNicOvnDevice
| LxdNicP2pDevice
| LxdNicPhysicalDevice
| LxdNicRoutedDevice
| LxdNicSriovDevice;
export type LxdDiskDevice = LxdDeviceBase<
LxdDeviceType.Disk,
Partial<{
'boot.priority': number;
'ceph.cluster_name': string;
'ceph.user_name': string;
'io.cache': 'none' | 'writeback' | 'unsafe';
'limitx.max': string;
'limits.read': string;
'limits.write': string;
path: string;
pool: string;
propagation: string;
'raw.mount.options': string;
readonly: boolean;
recursive: boolean;
required: boolean;
shift: boolean;
size: string;
'size.state': string;
source: string;
}>
>;
export type LxdUnixCharDevice = LxdDeviceBase<
LxdDeviceType.UnixChar,
Partial<{
gid: number;
major: number;
minor: number;
mode: number;
path: string;
required: boolean;
source: string;
uid: number;
}>
>;
export type LxdUnixBlockDevice = LxdDeviceBase<
LxdDeviceType.UnixBlock,
Partial<{
gid: number;
major: number;
minor: number;
mode: number;
path: string;
required: boolean;
source: string;
uid: number;
}>
>;
export type LxdUsbDevice = LxdDeviceBase<
LxdDeviceType.Usb,
Partial<{
gid: number;
mode: number;
productid: string;
required: boolean;
uid: number;
vendorid: string;
}>
>;
export enum LxdGpuDeviceType {
Physical = 'physical',
Mdev = 'mdev',
Mig = 'mig',
Sriov = 'sriov',
}
export type LxdPhysicalGpuDevice = LxdDeviceBase<
LxdDeviceType.Gpu,
{
gputype: LxdGpuDeviceType.Physical;
} & Partial<{
gid: number;
id: string;
mode: number;
pci: string;
productid: string;
uid: number;
vendorid: string;
}>
>;
export type LxdMdevGpuDevice = LxdDeviceBase<
LxdDeviceType.Gpu,
{
gputype: LxdGpuDeviceType.Mdev;
} & Partial<{
id: string;
mdev: string;
pci: string;
productid: string;
vendorid: string;
}>
>;
export type LxdMigGpuDevice = LxdDeviceBase<
LxdDeviceType.Gpu,
{
gputype: LxdGpuDeviceType.Mig;
} & Partial<{
id: string;
'mig.ci': number;
'mig.gi': number;
'mig.uuid': string;
pci: string;
productid: string;
vendorid: string;
}>
>;
export type LxdSriovGpuDevice = LxdDeviceBase<
LxdDeviceType.Gpu,
{
gputype: LxdGpuDeviceType.Sriov;
} & Partial<{
id: string;
pci: string;
productid: string;
vendorid: string;
}>
>;
export type LxdGpuDevice = LxdPhysicalGpuDevice
| LxdSriovGpuDevice
| LxdMdevGpuDevice
| LxdMigGpuDevice;
export type LxdInfinibandDevice = LxdDeviceBase<
LxdDeviceType.Infiniband,
{
nictype: LxdNicDeviceType.Physical | LxdNicDeviceType.Sriov;
} & Partial<{
name: string;
hwaddr: string;
mtu: string;
parent: string;
}>
>;
export enum LxdProxyDeviceProtocol {
Tcp = 'tcp',
Udp = 'udp',
Unix = 'unix',
}
export type LxdProxyAddressFormat = `${LxdProxyDeviceProtocol}:${string}:${string}`;
export type LxdProxyDevice = LxdDeviceBase<
LxdDeviceType.Proxy,
Partial<{
bind: string;
connect: LxdProxyAddressFormat;
gid: number;
listen: LxdProxyAddressFormat;
mode: number;
nat: boolean;
proxy_protocol: boolean;
'security.gid': number;
'security.uid': number;
uid: number;
}>
>;
export type LxdHotplugDevice = LxdDeviceBase<
LxdDeviceType.UnixHotplug,
Partial<{
gid: number;
mode: number;
productid: string;
required: boolean;
uid: number;
vendorid: string;
}>
>;
export type LxdTpmDevice = LxdDeviceBase<
LxdDeviceType.Tpm,
Partial<{
path: string;
pathrm: string;
}>
>;
export type LxdPciDevice = LxdDeviceBase<
LxdDeviceType.Pci,
Partial<{
address: string;
}>
>;
export type LxdDevice = LxdNicDevice
| LxdDiskDevice
| LxdUnixCharDevice
| LxdUnixBlockDevice
| LxdGpuDevice
| LxdInfinibandDevice
| LxdProxyDevice
| LxdHotplugDevice
| LxdTpmDevice
| LxdPciDevice;
export type LxdInstanceBaseConfig = {
name: string;
architecture: string;
};
export type LxdInstanceMiscellaneousConfig = {
'agent.nic_config': boolean;
'cluster.evacuate': 'auto' | 'migrate' | 'live-migrate' | 'stop';
'linux.kernel_modules': string;
}
& Record<`environment.${string}`, string>
& Record<`linux.sysctl.${string}`, string>
& Record<`user.${string}`, string>;
export type LxdInstanceBootConfig = {
'boot.autostart': boolean;
'boot.autostart.delay': number;
'boot.autostart.priority': number;
'boot.host_shutdown_timeout': number;
'boot.stop.priority': number;
};
export type LxdInstanceCloudInitConfig = {
'cloud-init.network-config': string;
'cloud-init.user-data': string;
'cloud-init.vendor-data': string;
'user.network-config': string;
'user.user-data': string;
'user.vendor-data': string;
};
export type LxdInstanceResourceConfig = {
'limits.cpu': string;
'limits.cpu.allowance': string;
'limits.cpu.priority': number;
'limits.disk.priority': number;
'limits.hugepages.64KB': string;
'limits.hugepages.1MB': string;
'limits.hugepages.2MB': string;
'limits.hugepages.1GB': string;
'limits.memory': string;
'limits.memory.enforce': 'hard' | 'soft';
'limits.memory.hugepages': boolean;
'limits.memory.swap': boolean;
'limits.memory.swap.priority': number;
'limits.network.priority': number;
'limits.processes': number;
}
& Record<`limits.kernel.${string}`, string>;
export type LxdInstanceMigrationConfig = {
'migration.incremental.memory': boolean;
'migration.incremental.memory.goal': number;
'migration.incremental.memory.iterations': number;
'migration.stateful': boolean;
};
export type LxdInstanceNvidiaConfig = {
'nvidia.driver.capabilities': string;
'nvidia.runtime': boolean;
'nvidia.require.cuda': string;
'nvidia.require.driver': string;
};
export type LxdInstanceRawOverridableConfig = {
'raw.apparmor': unknown;
'raw.idmap': unknown;
'raw.lxc': unknown;
'raw.qemu': unknown;
'raw.qemu.config': unknown;
'raw.seccomp': unknown;
};
export type LxdInstanceSecurityConfig = {
'security.devlxd': boolean;
'security.devlxd.images': boolean;
'security.idmap.base': number;
'security.idmap.isolated': boolean;
'security.idmap.size': number;
'security.nesting': boolean;
'security.privileged': boolean;
'security.protection.delete': boolean;
'security.protection.shift': boolean;
'security.agent.metrics': boolean;
'security.secureboot': boolean;
'security.sev': boolean;
'security.sev.policy.es': boolean;
'security.sev.session.dh': string;
'security.sev.session.data': string;
'security.syscalls.allow': string;
'security.syscalls.deny': string;
'security.syscalls.deny_compact': boolean;
'security.syscalls.deny_default': boolean;
'security.syscalls.intercept.bpf': boolean;
'security.syscalls.intercept.bpf.devices': boolean;
'security.syscalls.intercept.mknod': boolean;
'security.syscalls.intercept.mount': boolean;
'security.syscalls.intercept.mount.allowed': string;
'security.syscalls.intercept.mount.fuse': string;
'security.syscalls.intercept.mount.shift': boolean;
'security.syscalls.intercept.sched_setscheduler': boolean;
'security.syscalls.intercept.setxattr': boolean;
'security.syscalls.intercept.sysinfo': boolean;
};
export type LxdInstanceSnapshotConfig = {
'snapshots.schedule': string;
'snapshots.schedule.stopped': boolean;
'snapshots.pattern': string;
'snapshots.expiry': string;
};
export type LxdInstanceVolatileConfig = {
'volatile.apply_template': string;
'volatile.apply_nvram': string;
'volatile.base_image': string;
'volatile.cloud-init.instance-id': string;
'volatile.evacuate.origin': string;
'volatile.idmap.base': number;
'volatile.idmap.current': string;
'volatile.idmap.next': string;
'volatile.last_state.idmap': string;
'volatile.last_state.power': string;
'volatile.vsock_id': string;
'volatile.uuid': string;
'volatile.uuid.generation': string;
}
& Record<`volatile.${string}.${
'apply_quota'
| 'ceph_rbd'
| 'host_name'
| 'hwaddr'
| 'last_state.created'
| 'last_state.mtu'
| 'last_state.hwaddr'
| 'last_state.ip_addresses'
| 'last_state.vdpa.name'
| 'last_state.vf.id'
| 'last_state.vf.hwaddr'
| 'last_state.vf.vlan'
| 'last_state.vf.spoofcheck'
}`, string>;
export type LxdInstanceImageConfig = {
'image.architecture': string;
'image.description': string;
'image.os': string;
'image.release': string;
'image.serial': string;
'image.type': string;
'image.variant': string;
};
export type LxdInstanceConfig = Partial<
LxdInstanceMiscellaneousConfig
& LxdInstanceBootConfig
& LxdInstanceCloudInitConfig
& LxdInstanceResourceConfig
& LxdInstanceNvidiaConfig
& LxdInstanceRawOverridableConfig
& LxdInstanceSecurityConfig
& LxdInstanceSnapshotConfig
& LxdInstanceVolatileConfig
& LxdInstanceImageConfig
>;
export type LxdInstance = LxdInstanceBaseConfig
& {
config: LxdInstanceConfig;
devices: Record<string, LxdDevice>;
ephemeral: boolean;
profiles: string[];
stateful: boolean;
description: string;
created_at: string;
expanded_config: LxdInstanceConfig;
expanded_devices: Record<string, LxdDevice>;
name: string;
status: string;
status_code: number;
last_used_at: string;
location: string;
type: LxdInstanceType;
project: string;
};
// -- LXD Instance creation properties
export type LxdDescriptionRecord = {description: string} & Record<string, string>;
export type LxdInstanceSourceBase = {
alias: string;
allow_inconsistent: boolean;
'base-image': string;
certificate: string;
container_only: boolean;
fingerprint: string;
instance_only: boolean;
live: boolean;
mode: 'pull';
operation: string;
project: string;
properties: LxdDescriptionRecord;
protocol: string;
refresh: boolean;
secret: string;
secrets: LxdDescriptionRecord;
server: string;
type: 'image';
};
export type LxdInstanceSourceSimpleStreams = Pick<LxdInstanceSourceBase, 'type' | 'alias' | 'server' | 'mode' | 'allow_inconsistent'> & {
protocol: 'simplestreams';
};
export type LxdInstanceSourceLocal = Pick<LxdInstanceSourceBase, 'type' | 'alias'> & Partial<LxdInstanceSourceBase>;
export type LxdInstanceSource = LxdInstanceSourceBase
| LxdInstanceSourceSimpleStreams
| LxdInstanceSourceLocal;
export type LxdInstanceBootstrapBase = {
architecture: LxdInstanceArchitectureType;
config: LxdInstanceConfig;
description: string;
devices: Record<string, LxdDevice>;
ephemeral: boolean;
instance_type?: string;
name: string;
profiles: string[];
restore?: string;
source: LxdInstanceSource;
stateful: boolean;
type: LxdInstanceType;
};
export type LxdInstanceBootstrapInitial = Omit<LxdInstanceBootstrapBase, 'restore' | 'source'> & {
source: Omit<LxdInstanceSource, 'base-image' | 'project' | 'refresh'>;
stateful: false;
};
export type LxdInstanceBootstrap = LxdInstanceBootstrapInitial;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment