Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion api/v1alpha1/ironic_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,18 @@ type Inspection struct {
VLANInterfaces []string `json:"vlanInterfaces,omitempty"`
}

// DHCPRange defines a DHCP range for a subnet served via DHCP relay agents.
type DHCPRange struct {
// NetworkCIDR is the CIDR of the subnet. Required.
NetworkCIDR string `json:"networkCIDR"`

// RangeBegin is the first IP that can be given to hosts. Must be inside NetworkCIDR.
RangeBegin string `json:"rangeBegin"`

// RangeEnd is the last IP that can be given to hosts. Must be inside NetworkCIDR.
RangeEnd string `json:"rangeEnd"`
}

type DHCP struct {
// DNSAddress is the IP address of the DNS server to pass to hosts via DHCP.
// Must not be set together with ServeDNS.
Expand All @@ -75,15 +87,29 @@ type DHCP struct {
// +optional
Ignore []string `json:"ignore,omitempty"`

// NetworkCIDR is a CIDR of the provisioning network. Required.
// NetworkCIDR is a CIDR of the provisioning network.
//
// Deprecated: use NetworkRanges instead.
// +optional
NetworkCIDR string `json:"networkCIDR,omitempty"`

// RangeBegin is the first IP that can be given to hosts. Must be inside NetworkCIDR.
//
// Deprecated: use NetworkRanges instead.
// +optional
RangeBegin string `json:"rangeBegin,omitempty"`

// RangeEnd is the last IP that can be given to hosts. Must be inside NetworkCIDR.
//
// Deprecated: use NetworkRanges instead.
// +optional
RangeEnd string `json:"rangeEnd,omitempty"`

// NetworkRanges is a list of additional DHCP ranges for subnets served via DHCP relay agents.
// Each range defines a separate subnet. The provisioning IP does not need to be within these subnets.
// +optional
NetworkRanges []DHCPRange `json:"networkRanges,omitempty"`

// ServeDNS is set to true to pass the provisioning host as the DNS server on the provisioning network.
// Must not be set together with DNSAddress.
// +optional
Expand Down
20 changes: 20 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 38 additions & 6 deletions config/crd/bases/ironic.metal3.io_ironics.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -220,16 +220,48 @@ spec:
type: string
type: array
networkCIDR:
description: NetworkCIDR is a CIDR of the provisioning network.
Required.
description: |-
NetworkCIDR is a CIDR of the provisioning network.

Deprecated: use NetworkRanges instead.
type: string
networkRanges:
description: |-
NetworkRanges is a list of additional DHCP ranges for subnets served via DHCP relay agents.
Each range defines a separate subnet. The provisioning IP does not need to be within these subnets.
items:
description: DHCPRange defines a DHCP range for a subnet
served via DHCP relay agents.
properties:
networkCIDR:
description: NetworkCIDR is the CIDR of the subnet.
Required.
type: string
rangeBegin:
description: RangeBegin is the first IP that can be
given to hosts. Must be inside NetworkCIDR.
type: string
rangeEnd:
description: RangeEnd is the last IP that can be given
to hosts. Must be inside NetworkCIDR.
type: string
required:
- networkCIDR
- rangeBegin
- rangeEnd
type: object
type: array
rangeBegin:
description: RangeBegin is the first IP that can be given
to hosts. Must be inside NetworkCIDR.
description: |-
RangeBegin is the first IP that can be given to hosts. Must be inside NetworkCIDR.

Deprecated: use NetworkRanges instead.
type: string
rangeEnd:
description: RangeEnd is the last IP that can be given to
hosts. Must be inside NetworkCIDR.
description: |-
RangeEnd is the last IP that can be given to hosts. Must be inside NetworkCIDR.

Deprecated: use NetworkRanges instead.
type: string
serveDNS:
description: |-
Expand Down
61 changes: 58 additions & 3 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -612,21 +612,35 @@ There is no API-side validation. Most users will leave this unset.<br/>
<td><b>networkCIDR</b></td>
<td>string</td>
<td>
NetworkCIDR is a CIDR of the provisioning network. Required.<br/>
NetworkCIDR is a CIDR of the provisioning network.

Deprecated: use NetworkRanges instead.<br/>
</td>
<td>false</td>
</tr><tr>
<td><b><a href="#ironicspecnetworkingdhcpnetworkrangesindex">networkRanges</a></b></td>
<td>[]object</td>
<td>
NetworkRanges is a list of additional DHCP ranges for subnets served via DHCP relay agents.
Each range defines a separate subnet. The provisioning IP does not need to be within these subnets.<br/>
</td>
<td>false</td>
</tr><tr>
<td><b>rangeBegin</b></td>
<td>string</td>
<td>
RangeBegin is the first IP that can be given to hosts. Must be inside NetworkCIDR.<br/>
RangeBegin is the first IP that can be given to hosts. Must be inside NetworkCIDR.

Deprecated: use NetworkRanges instead.<br/>
</td>
<td>false</td>
</tr><tr>
<td><b>rangeEnd</b></td>
<td>string</td>
<td>
RangeEnd is the last IP that can be given to hosts. Must be inside NetworkCIDR.<br/>
RangeEnd is the last IP that can be given to hosts. Must be inside NetworkCIDR.

Deprecated: use NetworkRanges instead.<br/>
</td>
<td>false</td>
</tr><tr>
Expand All @@ -641,6 +655,47 @@ Must not be set together with DNSAddress.<br/>
</table>


### Ironic.spec.networking.dhcp.networkRanges[index]
<sup><sup>[↩ Parent](#ironicspecnetworkingdhcp)</sup></sup>



DHCPRange defines a DHCP range for a subnet served via DHCP relay agents.

<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
<th>Required</th>
</tr>
</thead>
<tbody><tr>
<td><b>networkCIDR</b></td>
<td>string</td>
<td>
NetworkCIDR is the CIDR of the subnet. Required.<br/>
</td>
<td>true</td>
</tr><tr>
<td><b>rangeBegin</b></td>
<td>string</td>
<td>
RangeBegin is the first IP that can be given to hosts. Must be inside NetworkCIDR.<br/>
</td>
<td>true</td>
</tr><tr>
<td><b>rangeEnd</b></td>
<td>string</td>
<td>
RangeEnd is the last IP that can be given to hosts. Must be inside NetworkCIDR.<br/>
</td>
<td>true</td>
</tr></tbody>
</table>


### Ironic.spec.overrides
<sup><sup>[↩ Parent](#ironicspec)</sup></sup>

Expand Down
23 changes: 19 additions & 4 deletions pkg/ironic/containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -506,12 +506,27 @@ func buildIronicHttpdPorts(ironic *metal3api.Ironic) (ironicPorts []corev1.Conta
}

func buildDHCPRange(dhcp *metal3api.DHCP) string {
prefix, err := netip.ParsePrefix(dhcp.NetworkCIDR)
if err != nil {
return "" // don't disable your webhooks people
parts := make([]string, 0, len(dhcp.NetworkRanges)+1)

// Primary range (from deprecated flat fields)
//nolint:staticcheck // backward compat with deprecated flat DHCP fields
if dhcp.NetworkCIDR != "" && dhcp.RangeBegin != "" && dhcp.RangeEnd != "" {
prefix, err := netip.ParsePrefix(dhcp.NetworkCIDR) //nolint:staticcheck // backward compat with deprecated flat DHCP fields
if err == nil {
parts = append(parts, fmt.Sprintf("%s,%s,%d", dhcp.RangeBegin, dhcp.RangeEnd, prefix.Bits())) //nolint:staticcheck // backward compat with deprecated flat DHCP fields
}
}

// Additional network ranges
for _, r := range dhcp.NetworkRanges {
prefix, err := netip.ParsePrefix(r.NetworkCIDR)
if err != nil {
continue
}
parts = append(parts, fmt.Sprintf("%s,%s,%d", r.RangeBegin, r.RangeEnd, prefix.Bits()))
}

return fmt.Sprintf("%s,%s,%d", dhcp.RangeBegin, dhcp.RangeEnd, prefix.Bits())
return strings.Join(parts, ";")
}

func buildDNSIP(dhcp *metal3api.DHCP) string {
Expand Down
82 changes: 82 additions & 0 deletions pkg/ironic/containers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,88 @@ func TestIronicPortEnvVars(t *testing.T) {
}
}

func TestBuildDHCPRange(t *testing.T) {
testCases := []struct {
name string
dhcp *metal3api.DHCP
expected string
}{
{
name: "primary range only",
dhcp: &metal3api.DHCP{
NetworkCIDR: "192.168.1.0/24",
RangeBegin: "192.168.1.10",
RangeEnd: "192.168.1.200",
},
expected: "192.168.1.10,192.168.1.200,24",
},
{
name: "networkRanges only",
dhcp: &metal3api.DHCP{
NetworkRanges: []metal3api.DHCPRange{
{
NetworkCIDR: "192.168.1.0/24",
RangeBegin: "192.168.1.10",
RangeEnd: "192.168.1.200",
},
{
NetworkCIDR: "192.168.2.0/24",
RangeBegin: "192.168.2.10",
RangeEnd: "192.168.2.200",
},
},
},
expected: "192.168.1.10,192.168.1.200,24;192.168.2.10,192.168.2.200,24",
},
{
name: "primary range and networkRanges combined",
dhcp: &metal3api.DHCP{
NetworkCIDR: "10.0.0.0/16",
RangeBegin: "10.0.1.1",
RangeEnd: "10.0.1.254",
NetworkRanges: []metal3api.DHCPRange{
{
NetworkCIDR: "192.168.1.0/24",
RangeBegin: "192.168.1.10",
RangeEnd: "192.168.1.200",
},
},
},
expected: "10.0.1.1,10.0.1.254,16;192.168.1.10,192.168.1.200,24",
},
{
name: "IPv6 networkRanges",
dhcp: &metal3api.DHCP{
NetworkRanges: []metal3api.DHCPRange{
{
NetworkCIDR: "fd69:158d:692a:1::/64",
RangeBegin: "fd69:158d:692a:1::3000",
RangeEnd: "fd69:158d:692a:1::3fff",
},
{
NetworkCIDR: "fd69:158d:692a:2::/64",
RangeBegin: "fd69:158d:692a:2::3000",
RangeEnd: "fd69:158d:692a:2::3fff",
},
},
},
expected: "fd69:158d:692a:1::3000,fd69:158d:692a:1::3fff,64;fd69:158d:692a:2::3000,fd69:158d:692a:2::3fff,64",
},
{
name: "empty DHCP",
dhcp: &metal3api.DHCP{},
expected: "",
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
result := buildDHCPRange(tc.dhcp)
assert.Equal(t, tc.expected, result)
})
}
}

func TestPrometheusExporterEnvVars(t *testing.T) {
testCases := []struct {
name string
Expand Down
Loading
Loading