262 lines
17 KiB
XML
262 lines
17 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!--
|
|
Rackpad population settings.
|
|
|
|
This document is loaded by the script that shares its base name, so Invoke-RackpadPopulation.ps1 reads
|
|
Settings\Invoke-RackpadPopulation.xml unless the ConfigurationPath parameter says otherwise.
|
|
|
|
Ownership model.
|
|
|
|
Omada owns switches, access points, switch ports, cables, VLANs, and wireless.
|
|
UniFi owns the same shapes as Omada and can run alongside it.
|
|
Proxmox owns hypervisor hosts, bridges, guests, and guest network interfaces.
|
|
Hyper-V owns the same shapes as Proxmox and can run alongside it.
|
|
OPNsense owns VLANs, subnets, and the routed edge.
|
|
|
|
The live sources are authoritative. This document cannot create devices, VLANs, subnets, or SSIDs; it only supplies what no API
|
|
knows, which is the physical layout consisting of rooms, racks, and rack unit placement, together with the address ranges that
|
|
serve them.
|
|
|
|
Rooms and racks are optional. Leave them empty and discovered equipment stays loose within the lab. Declare them and they are
|
|
created, and every Placement entry that names them files the matching equipment into them.
|
|
|
|
DHCP is served elsewhere and is deliberately out of scope. No DHCP scope is created, updated, or deleted, and IP assignments are
|
|
always written using the static allocation mode. Leave DHCP as a manual concern within Rackpad.
|
|
|
|
Value expansion happens before this document is parsed, in three passes over the raw text.
|
|
|
|
1. Environment variables in the %NAME% form are expanded.
|
|
2. PowerShell expressions are expanded against the current execution context, so $env:NAME, $($env:NAME), and any other
|
|
PowerShell variable or subexpression resolves. User and machine scoped environment variables are promoted into the process
|
|
first, so a variable created after the shell started still resolves.
|
|
3. The expanded text is loaded into an XmlDocument and navigated using XPath.
|
|
|
|
Because pass two evaluates PowerShell, treat this document with the same care as a script, and escape any literal dollar sign
|
|
that is not meant as an expression using a backtick.
|
|
|
|
Secrets belong in CDATA sections so that reserved XML characters survive unchanged. Prefer keeping the value itself in an
|
|
environment variable and referencing it here.
|
|
-->
|
|
<RackpadPopulation Version="2026.08.02.0000">
|
|
<Instances>
|
|
|
|
<Instance Name="Primary" Enabled="false">
|
|
|
|
<!-- Rackpad connection. -->
|
|
<Rackpad BaseURL="$env:RACKPAD_BASE_URL" SkipCertificateCheck="false">
|
|
<Username><![CDATA[$env:RACKPAD_USERNAME]]></Username>
|
|
<Password><![CDATA[$env:RACKPAD_PASSWORD]]></Password>
|
|
</Rackpad>
|
|
|
|
<!-- The lab is resolved by name. When CreateIfMissing is true a lab with this name is created on the first run. -->
|
|
<Lab Name="Primary Lab"
|
|
Description="Layer two switching and wireless from the controller, layer three from the virtualized edge firewall."
|
|
Location=""
|
|
CreateIfMissing="true" />
|
|
|
|
<!--
|
|
PruneManagedObjects Deletes objects that a previous run of this script created and that are no longer wanted.
|
|
Objects created by hand within the Rackpad user interface are never touched.
|
|
ManageIPAssignments Writes an IP assignment for each management address and each recognized client address.
|
|
ManagePortLinks Writes cable links derived from controller client sessions when both endpoints are known.
|
|
ManageWireless Writes the controller, SSIDs, access point metadata, radios, and client associations.
|
|
ManageClientEndpoints Creates an endpoint device per wireless client. Rackpad refuses a client association whose client
|
|
is not an existing device, so wireless associations are only written when this is enabled.
|
|
Leave false unless you want every phone and television in the inventory.
|
|
StateDirectory Where the managed object state document is written. Leave empty to use the Data directory
|
|
beside the script, which keeps the solution self contained and portable.
|
|
-->
|
|
<Options PruneManagedObjects="true"
|
|
ManageIPAssignments="true"
|
|
ManagePortLinks="true"
|
|
ManageWireless="true"
|
|
ManageClientEndpoints="false"
|
|
StateDirectory="" />
|
|
|
|
<Layout>
|
|
|
|
<!-- Remove or empty these elements to leave every discovered device loose within the lab. -->
|
|
<Rooms>
|
|
<Room Name="Server Room" Description="Primary equipment room." Location="" Enabled="true">
|
|
<Notes><![CDATA[Core switching, hypervisors, and the routed edge live here.]]></Notes>
|
|
</Room>
|
|
</Rooms>
|
|
|
|
<Racks>
|
|
<Rack Name="RACK-01" Room="Server Room" TotalU="22" Description="Primary rack." Location="1st Floor" Enabled="true" />
|
|
</Racks>
|
|
|
|
<!--
|
|
Placement pins discovered equipment to a physical position without having to name every device.
|
|
|
|
InclusionExpression and ExclusionExpression are regular expressions, matched case insensitively against whichever
|
|
value MatchBy selects: Hostname, MAC, or Serial. A rule matches when the inclusion expression matches and the
|
|
exclusion expression, if present, does not.
|
|
|
|
Rules are evaluated in document order and the FIRST match wins, so specific rules go above general ones, exactly as
|
|
in an access list. That means a broad catch-all can sit at the bottom and carve-outs above it.
|
|
|
|
Supplying a Rack implies rack placement; supplying only a Room leaves the device as loose room technology.
|
|
Equipment matching no rule stays loose.
|
|
|
|
StartU is optional. Omit it in a broad rule and matching devices are assigned to the rack without a fixed rack unit,
|
|
which you can then arrange in the user interface. Only name a rack unit on a rule that matches a single device.
|
|
|
|
The literal Match attribute from earlier versions is still accepted and is treated as an anchored exact expression.
|
|
-->
|
|
<Placements>
|
|
<!-- Wireless first, so the catch-all below never claims an access point. -->
|
|
<Placement InclusionExpression=".*-AP-.*" MatchBy="Hostname" Room="Server Room" Enabled="false" />
|
|
|
|
<!-- The core switch is the one device worth pinning to a specific rack unit. -->
|
|
<Placement InclusionExpression=".*-SW-0*1$" MatchBy="Hostname" Rack="RACK-01" StartU="42" HeightU="1" Face="front" RackSlot="full" Enabled="false" />
|
|
|
|
<!-- Everything else racks, except storage and anything explicitly excluded. -->
|
|
<Placement InclusionExpression=".*" ExclusionExpression=".*NAS.*|.*STORAGE.*" MatchBy="Hostname" Rack="RACK-01" HeightU="1" Face="front" RackSlot="full" Enabled="false" />
|
|
</Placements>
|
|
|
|
</Layout>
|
|
|
|
<Networking>
|
|
|
|
<!--
|
|
Address ranges become IP zones inside the subnet that the routed edge reported. The parent subnet must already be
|
|
discovered by a source; this document cannot create it. Kind accepts static, reserved, or infrastructure. A DHCP
|
|
kind is rejected and downgraded to static because DHCP is out of scope.
|
|
Room and Rack are recorded against the zone description so that the range stays attributable in the user interface.
|
|
-->
|
|
<IPRanges>
|
|
<IPRange Subnet="10.0.0.0/24" Kind="infrastructure" StartIP="10.0.0.1" EndIP="10.0.0.31" Description="Network equipment" Room="Server Room" Rack="RACK-01" Enabled="false" />
|
|
<IPRange Subnet="10.0.0.0/24" Kind="static" StartIP="10.0.0.32" EndIP="10.0.0.127" Description="Static server assignments" Room="Server Room" Enabled="false" />
|
|
<IPRange Subnet="10.0.0.0/24" Kind="reserved" StartIP="10.0.0.240" EndIP="10.0.0.254" Description="Reserved" Enabled="false" />
|
|
</IPRanges>
|
|
|
|
<!--
|
|
The public address lookup is an outbound request to a third party geolocation service. Only the request leaves the
|
|
environment; no inventory data is transmitted. The result is written as a slash thirty two subnet carrying the
|
|
internet service provider detail, and is attributed to EdgeHostname when supplied, otherwise to the first
|
|
discovered firewall or router.
|
|
ProviderURL understands the ipinfo.io and ip-api.com response shapes.
|
|
-->
|
|
<PublicIP Enabled="false" ProviderURL="https://ipinfo.io/json" EdgeHostname="" />
|
|
|
|
</Networking>
|
|
|
|
<Sources>
|
|
|
|
<!--
|
|
Omada. Two transports exist and the richer one is preferred.
|
|
|
|
Username and Password are a controller login and unlock the controller interface, which carries switch uplinks and
|
|
downlinks with both port numbers, per port LLDP neighbours, VLAN definitions with gateway subnets, and the real SSID
|
|
configuration. A Viewer role account is sufficient because nothing is ever written.
|
|
|
|
ClientID and ClientSecret are Open API credentials, created under Global View, Settings, Platform Integration, Open
|
|
API. This transport is a published, versioned contract but is narrower: no uplinks at all, and no SSID configuration,
|
|
which forces SSIDs to be inferred from whichever clients happen to be associated.
|
|
|
|
Supply both and the controller interface is used with the Open API held in reserve, so an expired session or a route a
|
|
given controller release does not implement costs only that request rather than the whole collection. Set
|
|
PreferControllerInterface to false to pin collection to the Open API. Supply only one and that one is used.
|
|
|
|
Controllers usually present a self signed certificate, so SkipCertificateCheck defaults to true.
|
|
Remove the Sites element entirely to process every site the credentials can reach.
|
|
-->
|
|
<Omada Enabled="false" BaseURL="$env:OMADA_API_BASE_URL" SkipCertificateCheck="true" PreferControllerInterface="true">
|
|
<ClientID><![CDATA[$env:OMADA_API_CLIENT_ID]]></ClientID>
|
|
<ClientSecret><![CDATA[$env:OMADA_API_CLIENT_SECRET]]></ClientSecret>
|
|
<Username><![CDATA[$env:OMADA_API_USERNAME]]></Username>
|
|
<Password><![CDATA[$env:OMADA_API_PASSWORD]]></Password>
|
|
<Sites>
|
|
<Site Name="Site Name" Enabled="false" />
|
|
</Sites>
|
|
</Omada>
|
|
|
|
<!--
|
|
UniFi Network. The same two transport arrangement as Omada, for the same reason.
|
|
|
|
Username and Password are a controller login and unlock the network interface, which carries per port media, LLDP
|
|
neighbours, uplinks with the remote port, network definitions with their subnets, and the real wireless configuration.
|
|
A read only administrator is sufficient because nothing is ever written.
|
|
|
|
APIKey is an integration API key, created under Settings, Control Plane, Integrations. That transport is published and
|
|
versioned but narrower, covering sites, devices, and clients without port or topology detail.
|
|
|
|
Supply both and the network interface is used with the integration API held in reserve. Set PreferControllerInterface
|
|
to false to pin collection to the integration API.
|
|
|
|
Both deployment styles are detected rather than configured. A UniFi OS host such as a Dream Machine, Cloud Key Gen2, or
|
|
UniFi OS Server signs in at /api/auth/login and proxies the network application beneath /proxy/network. An older self
|
|
hosted controller signs in at /api/login and serves it from the root, usually on port 8443.
|
|
|
|
Remove the Sites element entirely to process every site. Site names are matched against the description shown in the
|
|
user interface, or against the short site key.
|
|
-->
|
|
<Unifi Enabled="false" BaseURL="$env:UNIFI_API_BASE_URL" SkipCertificateCheck="true" PreferControllerInterface="true">
|
|
<Username><![CDATA[$env:UNIFI_API_USERNAME]]></Username>
|
|
<Password><![CDATA[$env:UNIFI_API_PASSWORD]]></Password>
|
|
<APIKey><![CDATA[$env:UNIFI_API_KEY]]></APIKey>
|
|
<Sites>
|
|
<Site Name="Default" Enabled="false" />
|
|
</Sites>
|
|
</Unifi>
|
|
|
|
<!--
|
|
Proxmox Virtual Environment. Create an API token under Datacenter, Permissions, API Tokens and grant it PVEAuditor
|
|
on the root path. TokenID uses the USER@REALM!TOKENNAME form.
|
|
|
|
List one endpoint per cluster and one per standalone host. Querying any single member of a cluster returns every node
|
|
in that cluster, so a five node cluster needs only one entry. Separate clusters cannot see one another, so each needs
|
|
its own entry with its own token. Name is a label; when supplied it overrides whatever the endpoint reports, which is
|
|
how a standalone host with no cluster name still reads sensibly. If two endpoints overlap and report the same node,
|
|
the duplicate is collapsed rather than written twice.
|
|
-->
|
|
<Proxmox Enabled="false">
|
|
<Endpoints>
|
|
<Endpoint Name="Cluster A" BaseURL="$env:PROXMOX_API_BASE_URL" SkipCertificateCheck="true" IncludeTemplates="false" Enabled="false">
|
|
<TokenID><![CDATA[$env:PROXMOX_API_TOKEN_ID]]></TokenID>
|
|
<TokenSecret><![CDATA[$env:PROXMOX_API_TOKEN_SECRET]]></TokenSecret>
|
|
</Endpoint>
|
|
<Endpoint Name="Standalone Host" BaseURL="" SkipCertificateCheck="true" IncludeTemplates="false" Enabled="false">
|
|
<TokenID><![CDATA[]]></TokenID>
|
|
<TokenSecret><![CDATA[]]></TokenSecret>
|
|
</Endpoint>
|
|
</Endpoints>
|
|
</Proxmox>
|
|
|
|
<!--
|
|
Hyper-V. Requires the Hyper-V module on the machine running this script. Hosts are reached through a CIM session,
|
|
so Username and Password are host credentials. Set UseDCOM when PowerShell remoting is unavailable.
|
|
|
|
The guest operating system is read from the integration services key value pair exchange, which works remotely and
|
|
needs no guest credential. UseGuestIntrospection additionally attempts PowerShell Direct for a more precise answer,
|
|
which only works when this script runs on the Hyper-V host itself and a guest credential is supplied.
|
|
-->
|
|
<HyperV Enabled="false" ClusterName="" UseDCOM="false" UseGuestIntrospection="false">
|
|
<Hosts>
|
|
<Host Name="HYPERVISOR-01" Enabled="false" />
|
|
</Hosts>
|
|
<Username><![CDATA[$env:HYPERV_USERNAME]]></Username>
|
|
<Password><![CDATA[$env:HYPERV_PASSWORD]]></Password>
|
|
<GuestUsername><![CDATA[$env:HYPERV_GUEST_USERNAME]]></GuestUsername>
|
|
<GuestPassword><![CDATA[$env:HYPERV_GUEST_PASSWORD]]></GuestPassword>
|
|
</HyperV>
|
|
|
|
<!--
|
|
OPNsense. Create the key and secret under System, Access, Users, then the API keys section of the user.
|
|
Hostname is the name that the firewall guest carries within its hypervisor, which is how the two sources are joined
|
|
so that the routed edge appears as a virtual device on its host rather than as a second unrelated record.
|
|
ParentHostname is only used when no hypervisor source is enabled and the firewall still needs a host to hang from.
|
|
-->
|
|
<OPNsense Enabled="false" BaseURL="$env:OPNSENSE_API_BASE_URL" SkipCertificateCheck="true" Hostname="" ParentHostname="">
|
|
<APIKey><![CDATA[$env:OPNSENSE_API_KEY]]></APIKey>
|
|
<APISecret><![CDATA[$env:OPNSENSE_API_SECRET]]></APISecret>
|
|
</OPNsense>
|
|
|
|
</Sources>
|
|
|
|
</Instance>
|
|
|
|
</Instances>
|
|
</RackpadPopulation>
|