Build BMH network config
This constructs a VM's BMH network config secret, based on a template. It also integrates IPAM functionality into the controller. TODOs for subsequent patchsets: - manage VM mac addresses. - implement replacement of e.g. $vino.nodebridgegw - confirm the nameservers definition below works (it's a different field than we use in hostgenerator-m3) The current patchset generates a networkData like so from the sample CRs: links: - id: management name: management type: bridge mtu: 1500 # ethernet_mac_address: ?? bridgeName: vminfra-bridge - id: external name: external type: sriov-bond mtu: 9100 # ethernet_mac_address: ?? bond_miimon: 100 bond_mode: 802.3ad bond_xmit_hash_policy: layer3+4 pf: [enp29s0f0,enp219s1f1] vlan: 100 networks: - id: management type: ipv4 link: management ip_address: 192.168.2.10 #netmask: "TODO - see if needed when ip has CIDR range" dns_nameservers: [135.188.34.124] routes: - network: 10.0.0.0 netmask: 255.255.255.0 gateway: $vino.nodebridgegw - id: external type: ipv4 link: external ip_address: 169.0.0.10 #netmask: "TODO - see if needed when ip has CIDR range" dns_nameservers: [] routes: - network: 0.0.0.0 netmask: 0.0.0.0 gateway: 169.0.0.1 Change-Id: I99b1a104764687c8b84f2495591e0712bed73ae5
This commit is contained in:
parent
e4d8d7d23b
commit
7dddf0f7d1
@ -97,14 +97,18 @@ spec:
|
||||
items:
|
||||
description: VMRoutes defined
|
||||
properties:
|
||||
to:
|
||||
gateway:
|
||||
type: string
|
||||
via:
|
||||
netmask:
|
||||
type: string
|
||||
network:
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
subnet:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
nodeSelector:
|
||||
@ -163,8 +167,7 @@ spec:
|
||||
description: Parameter for Node master or worker-standard
|
||||
type: string
|
||||
networkDataTemplate:
|
||||
description: NetworkDataTemplate reference a Secret containing
|
||||
a template key
|
||||
description: NetworkDataTemplate must have a template key
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
@ -172,22 +175,24 @@ spec:
|
||||
type: string
|
||||
type: object
|
||||
networkInterfaces:
|
||||
description: NetworkInterface define interface on the VM
|
||||
properties:
|
||||
mtu:
|
||||
type: integer
|
||||
name:
|
||||
description: Define parameter for network interfaces
|
||||
type: string
|
||||
network:
|
||||
type: string
|
||||
options:
|
||||
additionalProperties:
|
||||
items:
|
||||
description: NetworkInterface define interface on the VM
|
||||
properties:
|
||||
mtu:
|
||||
type: integer
|
||||
name:
|
||||
description: Define parameter for network interfaces
|
||||
type: string
|
||||
type: object
|
||||
type:
|
||||
type: string
|
||||
type: object
|
||||
network:
|
||||
type: string
|
||||
options:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
type:
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
type: array
|
||||
vmBridge:
|
||||
|
@ -32,6 +32,18 @@ rules:
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- airship.airshipit.org
|
||||
resources:
|
||||
- ippools
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- airship.airshipit.org
|
||||
resources:
|
||||
|
@ -1,3 +1,6 @@
|
||||
# Note: IPPools are intended to be created and managed by ViNO itself.
|
||||
# ViNO will perform IPAM based on end user input in the ViNO CR.
|
||||
# This resource here is just a reference.
|
||||
apiVersion: airship.airshipit.org/v1
|
||||
kind: IPPool
|
||||
metadata:
|
||||
|
@ -1,3 +1,9 @@
|
||||
# This template creates a cloud-init network configuration,
|
||||
# based upon these input values:
|
||||
#
|
||||
# .Node: the Node from a ViNO CR
|
||||
# .Networks: the list of Networks from a ViNO CR
|
||||
# .Generated: host-specific info generated/calculated by ViNO itself
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
@ -5,4 +11,40 @@ metadata:
|
||||
namespace: default
|
||||
type: Opaque
|
||||
stringData:
|
||||
template: REPLACEME
|
||||
template: |
|
||||
{{ $netToIface := dict }}
|
||||
links:
|
||||
{{- range .Node.NetworkInterfaces }}
|
||||
- id: {{ .Name }}
|
||||
name: {{ .Name }}
|
||||
type: {{ .Type }}
|
||||
mtu: {{ .MTU }}
|
||||
# ethernet_mac_address: ??
|
||||
{{- if .Options -}}
|
||||
{{ range $key, $val := .Options }}
|
||||
{{ $key }}: {{ $val }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- /* Save the network->interface mapping, needed below */ -}}
|
||||
{{- $_ := set $netToIface .NetworkName .Name }}
|
||||
{{- end }}
|
||||
networks:
|
||||
{{- range .Networks }}
|
||||
- id: {{ .Name }}
|
||||
type: {{ .Type }}
|
||||
link: {{ index $netToIface .Name }}
|
||||
ip_address: {{ index $.Generated.IPAddresses .Name }}
|
||||
#netmask: "TODO - see if needed when ip has CIDR range"
|
||||
dns_nameservers: {{ .DNSServers }}
|
||||
{{- if .Routes }}
|
||||
routes:
|
||||
{{- range .Routes }}
|
||||
- network: {{ .Network }}
|
||||
{{ if .Netmask }}netmask: {{ .Netmask }}{{ end }}
|
||||
gateway: {{ .Gateway }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
#services:
|
||||
# TODO: confirm dns_nameservers above does the trick here
|
||||
|
||||
|
@ -14,19 +14,24 @@ spec:
|
||||
networks:
|
||||
- name: management
|
||||
subnet: 192.168.2.0/20
|
||||
type: ipv4
|
||||
allocationStart: 192.168.2.10
|
||||
allocationStop: 192.168.2.14 # docs should specify that the range should = number of vms (to permit future expansion over multiple vino crs etc)
|
||||
routes:
|
||||
- to: 10.0.0.0/24
|
||||
via: $vino.nodebridgegw # vino will need to populate this from the nodelabel value `airshipit.org/vino.nodebridgegw`
|
||||
- network: 10.0.0.0
|
||||
netmask: 255.255.255.0
|
||||
gateway: $vino.nodebridgegw # vino will need to populate this from the nodelabel value `airshipit.org/vino.nodebridgegw`
|
||||
dns_servers: ["135.188.34.124"]
|
||||
- name: external
|
||||
subnet: 169.0.0.0/24
|
||||
type: ipv4
|
||||
routes:
|
||||
- to: 0.0.0.0/0
|
||||
via: 169.0.0.1
|
||||
- network: 0.0.0.0
|
||||
netmask: 0.0.0.0
|
||||
gateway: 169.0.0.1
|
||||
allocationStart: 169.0.0.10
|
||||
allocationStop: 169.0.0.254
|
||||
|
||||
vmBridge: lo
|
||||
nodes:
|
||||
- name: "worker"
|
||||
@ -34,6 +39,24 @@ spec:
|
||||
networkDataTemplate:
|
||||
name: "test-template"
|
||||
namespace: "default"
|
||||
networkInterfaces:
|
||||
- name: management
|
||||
type: bridge
|
||||
network: management
|
||||
mtu: 1500
|
||||
options:
|
||||
bridgeName: vminfra-bridge
|
||||
- name: external
|
||||
type: sriov-bond
|
||||
network: external
|
||||
mtu: 9100
|
||||
options:
|
||||
# this is an 'open-ended' set of k/v pairs, validation is perfomed by vino rather than crd schema.
|
||||
pf: "[enp29s0f0,enp219s1f1]"
|
||||
vlan: "100"
|
||||
bond_mode: 802.3ad
|
||||
bond_xmit_hash_policy: layer3+4
|
||||
bond_miimon: "100"
|
||||
bmcCredentials:
|
||||
username: "admin"
|
||||
password: "passw0rd"
|
||||
|
@ -541,6 +541,16 @@ string
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>type</code><br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>allocationStart</code><br>
|
||||
<em>
|
||||
string
|
||||
@ -756,7 +766,7 @@ NamespacedName
|
||||
<code>networkInterfaces</code><br>
|
||||
<em>
|
||||
<a href="#airship.airshipit.org/v1.NetworkInterface">
|
||||
NetworkInterface
|
||||
[]NetworkInterface
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
@ -785,7 +795,7 @@ NamespacedName
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>NetworkDataTemplate reference a Secret containing a template key</p>
|
||||
<p>NetworkDataTemplate must have a template key</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@ -883,7 +893,7 @@ map[string]string
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>to</code><br>
|
||||
<code>network</code><br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
@ -893,7 +903,17 @@ string
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>via</code><br>
|
||||
<code>netmask</code><br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>gateway</code><br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
|
6
go.mod
6
go.mod
@ -3,12 +3,16 @@ module vino
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/sprig v2.22.0+incompatible
|
||||
github.com/evanphx/json-patch v4.9.0+incompatible
|
||||
github.com/go-logr/logr v0.3.0
|
||||
github.com/go-logr/zapr v0.2.0
|
||||
github.com/metal3-io/baremetal-operator v0.0.0-20210111093319-93a6fd209b9a
|
||||
github.com/golang/mock v1.4.4
|
||||
github.com/huandu/xstrings v1.3.2 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/metal3-io/baremetal-operator v0.0.0-20210111093319-93a6fd209b9a
|
||||
github.com/mitchellh/copystructure v1.1.1 // indirect
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||
github.com/onsi/ginkgo v1.14.2
|
||||
github.com/onsi/gomega v1.10.2
|
||||
|
11
go.sum
11
go.sum
@ -53,7 +53,12 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/Djarvur/go-err113 v0.0.0-20200511133814-5174e21577d5/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs=
|
||||
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
|
||||
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||
github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60=
|
||||
github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
|
||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM=
|
||||
@ -368,6 +373,8 @@ github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0m
|
||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=
|
||||
github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
@ -444,6 +451,8 @@ github.com/metal3-io/baremetal-operator v0.0.0-20210111093319-93a6fd209b9a h1:Gx
|
||||
github.com/metal3-io/baremetal-operator v0.0.0-20210111093319-93a6fd209b9a/go.mod h1:ydVPYnA+ShdlzVn0DcrRWbhFJwo9OGuEFZJ2GWVSB10=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/copystructure v1.1.1 h1:Bp6x9R1Wn16SIz3OfeDr0b7RnCG2OB66Y7PQyC/cvq4=
|
||||
github.com/mitchellh/copystructure v1.1.1/go.mod h1:EBArHfARyrSWO/+Wyr9zwEkc6XMFB9XyNgFNmRkZZU4=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk=
|
||||
@ -453,6 +462,8 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE=
|
||||
github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
|
5
main.go
5
main.go
@ -32,6 +32,7 @@ import (
|
||||
|
||||
vinov1 "vino/pkg/api/v1"
|
||||
"vino/pkg/controllers"
|
||||
"vino/pkg/ipam"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -80,9 +81,13 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
ipammer := ipam.NewIpam(ctrl.Log.WithName("IPAM"), mgr.GetClient(),
|
||||
os.Getenv("RUNTIME_NAMESPACE"))
|
||||
|
||||
if err = (&controllers.VinoReconciler{
|
||||
Client: mgr.GetClient(),
|
||||
Scheme: mgr.GetScheme(),
|
||||
Ipam: ipammer,
|
||||
}).SetupWithManager(mgr); err != nil {
|
||||
setupLog.Error(err, "unable to create controller", "controller", "Vino")
|
||||
os.Exit(1)
|
||||
|
@ -44,7 +44,7 @@ type VinoSpec struct {
|
||||
// Define network parameters
|
||||
Networks []Network `json:"networks,omitempty"`
|
||||
// Define node details
|
||||
Node []NodeSet `json:"nodes,omitempty"`
|
||||
Nodes []NodeSet `json:"nodes,omitempty"`
|
||||
// DaemonSetOptions defines how vino will spawn daemonset on nodes
|
||||
DaemonSetOptions DaemonSetOptions `json:"daemonSetOptions,omitempty"`
|
||||
// VMBridge defines the single interface name to be used as a bridge for VMs
|
||||
@ -78,6 +78,7 @@ type Network struct {
|
||||
//Network Parameter defined
|
||||
Name string `json:"name,omitempty"`
|
||||
SubNet string `json:"subnet,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
AllocationStart string `json:"allocationStart,omitempty"`
|
||||
AllocationStop string `json:"allocationStop,omitempty"`
|
||||
DNSServers []string `json:"dns_servers,omitempty"`
|
||||
@ -86,20 +87,21 @@ type Network struct {
|
||||
|
||||
// VMRoutes defined
|
||||
type VMRoutes struct {
|
||||
To string `json:"to,omitempty"`
|
||||
Via string `json:"via,omitempty"`
|
||||
Network string `json:"network,omitempty"`
|
||||
Netmask string `json:"netmask,omitempty"`
|
||||
Gateway string `json:"gateway,omitempty"`
|
||||
}
|
||||
|
||||
//NodeSet node definitions
|
||||
type NodeSet struct {
|
||||
//Parameter for Node master or worker-standard
|
||||
Name string `json:"name,omitempty"`
|
||||
Count int `json:"count,omitempty"`
|
||||
NodeLabel VMNodeFlavor `json:"labels,omitempty"`
|
||||
LibvirtTemplate NamespacedName `json:"libvirtTemplate,omitempty"`
|
||||
NetworkInterface *NetworkInterface `json:"networkInterfaces,omitempty"`
|
||||
DiskDrives *DiskDrivesTemplate `json:"diskDrives,omitempty"`
|
||||
// NetworkDataTemplate reference a Secret containing a template key
|
||||
Name string `json:"name,omitempty"`
|
||||
Count int `json:"count,omitempty"`
|
||||
NodeLabel VMNodeFlavor `json:"labels,omitempty"`
|
||||
LibvirtTemplateDefinition NamespacedName `json:"libvirtTemplate,omitempty"`
|
||||
NetworkInterfaces []NetworkInterface `json:"networkInterfaces,omitempty"`
|
||||
DiskDrives *DiskDrivesTemplate `json:"diskDrives,omitempty"`
|
||||
// NetworkDataTemplate must have a template key
|
||||
NetworkDataTemplate NamespacedName `json:"networkDataTemplate,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -308,11 +308,13 @@ func (in *NodeSelector) DeepCopy() *NodeSelector {
|
||||
func (in *NodeSet) DeepCopyInto(out *NodeSet) {
|
||||
*out = *in
|
||||
in.NodeLabel.DeepCopyInto(&out.NodeLabel)
|
||||
out.LibvirtTemplate = in.LibvirtTemplate
|
||||
if in.NetworkInterface != nil {
|
||||
in, out := &in.NetworkInterface, &out.NetworkInterface
|
||||
*out = new(NetworkInterface)
|
||||
(*in).DeepCopyInto(*out)
|
||||
out.LibvirtTemplateDefinition = in.LibvirtTemplateDefinition
|
||||
if in.NetworkInterfaces != nil {
|
||||
in, out := &in.NetworkInterfaces, &out.NetworkInterfaces
|
||||
*out = make([]NetworkInterface, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.DiskDrives != nil {
|
||||
in, out := &in.DiskDrives, &out.DiskDrives
|
||||
@ -463,8 +465,8 @@ func (in *VinoSpec) DeepCopyInto(out *VinoSpec) {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.Node != nil {
|
||||
in, out := &in.Node, &out.Node
|
||||
if in.Nodes != nil {
|
||||
in, out := &in.Nodes, &out.Nodes
|
||||
*out = make([]NodeSet, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
@ -22,6 +20,7 @@ import (
|
||||
"fmt"
|
||||
"text/template"
|
||||
|
||||
"github.com/Masterminds/sprig"
|
||||
"github.com/go-logr/logr"
|
||||
metal3 "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
@ -32,8 +31,20 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
vinov1 "vino/pkg/api/v1"
|
||||
"vino/pkg/ipam"
|
||||
)
|
||||
|
||||
type networkTemplateValues struct {
|
||||
Node vinov1.NodeSet // the specific node type to be templated
|
||||
BMHName string
|
||||
Networks []vinov1.Network
|
||||
Generated generatedValues // Host-specific values calculated by ViNO: IP, etc
|
||||
}
|
||||
|
||||
type generatedValues struct {
|
||||
IPAddresses map[string]string // a map of network names to IP addresses
|
||||
}
|
||||
|
||||
func (r *VinoReconciler) ensureBMHs(ctx context.Context, vino *vinov1.Vino) error {
|
||||
labelOpt := client.MatchingLabels{
|
||||
vinov1.VinoLabelDSNameSelector: vino.Name,
|
||||
@ -56,7 +67,11 @@ func (r *VinoReconciler) ensureBMHs(ctx context.Context, vino *vinov1.Vino) erro
|
||||
"pod name",
|
||||
types.NamespacedName{Namespace: pod.Namespace, Name: pod.Name},
|
||||
)
|
||||
err := r.createBMHperPod(ctx, vino, pod)
|
||||
err := r.createIpamNetworks(ctx, vino)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = r.createBMHperPod(ctx, vino, pod)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -101,8 +116,22 @@ func (r *VinoReconciler) reconcileBMHs(ctx context.Context, vino *vinov1.Vino) e
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *VinoReconciler) createIpamNetworks(ctx context.Context, vino *vinov1.Vino) error {
|
||||
for _, network := range vino.Spec.Networks {
|
||||
subnetRange, err := ipam.NewRange(network.AllocationStart, network.AllocationStop)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = r.Ipam.AddSubnetRange(ctx, network.SubNet, subnetRange)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *VinoReconciler) createBMHperPod(ctx context.Context, vino *vinov1.Vino, pod corev1.Pod) error {
|
||||
for _, node := range vino.Spec.Node {
|
||||
for _, node := range vino.Spec.Nodes {
|
||||
logger := logr.FromContext(ctx)
|
||||
logger.Info("Creating BMHs for vino node", "node name", node.Name, "count", node.Count)
|
||||
prefix := r.getBMHNodePrefix(vino, pod)
|
||||
@ -115,7 +144,43 @@ func (r *VinoReconciler) createBMHperPod(ctx context.Context, vino *vinov1.Vino,
|
||||
return err
|
||||
}
|
||||
|
||||
netData, netDataNs, err := r.reconcileBMHNetworkData(ctx, node, vino, nil)
|
||||
// Allocate an IP for each of this BMH's network interfaces
|
||||
ipAddresses := map[string]string{}
|
||||
for _, iface := range node.NetworkInterfaces {
|
||||
networkName := iface.NetworkName
|
||||
subnet := ""
|
||||
subnetRange := vinov1.Range{}
|
||||
for _, network := range vino.Spec.Networks {
|
||||
if network.Name == networkName {
|
||||
subnet = network.SubNet
|
||||
subnetRange, err = ipam.NewRange(network.AllocationStart,
|
||||
network.AllocationStop)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
if subnet == "" {
|
||||
return fmt.Errorf("Interface %s doesn't have a matching network defined", networkName)
|
||||
}
|
||||
ipAllocatedTo := fmt.Sprintf("%s/%s", bmhName, iface.NetworkName)
|
||||
ipAddress, er := r.Ipam.AllocateIP(ctx, subnet, subnetRange, ipAllocatedTo)
|
||||
if er != nil {
|
||||
return er
|
||||
}
|
||||
ipAddresses[networkName] = ipAddress
|
||||
}
|
||||
|
||||
values := networkTemplateValues{
|
||||
Node: node,
|
||||
BMHName: bmhName,
|
||||
Networks: vino.Spec.Networks,
|
||||
Generated: generatedValues{
|
||||
IPAddresses: ipAddresses,
|
||||
},
|
||||
}
|
||||
netData, netDataNs, err := r.reconcileBMHNetworkData(ctx, node, vino, values)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -213,7 +278,7 @@ func (r *VinoReconciler) reconcileBMHNetworkData(
|
||||
ctx context.Context,
|
||||
node vinov1.NodeSet,
|
||||
vino *vinov1.Vino,
|
||||
values interface{}) (string, string, error) {
|
||||
values networkTemplateValues) (string, string, error) {
|
||||
secret := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: node.NetworkDataTemplate.Name,
|
||||
@ -234,7 +299,7 @@ func (r *VinoReconciler) reconcileBMHNetworkData(
|
||||
return "", "", fmt.Errorf("network template secret %v has no key '%s'", objKey, TemplateDefaultKey)
|
||||
}
|
||||
|
||||
tpl, err := template.New("net-template").Parse(string(rawTmpl))
|
||||
tpl, err := template.New("net-template").Funcs(sprig.TxtFuncMap()).Parse(string(rawTmpl))
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
@ -245,7 +310,7 @@ func (r *VinoReconciler) reconcileBMHNetworkData(
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
name := fmt.Sprintf("%s-%s-%s", vino.Namespace, vino.Name, node.Name)
|
||||
name := fmt.Sprintf("%s-network-data", values.BMHName)
|
||||
|
||||
ns := getRuntimeNamespace()
|
||||
netSecret := &corev1.Secret{
|
||||
|
@ -40,7 +40,7 @@ var _ = Describe("Test BMH reconciliation", func() {
|
||||
os.Setenv("RUNTIME_NAMESPACE", "vino-system")
|
||||
defer os.Unsetenv("RUNTIME_NAMESPACE")
|
||||
vino := testVINO()
|
||||
vino.Spec.Node = []vinov1.NodeSet{
|
||||
vino.Spec.Nodes = []vinov1.NodeSet{
|
||||
{
|
||||
Name: "worker",
|
||||
Count: 3,
|
||||
@ -141,7 +141,7 @@ var _ = Describe("Test BMH reconciliation", func() {
|
||||
|
||||
networkSecret := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "default-vino-worker",
|
||||
Name: "default-vino-node01-worker-0-network-data",
|
||||
Namespace: "vino-system",
|
||||
},
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ import (
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
vinov1 "vino/pkg/api/v1"
|
||||
"vino/pkg/ipam"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -53,10 +54,12 @@ const (
|
||||
type VinoReconciler struct {
|
||||
client.Client
|
||||
Scheme *runtime.Scheme
|
||||
Ipam *ipam.Ipam
|
||||
}
|
||||
|
||||
// +kubebuilder:rbac:groups=airship.airshipit.org,resources=vinoes,verbs=get;list;watch;create;update;patch;delete
|
||||
// +kubebuilder:rbac:groups=airship.airshipit.org,resources=vinoes/status,verbs=get;update;patch
|
||||
// +kubebuilder:rbac:groups=airship.airshipit.org,resources=ippools,verbs=get;list;watch;create;update;patch;delete
|
||||
// +kubebuilder:rbac:groups="",resources=pods,verbs=list;watch
|
||||
// +kubebuilder:rbac:groups="",resources=nodes,verbs=get;list;watch
|
||||
// +kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch;create;update;patch
|
||||
|
@ -50,5 +50,6 @@ bmhCount=$(kubectl get baremetalhosts -n vino-system -o name | wc -l)
|
||||
|
||||
[[ "$bmhCount" -eq "3" ]]
|
||||
|
||||
kubectl get secret -o yaml -n vino-system default-vino-test-cr-worker
|
||||
kubectl get -o yaml -n vino-system \
|
||||
$(kubectl get secret -o name -n vino-system | grep network-data)
|
||||
kubectl get secret -o yaml -n vino-system default-vino-test-cr-credentials
|
||||
|
Loading…
Reference in New Issue
Block a user