Add NetworkData validation to BMH

This change introduces validation to ensure that NetworkData is present
when creating a machine. If not, the machine is skipped and placed in
NotScheduled state.

This change also includes a test case to validate this behavior occurs.

Signed-off-by: Alexander Hughes <Alexander.Hughes@pm.me>

restoring kustomization

Signed-off-by: Alexander Hughes <Alexander.Hughes@pm.me>
This commit is contained in:
Alexander Hughes 2020-12-08 15:09:13 -05:00
parent 1c75f4fbf7
commit 6ef42df03f
4 changed files with 50 additions and 12 deletions

View File

@ -4,7 +4,7 @@ apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition kind: CustomResourceDefinition
metadata: metadata:
annotations: annotations:
controller-gen.kubebuilder.io/version: (devel) controller-gen.kubebuilder.io/version: v0.2.5
creationTimestamp: null creationTimestamp: null
name: sipclusters.airship.airshipit.org name: sipclusters.airship.airshipit.org
spec: spec:
@ -115,5 +115,5 @@ status:
acceptedNames: acceptedNames:
kind: "" kind: ""
plural: "" plural: ""
conditions: null conditions: []
storedVersions: null storedVersions: []

View File

@ -2,6 +2,9 @@ package vbmh
import ( import (
"fmt" "fmt"
metal3 "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
airshipv1 "sipcluster/pkg/api/v1" airshipv1 "sipcluster/pkg/api/v1"
) )
@ -43,3 +46,12 @@ type ErrorUknownSpreadTopology struct {
func (e ErrorUknownSpreadTopology) Error() string { func (e ErrorUknownSpreadTopology) Error() string {
return fmt.Sprintf("Uknown spread topology '%s'", e.Topology) return fmt.Sprintf("Uknown spread topology '%s'", e.Topology)
} }
// ErrorNetworkDataNotFound is returned when NetworkData metadata is missing from BMH
type ErrorNetworkDataNotFound struct {
BMH metal3.BareMetalHost
}
func (e ErrorNetworkDataNotFound) Error() string {
return fmt.Sprintf("vBMH Host %v does not define NetworkData, but is required for scheduling.", e.BMH)
}

View File

@ -99,7 +99,11 @@ func (m *Machine) String() string {
m.BMH.ObjectMeta.Name, m.ScheduleStatus, m.VMRole) m.BMH.ObjectMeta.Name, m.ScheduleStatus, m.VMRole)
} }
func NewMachine(bmh metal3.BareMetalHost, nodeRole airshipv1.VMRoles, schedState ScheduledState) (m *Machine) { func NewMachine(bmh metal3.BareMetalHost, nodeRole airshipv1.VMRoles, schedState ScheduledState) (m *Machine, e error) {
// Add logic to check if required fields exist.
if bmh.Spec.NetworkData == nil {
return nil, &ErrorNetworkDataNotFound{BMH: bmh}
}
return &Machine{ return &Machine{
BMH: bmh, BMH: bmh,
ScheduleStatus: schedState, ScheduleStatus: schedState,
@ -107,7 +111,7 @@ func NewMachine(bmh metal3.BareMetalHost, nodeRole airshipv1.VMRoles, schedState
Data: &MachineData{ Data: &MachineData{
IPOnInterface: make(map[string]string), IPOnInterface: make(map[string]string),
}, },
} }, nil
} }
type MachineData struct { type MachineData struct {
@ -289,7 +293,12 @@ func (ml *MachineList) countScheduledAndTobeScheduled(nodeRole airshipv1.VMRoles
if readyScheduled { if readyScheduled {
logger.Info("BMH host is not yet marked as ready to be scheduled, marking it as ready to be scheduled") logger.Info("BMH host is not yet marked as ready to be scheduled, marking it as ready to be scheduled")
// Add it to the list. // Add it to the list.
ml.Machines[bmh.ObjectMeta.Name] = NewMachine(bmh, nodeRole, Scheduled) m, err := NewMachine(bmh, nodeRole, Scheduled)
if err != nil {
logger.Info("BMH did not meet scheduling requirements", "error", err.Error())
continue
}
ml.Machines[bmh.ObjectMeta.Name] = m
ml.ReadyForScheduleCount[nodeRole]++ ml.ReadyForScheduleCount[nodeRole]++
} }
} }
@ -348,7 +357,12 @@ func (ml *MachineList) scheduleIt(nodeRole airshipv1.VMRoles, nodeCfg airshipv1.
// Only if its not in the list already // Only if its not in the list already
if validBmh { if validBmh {
// Lets add it to the list as a schedulable thing // Lets add it to the list as a schedulable thing
ml.Machines[bmh.ObjectMeta.Name] = NewMachine(bmh, nodeRole, ToBeScheduled) m, err := NewMachine(bmh, nodeRole, ToBeScheduled)
if err != nil {
logger.Info("Skipping BMH host as it did not meet creation requirements", "error", err.Error())
continue
}
ml.Machines[bmh.ObjectMeta.Name] = m
ml.ReadyForScheduleCount[nodeRole]++ ml.ReadyForScheduleCount[nodeRole]++
// TODO Probable should remove the bmh from the // TODO Probable should remove the bmh from the
// list so if there are other node targets they // list so if there are other node targets they

View File

@ -21,11 +21,13 @@ const (
var _ = Describe("MachineList", func() { var _ = Describe("MachineList", func() {
var machineList *MachineList var machineList *MachineList
var err error
BeforeEach(func() { BeforeEach(func() {
nodes := map[string]*Machine{} nodes := map[string]*Machine{}
for n := 0; n < numNodes; n++ { for n := 0; n < numNodes; n++ {
bmh, _ := testutil.CreateBMH(n, "default", "master", 6) bmh, _ := testutil.CreateBMH(n, "default", "master", 6)
nodes[bmh.Name] = NewMachine(*bmh, airshipv1.VMMaster, NotScheduled) nodes[bmh.Name], err = NewMachine(*bmh, airshipv1.VMMaster, NotScheduled)
Expect(err).To(BeNil())
} }
machineList = &MachineList{ machineList = &MachineList{
@ -94,7 +96,8 @@ var _ = Describe("MachineList", func() {
It("Should retrieve the BMH IP from the BMH's NetworkData secret when infra services are defined", func() { It("Should retrieve the BMH IP from the BMH's NetworkData secret when infra services are defined", func() {
// Create a BMH with a NetworkData secret // Create a BMH with a NetworkData secret
bmh, secret := testutil.CreateBMH(1, "default", "master", 6) bmh, secret := testutil.CreateBMH(1, "default", "master", 6)
m, err := NewMachine(*bmh, airshipv1.VMMaster, NotScheduled)
Expect(err).To(BeNil())
var objs []runtime.Object var objs []runtime.Object
objs = append(objs, bmh) objs = append(objs, bmh)
objs = append(objs, secret) objs = append(objs, secret)
@ -105,7 +108,7 @@ var _ = Describe("MachineList", func() {
Namespace: "default", Namespace: "default",
}, },
Machines: map[string]*Machine{ Machines: map[string]*Machine{
bmh.Name: NewMachine(*bmh, airshipv1.VMMaster, NotScheduled), bmh.Name: m,
}, },
Log: ctrl.Log.WithName("controllers").WithName("SIPCluster"), Log: ctrl.Log.WithName("controllers").WithName("SIPCluster"),
} }
@ -131,7 +134,8 @@ var _ = Describe("MachineList", func() {
It("Should not retrieve the BMH IP from the BMH's NetworkData secret if no infraServices are defined", func() { It("Should not retrieve the BMH IP from the BMH's NetworkData secret if no infraServices are defined", func() {
// Create a BMH with a NetworkData secret // Create a BMH with a NetworkData secret
bmh, secret := testutil.CreateBMH(1, "default", "master", 6) bmh, secret := testutil.CreateBMH(1, "default", "master", 6)
m, err := NewMachine(*bmh, airshipv1.VMMaster, NotScheduled)
Expect(err).To(BeNil())
var objs []runtime.Object var objs []runtime.Object
objs = append(objs, bmh) objs = append(objs, bmh)
objs = append(objs, secret) objs = append(objs, secret)
@ -142,7 +146,7 @@ var _ = Describe("MachineList", func() {
Namespace: "default", Namespace: "default",
}, },
Machines: map[string]*Machine{ Machines: map[string]*Machine{
bmh.Name: NewMachine(*bmh, airshipv1.VMMaster, NotScheduled), bmh.Name: m,
}, },
Log: ctrl.Log.WithName("controllers").WithName("SIPCluster"), Log: ctrl.Log.WithName("controllers").WithName("SIPCluster"),
} }
@ -167,4 +171,12 @@ var _ = Describe("MachineList", func() {
sipCluster := testutil.CreateSIPCluster("subcluster-1", "default", 1, 3) sipCluster := testutil.CreateSIPCluster("subcluster-1", "default", 1, 3)
Expect(machineList.Extrapolate(*sipCluster, k8sClient)).To(BeTrue()) Expect(machineList.Extrapolate(*sipCluster, k8sClient)).To(BeTrue())
}) })
It("Should not schedule BMH if it is missing networkdata", func() {
// Create a BMH without NetworkData
bmh, _ := testutil.CreateBMH(1, "default", "master", 6)
bmh.Spec.NetworkData = nil
_, err := NewMachine(*bmh, airshipv1.VMMaster, NotScheduled)
Expect(err).ToNot(BeNil())
})
}) })