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:
|
items:
|
||||||
description: VMRoutes defined
|
description: VMRoutes defined
|
||||||
properties:
|
properties:
|
||||||
to:
|
gateway:
|
||||||
type: string
|
type: string
|
||||||
via:
|
netmask:
|
||||||
|
type: string
|
||||||
|
network:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
type: array
|
type: array
|
||||||
subnet:
|
subnet:
|
||||||
type: string
|
type: string
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
type: object
|
type: object
|
||||||
type: array
|
type: array
|
||||||
nodeSelector:
|
nodeSelector:
|
||||||
@ -163,8 +167,7 @@ spec:
|
|||||||
description: Parameter for Node master or worker-standard
|
description: Parameter for Node master or worker-standard
|
||||||
type: string
|
type: string
|
||||||
networkDataTemplate:
|
networkDataTemplate:
|
||||||
description: NetworkDataTemplate reference a Secret containing
|
description: NetworkDataTemplate must have a template key
|
||||||
a template key
|
|
||||||
properties:
|
properties:
|
||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
@ -172,22 +175,24 @@ spec:
|
|||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
networkInterfaces:
|
networkInterfaces:
|
||||||
description: NetworkInterface define interface on the VM
|
items:
|
||||||
properties:
|
description: NetworkInterface define interface on the VM
|
||||||
mtu:
|
properties:
|
||||||
type: integer
|
mtu:
|
||||||
name:
|
type: integer
|
||||||
description: Define parameter for network interfaces
|
name:
|
||||||
type: string
|
description: Define parameter for network interfaces
|
||||||
network:
|
|
||||||
type: string
|
|
||||||
options:
|
|
||||||
additionalProperties:
|
|
||||||
type: string
|
type: string
|
||||||
type: object
|
network:
|
||||||
type:
|
type: string
|
||||||
type: string
|
options:
|
||||||
type: object
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
type: object
|
type: object
|
||||||
type: array
|
type: array
|
||||||
vmBridge:
|
vmBridge:
|
||||||
|
@ -32,6 +32,18 @@ rules:
|
|||||||
- patch
|
- patch
|
||||||
- update
|
- update
|
||||||
- watch
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- airship.airshipit.org
|
||||||
|
resources:
|
||||||
|
- ippools
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- airship.airshipit.org
|
- airship.airshipit.org
|
||||||
resources:
|
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
|
apiVersion: airship.airshipit.org/v1
|
||||||
kind: IPPool
|
kind: IPPool
|
||||||
metadata:
|
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
|
apiVersion: v1
|
||||||
kind: Secret
|
kind: Secret
|
||||||
metadata:
|
metadata:
|
||||||
@ -5,4 +11,40 @@ metadata:
|
|||||||
namespace: default
|
namespace: default
|
||||||
type: Opaque
|
type: Opaque
|
||||||
stringData:
|
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:
|
networks:
|
||||||
- name: management
|
- name: management
|
||||||
subnet: 192.168.2.0/20
|
subnet: 192.168.2.0/20
|
||||||
|
type: ipv4
|
||||||
allocationStart: 192.168.2.10
|
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)
|
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:
|
routes:
|
||||||
- to: 10.0.0.0/24
|
- network: 10.0.0.0
|
||||||
via: $vino.nodebridgegw # vino will need to populate this from the nodelabel value `airshipit.org/vino.nodebridgegw`
|
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"]
|
dns_servers: ["135.188.34.124"]
|
||||||
- name: external
|
- name: external
|
||||||
subnet: 169.0.0.0/24
|
subnet: 169.0.0.0/24
|
||||||
|
type: ipv4
|
||||||
routes:
|
routes:
|
||||||
- to: 0.0.0.0/0
|
- network: 0.0.0.0
|
||||||
via: 169.0.0.1
|
netmask: 0.0.0.0
|
||||||
|
gateway: 169.0.0.1
|
||||||
allocationStart: 169.0.0.10
|
allocationStart: 169.0.0.10
|
||||||
allocationStop: 169.0.0.254
|
allocationStop: 169.0.0.254
|
||||||
|
|
||||||
vmBridge: lo
|
vmBridge: lo
|
||||||
nodes:
|
nodes:
|
||||||
- name: "worker"
|
- name: "worker"
|
||||||
@ -34,6 +39,24 @@ spec:
|
|||||||
networkDataTemplate:
|
networkDataTemplate:
|
||||||
name: "test-template"
|
name: "test-template"
|
||||||
namespace: "default"
|
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:
|
bmcCredentials:
|
||||||
username: "admin"
|
username: "admin"
|
||||||
password: "passw0rd"
|
password: "passw0rd"
|
||||||
|
@ -541,6 +541,16 @@ string
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
|
<code>type</code><br>
|
||||||
|
<em>
|
||||||
|
string
|
||||||
|
</em>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
<code>allocationStart</code><br>
|
<code>allocationStart</code><br>
|
||||||
<em>
|
<em>
|
||||||
string
|
string
|
||||||
@ -756,7 +766,7 @@ NamespacedName
|
|||||||
<code>networkInterfaces</code><br>
|
<code>networkInterfaces</code><br>
|
||||||
<em>
|
<em>
|
||||||
<a href="#airship.airshipit.org/v1.NetworkInterface">
|
<a href="#airship.airshipit.org/v1.NetworkInterface">
|
||||||
NetworkInterface
|
[]NetworkInterface
|
||||||
</a>
|
</a>
|
||||||
</em>
|
</em>
|
||||||
</td>
|
</td>
|
||||||
@ -785,7 +795,7 @@ NamespacedName
|
|||||||
</em>
|
</em>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<p>NetworkDataTemplate reference a Secret containing a template key</p>
|
<p>NetworkDataTemplate must have a template key</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
@ -883,7 +893,7 @@ map[string]string
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<code>to</code><br>
|
<code>network</code><br>
|
||||||
<em>
|
<em>
|
||||||
string
|
string
|
||||||
</em>
|
</em>
|
||||||
@ -893,7 +903,17 @@ string
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<code>via</code><br>
|
<code>netmask</code><br>
|
||||||
|
<em>
|
||||||
|
string
|
||||||
|
</em>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<code>gateway</code><br>
|
||||||
<em>
|
<em>
|
||||||
string
|
string
|
||||||
</em>
|
</em>
|
||||||
|
6
go.mod
6
go.mod
@ -3,12 +3,16 @@ module vino
|
|||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
require (
|
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/evanphx/json-patch v4.9.0+incompatible
|
||||||
github.com/go-logr/logr v0.3.0
|
github.com/go-logr/logr v0.3.0
|
||||||
github.com/go-logr/zapr v0.2.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/golang/mock v1.4.4
|
||||||
|
github.com/huandu/xstrings v1.3.2 // indirect
|
||||||
github.com/kr/text v0.2.0 // 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/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||||
github.com/onsi/ginkgo v1.14.2
|
github.com/onsi/ginkgo v1.14.2
|
||||||
github.com/onsi/gomega v1.10.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/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/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/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/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/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/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM=
|
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/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
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/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/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.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||||
github.com/imdario/mergo v0.3.9/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/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/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
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.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/mitchellh/go-homedir v1.1.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=
|
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/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 v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/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/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-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
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"
|
vinov1 "vino/pkg/api/v1"
|
||||||
"vino/pkg/controllers"
|
"vino/pkg/controllers"
|
||||||
|
"vino/pkg/ipam"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -80,9 +81,13 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ipammer := ipam.NewIpam(ctrl.Log.WithName("IPAM"), mgr.GetClient(),
|
||||||
|
os.Getenv("RUNTIME_NAMESPACE"))
|
||||||
|
|
||||||
if err = (&controllers.VinoReconciler{
|
if err = (&controllers.VinoReconciler{
|
||||||
Client: mgr.GetClient(),
|
Client: mgr.GetClient(),
|
||||||
Scheme: mgr.GetScheme(),
|
Scheme: mgr.GetScheme(),
|
||||||
|
Ipam: ipammer,
|
||||||
}).SetupWithManager(mgr); err != nil {
|
}).SetupWithManager(mgr); err != nil {
|
||||||
setupLog.Error(err, "unable to create controller", "controller", "Vino")
|
setupLog.Error(err, "unable to create controller", "controller", "Vino")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
@ -44,7 +44,7 @@ type VinoSpec struct {
|
|||||||
// Define network parameters
|
// Define network parameters
|
||||||
Networks []Network `json:"networks,omitempty"`
|
Networks []Network `json:"networks,omitempty"`
|
||||||
// Define node details
|
// Define node details
|
||||||
Node []NodeSet `json:"nodes,omitempty"`
|
Nodes []NodeSet `json:"nodes,omitempty"`
|
||||||
// DaemonSetOptions defines how vino will spawn daemonset on nodes
|
// DaemonSetOptions defines how vino will spawn daemonset on nodes
|
||||||
DaemonSetOptions DaemonSetOptions `json:"daemonSetOptions,omitempty"`
|
DaemonSetOptions DaemonSetOptions `json:"daemonSetOptions,omitempty"`
|
||||||
// VMBridge defines the single interface name to be used as a bridge for VMs
|
// VMBridge defines the single interface name to be used as a bridge for VMs
|
||||||
@ -78,6 +78,7 @@ type Network struct {
|
|||||||
//Network Parameter defined
|
//Network Parameter defined
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
SubNet string `json:"subnet,omitempty"`
|
SubNet string `json:"subnet,omitempty"`
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
AllocationStart string `json:"allocationStart,omitempty"`
|
AllocationStart string `json:"allocationStart,omitempty"`
|
||||||
AllocationStop string `json:"allocationStop,omitempty"`
|
AllocationStop string `json:"allocationStop,omitempty"`
|
||||||
DNSServers []string `json:"dns_servers,omitempty"`
|
DNSServers []string `json:"dns_servers,omitempty"`
|
||||||
@ -86,20 +87,21 @@ type Network struct {
|
|||||||
|
|
||||||
// VMRoutes defined
|
// VMRoutes defined
|
||||||
type VMRoutes struct {
|
type VMRoutes struct {
|
||||||
To string `json:"to,omitempty"`
|
Network string `json:"network,omitempty"`
|
||||||
Via string `json:"via,omitempty"`
|
Netmask string `json:"netmask,omitempty"`
|
||||||
|
Gateway string `json:"gateway,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//NodeSet node definitions
|
//NodeSet node definitions
|
||||||
type NodeSet struct {
|
type NodeSet struct {
|
||||||
//Parameter for Node master or worker-standard
|
//Parameter for Node master or worker-standard
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
Count int `json:"count,omitempty"`
|
Count int `json:"count,omitempty"`
|
||||||
NodeLabel VMNodeFlavor `json:"labels,omitempty"`
|
NodeLabel VMNodeFlavor `json:"labels,omitempty"`
|
||||||
LibvirtTemplate NamespacedName `json:"libvirtTemplate,omitempty"`
|
LibvirtTemplateDefinition NamespacedName `json:"libvirtTemplate,omitempty"`
|
||||||
NetworkInterface *NetworkInterface `json:"networkInterfaces,omitempty"`
|
NetworkInterfaces []NetworkInterface `json:"networkInterfaces,omitempty"`
|
||||||
DiskDrives *DiskDrivesTemplate `json:"diskDrives,omitempty"`
|
DiskDrives *DiskDrivesTemplate `json:"diskDrives,omitempty"`
|
||||||
// NetworkDataTemplate reference a Secret containing a template key
|
// NetworkDataTemplate must have a template key
|
||||||
NetworkDataTemplate NamespacedName `json:"networkDataTemplate,omitempty"`
|
NetworkDataTemplate NamespacedName `json:"networkDataTemplate,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,11 +308,13 @@ func (in *NodeSelector) DeepCopy() *NodeSelector {
|
|||||||
func (in *NodeSet) DeepCopyInto(out *NodeSet) {
|
func (in *NodeSet) DeepCopyInto(out *NodeSet) {
|
||||||
*out = *in
|
*out = *in
|
||||||
in.NodeLabel.DeepCopyInto(&out.NodeLabel)
|
in.NodeLabel.DeepCopyInto(&out.NodeLabel)
|
||||||
out.LibvirtTemplate = in.LibvirtTemplate
|
out.LibvirtTemplateDefinition = in.LibvirtTemplateDefinition
|
||||||
if in.NetworkInterface != nil {
|
if in.NetworkInterfaces != nil {
|
||||||
in, out := &in.NetworkInterface, &out.NetworkInterface
|
in, out := &in.NetworkInterfaces, &out.NetworkInterfaces
|
||||||
*out = new(NetworkInterface)
|
*out = make([]NetworkInterface, len(*in))
|
||||||
(*in).DeepCopyInto(*out)
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if in.DiskDrives != nil {
|
if in.DiskDrives != nil {
|
||||||
in, out := &in.DiskDrives, &out.DiskDrives
|
in, out := &in.DiskDrives, &out.DiskDrives
|
||||||
@ -463,8 +465,8 @@ func (in *VinoSpec) DeepCopyInto(out *VinoSpec) {
|
|||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if in.Node != nil {
|
if in.Nodes != nil {
|
||||||
in, out := &in.Node, &out.Node
|
in, out := &in.Nodes, &out.Nodes
|
||||||
*out = make([]NodeSet, len(*in))
|
*out = make([]NodeSet, len(*in))
|
||||||
for i := range *in {
|
for i := range *in {
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
You may obtain a copy of the License at
|
You may obtain a copy of the License at
|
||||||
@ -22,6 +20,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
|
"github.com/Masterminds/sprig"
|
||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
metal3 "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
|
metal3 "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
@ -32,8 +31,20 @@ import (
|
|||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
|
||||||
vinov1 "vino/pkg/api/v1"
|
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 {
|
func (r *VinoReconciler) ensureBMHs(ctx context.Context, vino *vinov1.Vino) error {
|
||||||
labelOpt := client.MatchingLabels{
|
labelOpt := client.MatchingLabels{
|
||||||
vinov1.VinoLabelDSNameSelector: vino.Name,
|
vinov1.VinoLabelDSNameSelector: vino.Name,
|
||||||
@ -56,7 +67,11 @@ func (r *VinoReconciler) ensureBMHs(ctx context.Context, vino *vinov1.Vino) erro
|
|||||||
"pod name",
|
"pod name",
|
||||||
types.NamespacedName{Namespace: pod.Namespace, Name: 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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -101,8 +116,22 @@ func (r *VinoReconciler) reconcileBMHs(ctx context.Context, vino *vinov1.Vino) e
|
|||||||
return nil
|
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 {
|
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 := logr.FromContext(ctx)
|
||||||
logger.Info("Creating BMHs for vino node", "node name", node.Name, "count", node.Count)
|
logger.Info("Creating BMHs for vino node", "node name", node.Name, "count", node.Count)
|
||||||
prefix := r.getBMHNodePrefix(vino, pod)
|
prefix := r.getBMHNodePrefix(vino, pod)
|
||||||
@ -115,7 +144,43 @@ func (r *VinoReconciler) createBMHperPod(ctx context.Context, vino *vinov1.Vino,
|
|||||||
return err
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -213,7 +278,7 @@ func (r *VinoReconciler) reconcileBMHNetworkData(
|
|||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
node vinov1.NodeSet,
|
node vinov1.NodeSet,
|
||||||
vino *vinov1.Vino,
|
vino *vinov1.Vino,
|
||||||
values interface{}) (string, string, error) {
|
values networkTemplateValues) (string, string, error) {
|
||||||
secret := &corev1.Secret{
|
secret := &corev1.Secret{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: node.NetworkDataTemplate.Name,
|
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)
|
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 {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
@ -245,7 +310,7 @@ func (r *VinoReconciler) reconcileBMHNetworkData(
|
|||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
name := fmt.Sprintf("%s-%s-%s", vino.Namespace, vino.Name, node.Name)
|
name := fmt.Sprintf("%s-network-data", values.BMHName)
|
||||||
|
|
||||||
ns := getRuntimeNamespace()
|
ns := getRuntimeNamespace()
|
||||||
netSecret := &corev1.Secret{
|
netSecret := &corev1.Secret{
|
||||||
|
@ -40,7 +40,7 @@ var _ = Describe("Test BMH reconciliation", func() {
|
|||||||
os.Setenv("RUNTIME_NAMESPACE", "vino-system")
|
os.Setenv("RUNTIME_NAMESPACE", "vino-system")
|
||||||
defer os.Unsetenv("RUNTIME_NAMESPACE")
|
defer os.Unsetenv("RUNTIME_NAMESPACE")
|
||||||
vino := testVINO()
|
vino := testVINO()
|
||||||
vino.Spec.Node = []vinov1.NodeSet{
|
vino.Spec.Nodes = []vinov1.NodeSet{
|
||||||
{
|
{
|
||||||
Name: "worker",
|
Name: "worker",
|
||||||
Count: 3,
|
Count: 3,
|
||||||
@ -141,7 +141,7 @@ var _ = Describe("Test BMH reconciliation", func() {
|
|||||||
|
|
||||||
networkSecret := &corev1.Secret{
|
networkSecret := &corev1.Secret{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "default-vino-worker",
|
Name: "default-vino-node01-worker-0-network-data",
|
||||||
Namespace: "vino-system",
|
Namespace: "vino-system",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@ import (
|
|||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
|
|
||||||
vinov1 "vino/pkg/api/v1"
|
vinov1 "vino/pkg/api/v1"
|
||||||
|
"vino/pkg/ipam"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -53,10 +54,12 @@ const (
|
|||||||
type VinoReconciler struct {
|
type VinoReconciler struct {
|
||||||
client.Client
|
client.Client
|
||||||
Scheme *runtime.Scheme
|
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,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=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=pods,verbs=list;watch
|
||||||
// +kubebuilder:rbac:groups="",resources=nodes,verbs=get;list;watch
|
// +kubebuilder:rbac:groups="",resources=nodes,verbs=get;list;watch
|
||||||
// +kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch;create;update;patch
|
// +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" ]]
|
[[ "$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
|
kubectl get secret -o yaml -n vino-system default-vino-test-cr-credentials
|
||||||
|
Loading…
Reference in New Issue
Block a user