diff --git a/OMICRON_VERSION b/OMICRON_VERSION index 77eaa4db42..a5ab3c48ac 100644 --- a/OMICRON_VERSION +++ b/OMICRON_VERSION @@ -1 +1 @@ -f3e2c929a72e5f1a6fba5243caa9ab09a76c9152 +d2ed4524f17ae025fb2e55956d7c82d377872a3e diff --git a/app/api/__generated__/Api.ts b/app/api/__generated__/Api.ts index e69cb1acbb..efc3e6a84c 100644 --- a/app/api/__generated__/Api.ts +++ b/app/api/__generated__/Api.ts @@ -175,6 +175,37 @@ export type AggregateBgpMessageHistory = { switchHistories: SwitchBgpHistory[] } +/** + * Description of source IPs allowed to reach rack services. + */ +export type AllowedSourceIps = + /** Allow traffic from any external IP address. */ + | { allow: 'any' } + /** Restrict access to a specific set of source IP addresses or subnets. + +All others are prevented from reaching rack services. */ + | { allow: 'list'; ips: IpNet[] } + +/** + * Allowlist of IPs or subnets that can make requests to user-facing services. + */ +export type AllowList = { + /** The allowlist of IPs or subnets. */ + allowedIps: AllowedSourceIps + /** Time the list was created. */ + timeCreated: Date + /** Time the list was last modified. */ + timeModified: Date +} + +/** + * Parameters for updating allowed source IPs + */ +export type AllowListUpdate = { + /** The new list of allowed source IPs. */ + allowedIps: AllowedSourceIps +} + /** * Properties that uniquely identify an Oxide hardware component */ @@ -338,21 +369,34 @@ export type BgpImportedRouteIpv4 = { switch: SwitchLocation } +/** + * Define policy relating to the import and export of prefixes from a BGP peer. + */ +export type ImportExportPolicy = + /** Do not perform any filtering. */ + { type: 'no_filtering' } | { type: 'allow'; value: IpNet[] } + /** * A BGP peer configuration for an interface. Includes the set of announcements that will be advertised to the peer identified by `addr`. The `bgp_config` parameter is a reference to global BGP parameters. The `interface_name` indicates what interface the peer should be contacted on. */ export type BgpPeer = { /** The address of the host to peer with. */ addr: string - /** The set of announcements advertised by the peer. */ - bgpAnnounceSet: NameOrId + /** Define export policy for a peer. */ + allowedExport: ImportExportPolicy + /** Define import policy for a peer. */ + allowedImport: ImportExportPolicy /** The global BGP configuration used for establishing a session with this peer. */ bgpConfig: NameOrId + /** Include the provided communities in updates sent to the peer. */ + communities: number[] /** How long to to wait between TCP connection retries (seconds). */ connectRetry: number /** How long to delay sending an open request after establishing a TCP session (seconds). */ delayOpen: number - /** How long to hold peer connections between keppalives (seconds). */ + /** Enforce that the first AS in paths received from this peer is the peer's AS. */ + enforceFirstAs: boolean + /** How long to hold peer connections between keepalives (seconds). */ holdTime: number /** How long to hold a peer in idle before attempting a new session (seconds). */ idleHoldTime: number @@ -360,6 +404,18 @@ export type BgpPeer = { interfaceName: string /** How often to send keepalive requests (seconds). */ keepalive: number + /** Apply a local preference to routes received from this peer. */ + localPref?: number + /** Use the given key for TCP-MD5 authentication with the peer. */ + md5AuthKey?: string + /** Require messages from a peer have a minimum IP time to live field. */ + minTtl?: number + /** Apply the provided multi-exit discriminator (MED) updates sent to the peer. */ + multiExitDiscriminator?: number + /** Require that a peer has a specified ASN. */ + remoteAsn?: number + /** Associate a VLAN ID with a peer. */ + vlanId?: number } export type BgpPeerConfig = { peers: BgpPeer[] } @@ -368,7 +424,7 @@ export type BgpPeerConfig = { peers: BgpPeer[] } * The current state of a BGP peer. */ export type BgpPeerState = - /** Initial state. Refuse all incomming BGP connections. No resources allocated to peer. */ + /** Initial state. Refuse all incoming BGP connections. No resources allocated to peer. */ | 'idle' /** Waiting for the TCP connection to be completed. */ | 'connect' @@ -380,7 +436,7 @@ export type BgpPeerState = | 'open_confirm' /** Synchronizing with peer. */ | 'session_setup' - /** Session established. Able to exchange update, notification and keepliave messages with peers. */ + /** Session established. Able to exchange update, notification and keepalive messages with peers. */ | 'established' /** @@ -1024,6 +1080,8 @@ export type ExternalIp = instanceId?: string /** The IP address held by this resource. */ ip: string + /** The ID of the IP pool this resource belongs to. */ + ipPoolId: string kind: 'floating' /** unique, mutable, user-controlled identifier for each resource */ name: Name @@ -1148,6 +1206,8 @@ export type FloatingIp = { instanceId?: string /** The IP address held by this resource. */ ip: string + /** The ID of the IP pool this resource belongs to. */ + ipPoolId: string /** unique, mutable, user-controlled identifier for each resource */ name: Name /** The project this resource exists within. */ @@ -1682,7 +1742,7 @@ export type L4PortRange = string * The forward error correction mode of a link. */ export type LinkFec = - /** Firecode foward error correction. */ + /** Firecode forward error correction. */ | 'firecode' /** No forward error correction. */ | 'none' @@ -2441,6 +2501,11 @@ export type Sled = { usablePhysicalRam: ByteCount } +/** + * The unique ID of a sled. + */ +export type SledId = { id: string } + /** * An operator's view of an instance running on a given sled */ @@ -2648,6 +2713,8 @@ export type SwitchInterfaceConfigCreate = { v6Enabled: boolean } +export type SwitchLinkState = Record + /** * A switch port represents a physical external port on a rack switch. */ @@ -2686,20 +2753,6 @@ export type SwitchPortApplySettings = { portSettings: NameOrId } -/** - * A BGP peer configuration for a port settings object. - */ -export type SwitchPortBgpPeerConfig = { - /** The address of the peer. */ - addr: string - /** The id of the global BGP configuration referenced by this peer configuration. */ - bgpConfigId: string - /** The interface name used to establish a peer session. */ - interfaceName: string - /** The port settings object this BGP configuration belongs to. */ - portSettingsId: string -} - /** * The link geometry associated with a switch port. */ @@ -2744,6 +2797,10 @@ export type SwitchPortConfigCreate = { * A link configuration for a port settings object. */ export type SwitchPortLinkConfig = { + /** Whether or not the link has autonegotiation enabled. */ + autoneg: boolean + /** The forward error correction mode of the link. */ + fec: LinkFec /** The name of this link. */ linkName: string /** The link-layer discovery protocol service configuration id for this link. */ @@ -2752,6 +2809,8 @@ export type SwitchPortLinkConfig = { mtu: number /** The port settings this link configuration belongs to. */ portSettingsId: string + /** The configured speed of the link. */ + speed: LinkSpeed } /** @@ -2853,7 +2912,7 @@ export type SwitchPortSettingsView = { /** Layer 3 IP address settings. */ addresses: SwitchPortAddressConfig[] /** BGP peer settings. */ - bgpPeers: SwitchPortBgpPeerConfig[] + bgpPeers: BgpPeer[] /** Switch port settings included from other switch port settings groups. */ groups: SwitchPortSettingsGroups[] /** Layer 3 interface settings. */ @@ -3894,6 +3953,15 @@ export interface NetworkingSwitchPortClearSettingsQueryParams { switchLocation: Name } +export interface NetworkingSwitchPortStatusPathParams { + port: Name +} + +export interface NetworkingSwitchPortStatusQueryParams { + rackId: string + switchLocation: Name +} + export interface SwitchListQueryParams { limit?: number pageToken?: string @@ -5696,7 +5764,7 @@ export class Api extends HttpClient { * Add sled to initialized rack */ sledAdd: ({ body }: { body: UninitializedSledId }, params: FetchParams = {}) => { - return this.request({ + return this.request({ path: `/v1/system/hardware/sleds`, method: 'POST', body, @@ -5835,6 +5903,26 @@ export class Api extends HttpClient { ...params, }) }, + /** + * Get switch port status + */ + networkingSwitchPortStatus: ( + { + path, + query, + }: { + path: NetworkingSwitchPortStatusPathParams + query: NetworkingSwitchPortStatusQueryParams + }, + params: FetchParams = {} + ) => { + return this.request({ + path: `/v1/system/hardware/switch-port/${path.port}/status`, + method: 'GET', + query, + ...params, + }) + }, /** * List switches */ @@ -6268,6 +6356,30 @@ export class Api extends HttpClient { ...params, }) }, + /** + * Get user-facing services IP allowlist + */ + networkingAllowListView: (_: EmptyObj, params: FetchParams = {}) => { + return this.request({ + path: `/v1/system/networking/allow-list`, + method: 'GET', + ...params, + }) + }, + /** + * Update user-facing services IP allowlist + */ + networkingAllowListUpdate: ( + { body }: { body: AllowListUpdate }, + params: FetchParams = {} + ) => { + return this.request({ + path: `/v1/system/networking/allow-list`, + method: 'PUT', + body, + ...params, + }) + }, /** * Disable a BFD session */ diff --git a/app/api/__generated__/OMICRON_VERSION b/app/api/__generated__/OMICRON_VERSION index 3f8b644c77..c8a1e4afd7 100644 --- a/app/api/__generated__/OMICRON_VERSION +++ b/app/api/__generated__/OMICRON_VERSION @@ -1,2 +1,2 @@ # generated file. do not update manually. see docs/update-pinned-api.md -f3e2c929a72e5f1a6fba5243caa9ab09a76c9152 +d2ed4524f17ae025fb2e55956d7c82d377872a3e diff --git a/app/api/__generated__/msw-handlers.ts b/app/api/__generated__/msw-handlers.ts index 6a5e8da00e..43a4859036 100644 --- a/app/api/__generated__/msw-handlers.ts +++ b/app/api/__generated__/msw-handlers.ts @@ -630,7 +630,7 @@ export interface MSWHandlers { body: Json req: Request cookies: Record - }) => Promisable + }) => Promisable> /** `GET /v1/system/hardware/sleds/:sledId` */ sledView: (params: { path: Api.SledViewPathParams @@ -685,6 +685,13 @@ export interface MSWHandlers { req: Request cookies: Record }) => Promisable + /** `GET /v1/system/hardware/switch-port/:port/status` */ + networkingSwitchPortStatus: (params: { + path: Api.NetworkingSwitchPortStatusPathParams + query: Api.NetworkingSwitchPortStatusQueryParams + req: Request + cookies: Record + }) => Promisable> /** `GET /v1/system/hardware/switches` */ switchList: (params: { query: Api.SwitchListQueryParams @@ -879,6 +886,17 @@ export interface MSWHandlers { req: Request cookies: Record }) => Promisable> + /** `GET /v1/system/networking/allow-list` */ + networkingAllowListView: (params: { + req: Request + cookies: Record + }) => Promisable> + /** `PUT /v1/system/networking/allow-list` */ + networkingAllowListUpdate: (params: { + body: Json + req: Request + cookies: Record + }) => Promisable> /** `POST /v1/system/networking/bfd-disable` */ networkingBfdDisable: (params: { body: Json @@ -1793,6 +1811,14 @@ export function makeHandlers(handlers: MSWHandlers): HttpHandler[] { null ) ), + http.get( + '/v1/system/hardware/switch-port/:port/status', + handler( + handlers['networkingSwitchPortStatus'], + schema.NetworkingSwitchPortStatusParams, + null + ) + ), http.get( '/v1/system/hardware/switches', handler(handlers['switchList'], schema.SwitchListParams, null) @@ -1953,6 +1979,14 @@ export function makeHandlers(handlers: MSWHandlers): HttpHandler[] { null ) ), + http.get( + '/v1/system/networking/allow-list', + handler(handlers['networkingAllowListView'], null, null) + ), + http.put( + '/v1/system/networking/allow-list', + handler(handlers['networkingAllowListUpdate'], null, schema.AllowListUpdate) + ), http.post( '/v1/system/networking/bfd-disable', handler(handlers['networkingBfdDisable'], null, schema.BfdSessionDisable) diff --git a/app/api/__generated__/validate.ts b/app/api/__generated__/validate.ts index 0e7cda181b..fcb58fb1f2 100644 --- a/app/api/__generated__/validate.ts +++ b/app/api/__generated__/validate.ts @@ -49,7 +49,7 @@ export const Ipv6Net = z.preprocess( z .string() .regex( - /^([fF][dD])[0-9a-fA-F]{2}:(([0-9a-fA-F]{1,4}:){6}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,6}:)([0-9a-fA-F]{1,4})?\/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$/ + /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))\/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$/ ) ) @@ -198,6 +198,37 @@ export const AggregateBgpMessageHistory = z.preprocess( z.object({ switchHistories: SwitchBgpHistory.array() }) ) +/** + * Description of source IPs allowed to reach rack services. + */ +export const AllowedSourceIps = z.preprocess( + processResponseBody, + z.union([ + z.object({ allow: z.enum(['any']) }), + z.object({ allow: z.enum(['list']), ips: IpNet.array() }), + ]) +) + +/** + * Allowlist of IPs or subnets that can make requests to user-facing services. + */ +export const AllowList = z.preprocess( + processResponseBody, + z.object({ + allowedIps: AllowedSourceIps, + timeCreated: z.coerce.date(), + timeModified: z.coerce.date(), + }) +) + +/** + * Parameters for updating allowed source IPs + */ +export const AllowListUpdate = z.preprocess( + processResponseBody, + z.object({ allowedIps: AllowedSourceIps }) +) + /** * Properties that uniquely identify an Oxide hardware component */ @@ -352,6 +383,17 @@ export const BgpImportedRouteIpv4 = z.preprocess( }) ) +/** + * Define policy relating to the import and export of prefixes from a BGP peer. + */ +export const ImportExportPolicy = z.preprocess( + processResponseBody, + z.union([ + z.object({ type: z.enum(['no_filtering']) }), + z.object({ type: z.enum(['allow']), value: IpNet.array() }), + ]) +) + /** * A BGP peer configuration for an interface. Includes the set of announcements that will be advertised to the peer identified by `addr`. The `bgp_config` parameter is a reference to global BGP parameters. The `interface_name` indicates what interface the peer should be contacted on. */ @@ -359,14 +401,23 @@ export const BgpPeer = z.preprocess( processResponseBody, z.object({ addr: z.string().ip(), - bgpAnnounceSet: NameOrId, + allowedExport: ImportExportPolicy, + allowedImport: ImportExportPolicy, bgpConfig: NameOrId, + communities: z.number().min(0).max(4294967295).array(), connectRetry: z.number().min(0).max(4294967295), delayOpen: z.number().min(0).max(4294967295), + enforceFirstAs: SafeBoolean, holdTime: z.number().min(0).max(4294967295), idleHoldTime: z.number().min(0).max(4294967295), interfaceName: z.string(), keepalive: z.number().min(0).max(4294967295), + localPref: z.number().min(0).max(4294967295).optional(), + md5AuthKey: z.string().optional(), + minTtl: z.number().min(0).max(255).optional(), + multiExitDiscriminator: z.number().min(0).max(4294967295).optional(), + remoteAsn: z.number().min(0).max(4294967295).optional(), + vlanId: z.number().min(0).max(65535).optional(), }) ) @@ -1136,6 +1187,7 @@ export const ExternalIp = z.preprocess( id: z.string().uuid(), instanceId: z.string().uuid().optional(), ip: z.string().ip(), + ipPoolId: z.string().uuid(), kind: z.enum(['floating']), name: Name, projectId: z.string().uuid(), @@ -1274,6 +1326,7 @@ export const FloatingIp = z.preprocess( id: z.string().uuid(), instanceId: z.string().uuid().optional(), ip: z.string().ip(), + ipPoolId: z.string().uuid(), name: Name, projectId: z.string().uuid(), timeCreated: z.coerce.date(), @@ -2504,6 +2557,11 @@ export const Sled = z.preprocess( }) ) +/** + * The unique ID of a sled. + */ +export const SledId = z.preprocess(processResponseBody, z.object({ id: z.string().uuid() })) + /** * An operator's view of an instance running on a given sled */ @@ -2683,6 +2741,8 @@ export const SwitchInterfaceConfigCreate = z.preprocess( z.object({ kind: SwitchInterfaceKind, v6Enabled: SafeBoolean }) ) +export const SwitchLinkState = z.preprocess(processResponseBody, z.record(z.unknown())) + /** * A switch port represents a physical external port on a rack switch. */ @@ -2718,19 +2778,6 @@ export const SwitchPortApplySettings = z.preprocess( z.object({ portSettings: NameOrId }) ) -/** - * A BGP peer configuration for a port settings object. - */ -export const SwitchPortBgpPeerConfig = z.preprocess( - processResponseBody, - z.object({ - addr: z.string().ip(), - bgpConfigId: z.string().uuid(), - interfaceName: z.string(), - portSettingsId: z.string().uuid(), - }) -) - /** * The link geometry associated with a switch port. */ @@ -2769,10 +2816,13 @@ export const SwitchPortConfigCreate = z.preprocess( export const SwitchPortLinkConfig = z.preprocess( processResponseBody, z.object({ + autoneg: SafeBoolean, + fec: LinkFec, linkName: z.string(), lldpServiceConfigId: z.string().uuid(), mtu: z.number().min(0).max(65535), portSettingsId: z.string().uuid(), + speed: LinkSpeed, }) ) @@ -2861,7 +2911,7 @@ export const SwitchPortSettingsView = z.preprocess( processResponseBody, z.object({ addresses: SwitchPortAddressConfig.array(), - bgpPeers: SwitchPortBgpPeerConfig.array(), + bgpPeers: BgpPeer.array(), groups: SwitchPortSettingsGroups.array(), interfaces: SwitchInterfaceConfig.array(), linkLldp: LldpServiceConfig.array(), @@ -4425,6 +4475,19 @@ export const NetworkingSwitchPortClearSettingsParams = z.preprocess( }) ) +export const NetworkingSwitchPortStatusParams = z.preprocess( + processResponseBody, + z.object({ + path: z.object({ + port: Name, + }), + query: z.object({ + rackId: z.string().uuid(), + switchLocation: Name, + }), + }) +) + export const SwitchListParams = z.preprocess( processResponseBody, z.object({ @@ -4751,6 +4814,22 @@ export const NetworkingAddressLotBlockListParams = z.preprocess( }) ) +export const NetworkingAllowListViewParams = z.preprocess( + processResponseBody, + z.object({ + path: z.object({}), + query: z.object({}), + }) +) + +export const NetworkingAllowListUpdateParams = z.preprocess( + processResponseBody, + z.object({ + path: z.object({}), + query: z.object({}), + }) +) + export const NetworkingBfdDisableParams = z.preprocess( processResponseBody, z.object({ diff --git a/mock-api/floating-ip.ts b/mock-api/floating-ip.ts index 71fc4df4f4..787bff639a 100644 --- a/mock-api/floating-ip.ts +++ b/mock-api/floating-ip.ts @@ -9,6 +9,7 @@ import type { FloatingIp } from '@oxide/api' import { instance } from './instance' +import { ipPool1 } from './ip-pool' import type { Json } from './json-type' import { project } from './project' @@ -21,6 +22,7 @@ export const floatingIp: Json = { description: 'A classic.', instance_id: undefined, ip: '123.4.56.4', + ip_pool_id: ipPool1.id, project_id: project.id, time_created: new Date().toISOString(), time_modified: new Date().toISOString(), @@ -33,6 +35,7 @@ export const floatingIp2: Json = { description: 'A favourite.', instance_id: instance.id, ip: '123.4.56.5', + ip_pool_id: ipPool1.id, project_id: project.id, time_created: new Date().toISOString(), time_modified: new Date().toISOString(), diff --git a/mock-api/ip-pool.ts b/mock-api/ip-pool.ts index cb028cbc23..0296782ae9 100644 --- a/mock-api/ip-pool.ts +++ b/mock-api/ip-pool.ts @@ -11,7 +11,7 @@ import { type IpPool, type IpPoolRange, type IpPoolSiloLink } from '@oxide/api' import type { Json } from './json-type' import { defaultSilo } from './silo' -const ipPool1: Json = { +export const ipPool1: Json = { id: '69b5c583-74a9-451a-823d-0741c1ec66e2', name: 'ip-pool-1', description: '', diff --git a/mock-api/msw/db.ts b/mock-api/msw/db.ts index fb75391799..7c4139c74a 100644 --- a/mock-api/msw/db.ts +++ b/mock-api/msw/db.ts @@ -200,6 +200,26 @@ export const lookup = { return { ...pool, is_default: link.is_default } }) }, + siloIpPool(path: PP.Silo & PP.IpPool): Json { + const silo = lookup.silo(path) + const pool = lookup.ipPool(path) + + // we want to 404 if it exists but isn't in the silo + const ipPoolSilo = db.ipPoolSilos.find( + (ips) => ips.ip_pool_id === pool.id && ips.silo_id === silo.id + ) + if (!ipPoolSilo) throw notFoundErr + + return { ...pool, is_default: ipPoolSilo.is_default } + }, + siloDefaultIpPool(path: PP.Silo): Json { + const silo = lookup.silo(path) + + const link = db.ipPoolSilos.find((ips) => ips.silo_id === silo.id && ips.is_default) + if (!link) throw notFoundErr + + return lookupById(db.ipPools, link.ip_pool_id) + }, samlIdp({ provider: id, ...siloSelector diff --git a/mock-api/msw/handlers.ts b/mock-api/msw/handlers.ts index f755c8526a..09e3168e3d 100644 --- a/mock-api/msw/handlers.ts +++ b/mock-api/msw/handlers.ts @@ -234,12 +234,16 @@ export const handlers = makeHandlers({ errIfExists(db.floatingIps, { name: body.name }) // TODO: when IP is specified, use ipInAnyRange to check that it is in the pool + const pool = body.pool + ? lookup.siloIpPool({ pool: body.pool, silo: defaultSilo.id }) + : lookup.siloDefaultIpPool({ silo: defaultSilo.id }) const newFloatingIp: Json = { id: uuid(), project_id: project.id, // TODO: use ip-num to actually get the next available IP in the pool ip: [...Array(4)].map(() => Math.floor(Math.random() * 256)).join('.'), + ip_pool_id: pool.id, ...body, ...getTimestamps(), } @@ -676,17 +680,8 @@ export const handlers = makeHandlers({ const pools = lookup.siloIpPools({ silo: defaultSilo.id }) return paginated(query, pools) }, - projectIpPoolView({ path }) { - // this will 404 if it doesn't exist at all... - const pool = lookup.ipPool(path) - // but we also want to 404 if it exists but isn't in the silo - const link = db.ipPoolSilos.find( - (link) => link.ip_pool_id === pool.id && link.silo_id === defaultSilo.id - ) - if (!link) throw notFoundErr() - - return { ...pool, is_default: link.is_default } - }, + projectIpPoolView: ({ path: { pool } }) => + lookup.siloIpPool({ pool, silo: defaultSilo.id }), // TODO: require admin permissions for system IP pool endpoints ipPoolView: ({ path }) => lookup.ipPool(path), ipPoolSiloList({ path /*query*/ }) { @@ -1273,6 +1268,8 @@ export const handlers = makeHandlers({ networkingAddressLotCreate: NotImplemented, networkingAddressLotDelete: NotImplemented, networkingAddressLotList: NotImplemented, + networkingAllowListUpdate: NotImplemented, + networkingAllowListView: NotImplemented, networkingBfdDisable: NotImplemented, networkingBfdEnable: NotImplemented, networkingBfdStatus: NotImplemented, @@ -1295,6 +1292,7 @@ export const handlers = makeHandlers({ networkingSwitchPortSettingsDelete: NotImplemented, networkingSwitchPortSettingsView: NotImplemented, networkingSwitchPortSettingsList: NotImplemented, + networkingSwitchPortStatus: NotImplemented, physicalDiskView: NotImplemented, probeCreate: NotImplemented, probeDelete: NotImplemented,