The compute rack
Read the compute rack, a 42U rack built from other designs, and add it and the designs it uses to the catalogue.
The compute rack is a 42U rack for the site you created in A second design. It holds a top-of-rack switch with a 10G uplink module, ten servers with a 10G network card each, and the cables between them: two data cables and a management cable from each server to the switch.
On a NetBox that has none of its types yet, the rack is 271 objects: the rack itself, eleven devices and their modules, their interfaces, power ports, console ports and module bays, 30 cables, and the device types, module types, rack type, roles and manufacturers they need. You write about 60 lines of YAML for it, because the rack is built from other designs.
The designs it uses
The rack uses two device designs from the catalogue: one for the switch and one for each server. Add them first, because the catalogue refuses a design whose parts it doesn't have, and it says so for every place the part is used.
Add this one as devices/Cisco_3850_w_module, the way you added the first two designs:
name: Cisco_3850_w_module
netbox_versions: ["4.6.*", "4.7.*"]
description: Cisco Catalyst 3850-48P with 4x10G Network Module
variables:
name: $USER
slug: $USER
position: $USER_OPTIONAL
face: $USER_OPTIONAL
status: $USER
serial: $USER_OPTIONAL
site: $USER
rack: $USER_OPTIONAL
infra:
- infra_type: Device
name: '{{ variables.name }}'
slug: '{{ variables.slug }}'
position: '{{ variables.position }}'
face: '{{ variables.face }}'
status: '{{ variables.status }}'
serial: '{{ variables.serial }}'
site: '{{ variables.site }}'
role:
infra_type: DeviceRole
name: TOR Switch
slug: tor-switch
color: 2196f3
rack: '{{ variables.rack }}'
device_type: 'dtl:device-types/Cisco/WS-C3850-48P-E.yaml@fdf12828'
modules:
- infra_type: Module
device: '{{ parent }}'
module_bay: '{{ nbd.nbt.get_module_bay(parent, 1) }}'
module_type: 'dtl:module-types/Cisco/C3850-NM-4-10G.yaml@fdf12828'
module_position: 1And this one as devices/Dell_R640_w_module:
name: Dell_R640_w_module
netbox_versions: ["4.6.*", "4.7.*"]
description: Dell PowerEdge R640 with Intel X710-DA4 10GbE NIC
variables:
name: $USER
slug: $USER
position: $USER_OPTIONAL
face: $USER_OPTIONAL
status: $USER
serial: $USER_OPTIONAL
site: $USER
rack: $USER_OPTIONAL
infra:
- infra_type: Device
name: '{{ variables.name }}'
slug: '{{ variables.slug }}'
position: '{{ variables.position }}'
face: '{{ variables.face }}'
status: '{{ variables.status }}'
serial: '{{ variables.serial }}'
site: '{{ variables.site }}'
role:
infra_type: DeviceRole
name: Compute Server
slug: compute-server
color: 4caf50
rack: '{{ variables.rack }}'
device_type: 'dtl:device-types/Dell/PowerEdge-R640.yaml@fdf12828'
modules:
- infra_type: Module
device: '{{ parent }}'
module_bay: "{{ nbd.nbt.get_module_bay(parent, 'PCIE1') }}"
module_type: 'dtl:module-types/Intel/X710-DA4.yaml@fdf12828'
module_position: PCIE1Each describes one device with its role, its device type and the module in it. The device type and module type come from the NetBox Device Type Library: dtl:device-types/Dell/PowerEdge-R640.yaml@fdf12828 brings in the PowerEdge R640 exactly as the library defines it at that commit, with its interfaces, power ports and module bays. The @fdf12828 pins the library at one commit, so the design builds the same device type next year as today.
Check the catalogue name as you add each: devices/Dell_R640_w_module must hold the Dell YAML. The catalogue takes whatever you paste under whatever name you give it, and a rack built from the wrong file fails later, at a cable that can't find the port it expects.
The rack
Add this as tutorial/compute_rack:
name: Compute Rack
netbox_versions: ["4.6.*", "4.7.*"]
description: A 42U compute rack in an existing site, with a top-of-rack switch, ten servers and their cabling.
variables:
rack_name: $USER
site_slug: $USER
status: active
infra:
- infra_type: Rack
name: '{{ variables.rack_name }}'
site: '{{ variables.site_slug }}'
rack_type: dtl:rack-types/APC/AR3350.yaml@fdf12828
status: '{{ variables.status }}'
devices:
- design: nbd:devices/Cisco_3850_w_module
template_vars:
name: '{{ variables.rack_name }}-TOR-01'
slug: '{{ variables.rack_name }}-tor-01'
position: 42
face: front
status: active
site: '{{ parent.site }}'
rack: '{{ parent }}'
- nbd_loop:
over: {start: 1, end: 10}
as: i
design: nbd:devices/Dell_R640_w_module
template_vars:
name: '{{ variables.rack_name }}-COMPUTE-{{ loop.i | zeropad }}'
slug: '{{ variables.rack_name }}-compute-{{ loop.i | zeropad }}'
position: '{{ loop.i }}'
face: front
status: active
site: '{{ parent.site }}'
rack: '{{ parent }}'
cables:
- nbd_loop:
over: {start: 1, end: 10}
as: i
items:
- infra_type: Cable
label: '{{ variables.rack_name }}-COMPUTE-{{ loop.i | zeropad }}-DATA-A'
type: cat6a
status: connected
termination_a: "{{ nbd.lookup.endpoint('{{ variables.rack_name }}-COMPUTE-{{ loop.i | zeropad }}', 'Interface', 'Ethernet/PCIE1/1') }}"
termination_b: "{{ nbd.lookup.endpoint('{{ variables.rack_name }}-TOR-01', 'Interface', 'GigabitEthernet1/0/{{ loop.i * 2 - 1 }}') }}"
- infra_type: Cable
label: '{{ variables.rack_name }}-COMPUTE-{{ loop.i | zeropad }}-DATA-B'
type: cat6a
status: connected
termination_a: "{{ nbd.lookup.endpoint('{{ variables.rack_name }}-COMPUTE-{{ loop.i | zeropad }}', 'Interface', 'Ethernet/PCIE1/2') }}"
termination_b: "{{ nbd.lookup.endpoint('{{ variables.rack_name }}-TOR-01', 'Interface', 'GigabitEthernet1/0/{{ loop.i * 2 }}') }}"
- nbd_loop:
over: {start: 1, end: 10}
as: i
infra_type: Cable
label: '{{ variables.rack_name }}-COMPUTE-{{ loop.i | zeropad }}-MGMT'
type: cat6
status: connected
termination_a: "{{ nbd.lookup.endpoint('{{ variables.rack_name }}-COMPUTE-{{ loop.i | zeropad }}', 'Interface', 'iDRAC9') }}"
termination_b: "{{ nbd.lookup.endpoint('{{ variables.rack_name }}-TOR-01', 'Interface', 'GigabitEthernet1/0/{{ loop.i + 20 }}') }}"Reading it from the top:
- The rack takes two variables you give when you plan,
rack_nameandsite_slug, and a defaultstatus. - The rack's type comes from the Device Type Library, like the device types.
devicesplaces the switch at the top of the rack and the ten servers below it, each built by its device design.nbd_looprepeats the server ten times, numbering them 01 to 10.cablesconnects each server's two data ports and its management port to the switch, using a function to find each port.
Each of these has a Concepts page if you want the detail now: Composition, Variables and Functions. The tutorial carries on without them.
Check a design before you add it
The catalogue checks a design's references when you add it, not what it builds. nbd validate <file> in the CLI checks the file offline: its structure, its variables, that every function it calls exists and, given the NetBox version of your target (--netbox-version 4.7.0), that every object type is one that NetBox has. See Write your own designs.