Remove BPA from Makefile
[icn.git] / cmd / bpa-operator / vendor / github.com / metal3-io / baremetal-operator / pkg / apis / metal3 / v1alpha1 / baremetalhost_types.go
1 package v1alpha1
2
3 import (
4         corev1 "k8s.io/api/core/v1"
5         metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
6         "k8s.io/apimachinery/pkg/types"
7 )
8
9 // NOTE: json tags are required.  Any new fields you add must have
10 // json tags for the fields to be serialized.
11
12 // NOTE(dhellmann): Update docs/api.md when changing these data structure.
13
14 const (
15         // BareMetalHostFinalizer is the name of the finalizer added to
16         // hosts to block delete operations until the physical host can be
17         // deprovisioned.
18         BareMetalHostFinalizer string = "baremetalhost.metal3.io"
19 )
20
21 // OperationalStatus represents the state of the host
22 type OperationalStatus string
23
24 const (
25         // OperationalStatusOK is the status value for when the host is
26         // configured correctly and is manageable.
27         OperationalStatusOK OperationalStatus = "OK"
28
29         // OperationalStatusDiscovered is the status value for when the
30         // host is only partially configured, such as when when the BMC
31         // address is known but the login credentials are not.
32         OperationalStatusDiscovered OperationalStatus = "discovered"
33
34         // OperationalStatusError is the status value for when the host
35         // has any sort of error.
36         OperationalStatusError OperationalStatus = "error"
37 )
38
39 // ProvisioningState defines the states the provisioner will report
40 // the host has having.
41 type ProvisioningState string
42
43 const (
44         // StateNone means the state is unknown
45         StateNone ProvisioningState = ""
46
47         // StateRegistrationError means there was an error registering the
48         // host with the backend
49         StateRegistrationError ProvisioningState = "registration error"
50
51         // StateRegistering means we are telling the backend about the host
52         StateRegistering ProvisioningState = "registering"
53
54         // StateMatchProfile means we are comparing the discovered details
55         // against known hardware profiles
56         StateMatchProfile ProvisioningState = "match profile"
57
58         // StateReady means the host can be consumed
59         StateReady ProvisioningState = "ready"
60
61         // StateValidationError means the provisioning instructions had an
62         // error
63         StateValidationError ProvisioningState = "validation error"
64
65         // StateProvisioning means we are writing an image to the host's
66         // disk(s)
67         StateProvisioning ProvisioningState = "provisioning"
68
69         // StateProvisioningError means we are writing an image to the
70         // host's disk(s)
71         StateProvisioningError ProvisioningState = "provisioning error"
72
73         // StateProvisioned means we have written an image to the host's
74         // disk(s)
75         StateProvisioned ProvisioningState = "provisioned"
76
77         // StateExternallyProvisioned means something else is managing the
78         // image on the host
79         StateExternallyProvisioned ProvisioningState = "externally provisioned"
80
81         // StateDeprovisioning means we are removing an image from the
82         // host's disk(s)
83         StateDeprovisioning ProvisioningState = "deprovisioning"
84
85         // StateInspecting means we are running the agent on the host to
86         // learn about the hardware components available there
87         StateInspecting ProvisioningState = "inspecting"
88
89         // StatePowerManagementError means something went wrong trying to
90         // power the server on or off.
91         StatePowerManagementError ProvisioningState = "power management error"
92 )
93
94 // BMCDetails contains the information necessary to communicate with
95 // the bare metal controller module on host.
96 type BMCDetails struct {
97
98         // Address holds the URL for accessing the controller on the
99         // network.
100         Address string `json:"address"`
101
102         // The name of the secret containing the BMC credentials (requires
103         // keys "username" and "password").
104         CredentialsName string `json:"credentialsName"`
105 }
106
107 // BareMetalHostSpec defines the desired state of BareMetalHost
108 type BareMetalHostSpec struct {
109         // Important: Run "operator-sdk generate k8s" to regenerate code
110         // after modifying this file
111
112         // Taints is the full, authoritative list of taints to apply to
113         // the corresponding Machine. This list will overwrite any
114         // modifications made to the Machine on an ongoing basis.
115         // +optional
116         Taints []corev1.Taint `json:"taints,omitempty"`
117
118         // How do we connect to the BMC?
119         BMC BMCDetails `json:"bmc,omitempty"`
120
121         // What is the name of the hardware profile for this host? It
122         // should only be necessary to set this when inspection cannot
123         // automatically determine the profile.
124         HardwareProfile string `json:"hardwareProfile,omitempty"`
125
126         // Which MAC address will PXE boot? This is optional for some
127         // types, but required for libvirt VMs driven by vbmc.
128         // +kubebuilder:validation:Pattern=[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}
129         BootMACAddress string `json:"bootMACAddress,omitempty"`
130
131         // Should the server be online?
132         Online bool `json:"online"`
133
134         // ConsumerRef can be used to store information about something
135         // that is using a host. When it is not empty, the host is
136         // considered "in use".
137         ConsumerRef *corev1.ObjectReference `json:"consumerRef,omitempty"`
138
139         // Image holds the details of the image to be provisioned.
140         Image *Image `json:"image,omitempty"`
141
142         // UserData holds the reference to the Secret containing the user
143         // data to be passed to the host before it boots.
144         UserData *corev1.SecretReference `json:"userData,omitempty"`
145
146         // Description is a human-entered text used to help identify the host
147         Description string `json:"description,omitempty"`
148
149         // ExternallyProvisioned means something else is managing the
150         // image running on the host and the operator should only manage
151         // the power status and hardware inventory inspection. If the
152         // Image field is filled in, this field is ignored.
153         ExternallyProvisioned bool `json:"externallyProvisioned,omitempty"`
154 }
155
156 // Image holds the details of an image either to provisioned or that
157 // has been provisioned.
158 type Image struct {
159         // URL is a location of an image to deploy.
160         URL string `json:"url"`
161
162         // Checksum is the checksum for the image.
163         Checksum string `json:"checksum"`
164 }
165
166 // FIXME(dhellmann): We probably want some other module to own these
167 // data structures.
168
169 // ClockSpeed is a clock speed in MHz
170 type ClockSpeed float64
171
172 // ClockSpeed multipliers
173 const (
174         MegaHertz ClockSpeed = 1.0
175         GigaHertz            = 1000 * MegaHertz
176 )
177
178 // Capacity is a disk size in Bytes
179 type Capacity int64
180
181 // Capacity multipliers
182 const (
183         Byte     Capacity = 1
184         KibiByte          = Byte * 1024
185         KiloByte          = Byte * 1000
186         MebiByte          = KibiByte * 1024
187         MegaByte          = KiloByte * 1000
188         GibiByte          = MebiByte * 1024
189         GigaByte          = MegaByte * 1000
190         TebiByte          = GibiByte * 1024
191         TeraByte          = GigaByte * 1000
192 )
193
194 // CPU describes one processor on the host.
195 type CPU struct {
196         Arch           string     `json:"arch"`
197         Model          string     `json:"model"`
198         ClockMegahertz ClockSpeed `json:"clockMegahertz"`
199         Flags          []string   `json:"flags"`
200         Count          int        `json:"count"`
201 }
202
203 // Storage describes one storage device (disk, SSD, etc.) on the host.
204 type Storage struct {
205         // A name for the disk, e.g. "disk 1 (boot)"
206         Name string `json:"name"`
207
208         // Whether this disk represents rotational storage
209         Rotational bool `json:"rotational"`
210
211         // The size of the disk in Bytes
212         SizeBytes Capacity `json:"sizeBytes"`
213
214         // The name of the vendor of the device
215         Vendor string `json:"vendor,omitempty"`
216
217         // Hardware model
218         Model string `json:"model,omitempty"`
219
220         // The serial number of the device
221         SerialNumber string `json:"serialNumber"`
222
223         // The WWN of the device
224         WWN string `json:"wwn,omitempty"`
225
226         // The WWN Vendor extension of the device
227         WWNVendorExtension string `json:"wwnVendorExtension,omitempty"`
228
229         // The WWN with the extension
230         WWNWithExtension string `json:"wwnWithExtension,omitempty"`
231
232         // The SCSI location of the device
233         HCTL string `json:"hctl,omitempty"`
234 }
235
236 // VLANID is a 12-bit 802.1Q VLAN identifier
237 type VLANID int32
238
239 // VLAN represents the name and ID of a VLAN
240 type VLAN struct {
241         // +kubebuilder:validation:Minimum=0
242         // +kubebuilder:validation:Maximum=4094
243         ID VLANID `json:"id"`
244
245         Name string `json:"name,omitempty"`
246 }
247
248 // NIC describes one network interface on the host.
249 type NIC struct {
250         // The name of the NIC, e.g. "nic-1"
251         Name string `json:"name"`
252
253         // The name of the model, e.g. "virt-io"
254         Model string `json:"model"`
255
256         // The device MAC addr
257         // +kubebuilder:validation:Pattern=[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}
258         MAC string `json:"mac"`
259
260         // The IP address of the device
261         IP string `json:"ip"`
262
263         // The speed of the device
264         SpeedGbps int `json:"speedGbps"`
265
266         // The VLANs available
267         VLANs []VLAN `json:"vlans,omitempty"`
268
269         // The untagged VLAN ID
270         // +kubebuilder:validation:Minimum=0
271         // +kubebuilder:validation:Maximum=4094
272         VLANID VLANID `json:"vlanId"`
273
274         // Whether the NIC is PXE Bootable
275         PXE bool `json:"pxe"`
276 }
277
278 // Firmware describes the firmware on the host.
279 type Firmware struct {
280         // The BIOS for this firmware
281         BIOS BIOS `json:"bios"`
282 }
283
284 // BIOS describes the BIOS version on the host.
285 type BIOS struct {
286         // The release/build date for this BIOS
287         Date string `json:"date"`
288
289         // The vendor name for this BIOS
290         Vendor string `json:"vendor"`
291
292         // The version of the BIOS
293         Version string `json:"version"`
294 }
295
296 // HardwareDetails collects all of the information about hardware
297 // discovered on the host.
298 type HardwareDetails struct {
299         SystemVendor HardwareSystemVendor `json:"systemVendor"`
300         Firmware     Firmware             `json:"firmware"`
301         RAMMebibytes int                  `json:"ramMebibytes"`
302         NIC          []NIC                `json:"nics"`
303         Storage      []Storage            `json:"storage"`
304         CPU          CPU                  `json:"cpu"`
305         Hostname     string               `json:"hostname"`
306 }
307
308 // HardwareSystemVendor stores details about the whole hardware system.
309 type HardwareSystemVendor struct {
310         Manufacturer string `json:"manufacturer"`
311         ProductName  string `json:"productName"`
312         SerialNumber string `json:"serialNumber"`
313 }
314
315 // CredentialsStatus contains the reference and version of the last
316 // set of BMC credentials the controller was able to validate.
317 type CredentialsStatus struct {
318         Reference *corev1.SecretReference `json:"credentials,omitempty"`
319         Version   string                  `json:"credentialsVersion,omitempty"`
320 }
321
322 // Match compares the saved status information with the name and
323 // content of a secret object.
324 func (cs CredentialsStatus) Match(secret corev1.Secret) bool {
325         switch {
326         case cs.Reference == nil:
327                 return false
328         case cs.Reference.Name != secret.ObjectMeta.Name:
329                 return false
330         case cs.Reference.Namespace != secret.ObjectMeta.Namespace:
331                 return false
332         case cs.Version != secret.ObjectMeta.ResourceVersion:
333                 return false
334         }
335         return true
336 }
337
338 // BareMetalHostStatus defines the observed state of BareMetalHost
339 type BareMetalHostStatus struct {
340         // Important: Run "operator-sdk generate k8s" to regenerate code
341         // after modifying this file
342
343         // OperationalStatus holds the status of the host
344         OperationalStatus OperationalStatus `json:"operationalStatus"`
345
346         // LastUpdated identifies when this status was last observed.
347         // +optional
348         LastUpdated *metav1.Time `json:"lastUpdated,omitempty"`
349
350         // The name of the profile matching the hardware details.
351         HardwareProfile string `json:"hardwareProfile"`
352
353         // The hardware discovered to exist on the host.
354         HardwareDetails *HardwareDetails `json:"hardware,omitempty"`
355
356         // Information tracked by the provisioner.
357         Provisioning ProvisionStatus `json:"provisioning"`
358
359         // the last credentials we were able to validate as working
360         GoodCredentials CredentialsStatus `json:"goodCredentials,omitempty"`
361
362         // the last credentials we sent to the provisioning backend
363         TriedCredentials CredentialsStatus `json:"triedCredentials,omitempty"`
364
365         // the last error message reported by the provisioning subsystem
366         ErrorMessage string `json:"errorMessage"`
367
368         // indicator for whether or not the host is powered on
369         PoweredOn bool `json:"poweredOn"`
370 }
371
372 // ProvisionStatus holds the state information for a single target.
373 type ProvisionStatus struct {
374         // An indiciator for what the provisioner is doing with the host.
375         State ProvisioningState `json:"state"`
376
377         // The machine's UUID from the underlying provisioning tool
378         ID string `json:"ID"`
379
380         // Image holds the details of the last image successfully
381         // provisioned to the host.
382         Image Image `json:"image,omitempty"`
383 }
384
385 // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
386
387 // BareMetalHost is the Schema for the baremetalhosts API
388 // +k8s:openapi-gen=true
389 // +kubebuilder:resource:shortName=bmh;bmhost
390 // +kubebuilder:subresource:status
391 // +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.operationalStatus",description="Operational status"
392 // +kubebuilder:printcolumn:name="Provisioning Status",type="string",JSONPath=".status.provisioning.state",description="Provisioning status"
393 // +kubebuilder:printcolumn:name="Consumer",type="string",JSONPath=".spec.consumerRef.name",description="Consumer using this host"
394 // +kubebuilder:printcolumn:name="BMC",type="string",JSONPath=".spec.bmc.address",description="Address of management controller"
395 // +kubebuilder:printcolumn:name="Hardware Profile",type="string",JSONPath=".status.hardwareProfile",description="The type of hardware detected"
396 // +kubebuilder:printcolumn:name="Online",type="string",JSONPath=".spec.online",description="Whether the host is online or not"
397 // +kubebuilder:printcolumn:name="Error",type="string",JSONPath=".status.errorMessage",description="Most recent error"
398 type BareMetalHost struct {
399         metav1.TypeMeta   `json:",inline"`
400         metav1.ObjectMeta `json:"metadata,omitempty"`
401
402         Spec   BareMetalHostSpec   `json:"spec,omitempty"`
403         Status BareMetalHostStatus `json:"status,omitempty"`
404 }
405
406 // Available returns true if the host is available to be provisioned.
407 func (host *BareMetalHost) Available() bool {
408         if host.Spec.ConsumerRef != nil {
409                 return false
410         }
411         if host.GetDeletionTimestamp() != nil {
412                 return false
413         }
414         if host.HasError() {
415                 return false
416         }
417         return true
418 }
419
420 // SetErrorMessage updates the ErrorMessage in the host Status struct
421 // when necessary and returns true when a change is made or false when
422 // no change is made.
423 func (host *BareMetalHost) SetErrorMessage(message string) (dirty bool) {
424         if host.Status.OperationalStatus != OperationalStatusError {
425                 host.Status.OperationalStatus = OperationalStatusError
426                 dirty = true
427         }
428         if host.Status.ErrorMessage != message {
429                 host.Status.ErrorMessage = message
430                 dirty = true
431         }
432         return dirty
433 }
434
435 // ClearError removes any existing error message.
436 func (host *BareMetalHost) ClearError() (dirty bool) {
437         dirty = host.SetOperationalStatus(OperationalStatusOK)
438         if host.Status.ErrorMessage != "" {
439                 host.Status.ErrorMessage = ""
440                 dirty = true
441         }
442         return dirty
443 }
444
445 // setLabel updates the given label when necessary and returns true
446 // when a change is made or false when no change is made.
447 func (host *BareMetalHost) setLabel(name, value string) bool {
448         if host.Labels == nil {
449                 host.Labels = make(map[string]string)
450         }
451         if host.Labels[name] != value {
452                 host.Labels[name] = value
453                 return true
454         }
455         return false
456 }
457
458 // getLabel returns the value associated with the given label. If
459 // there is no value, an empty string is returned.
460 func (host *BareMetalHost) getLabel(name string) string {
461         if host.Labels == nil {
462                 return ""
463         }
464         return host.Labels[name]
465 }
466
467 // NeedsHardwareProfile returns true if the profile is not set
468 func (host *BareMetalHost) NeedsHardwareProfile() bool {
469         return host.Status.HardwareProfile == ""
470 }
471
472 // HardwareProfile returns the hardware profile name for the host.
473 func (host *BareMetalHost) HardwareProfile() string {
474         return host.Status.HardwareProfile
475 }
476
477 // SetHardwareProfile updates the hardware profile name and returns
478 // true when a change is made or false when no change is made.
479 func (host *BareMetalHost) SetHardwareProfile(name string) (dirty bool) {
480         if host.Status.HardwareProfile != name {
481                 host.Status.HardwareProfile = name
482                 dirty = true
483         }
484         return dirty
485 }
486
487 // SetOperationalStatus updates the OperationalStatus field and returns
488 // true when a change is made or false when no change is made.
489 func (host *BareMetalHost) SetOperationalStatus(status OperationalStatus) bool {
490         if host.Status.OperationalStatus != status {
491                 host.Status.OperationalStatus = status
492                 return true
493         }
494         return false
495 }
496
497 // OperationalStatus returns the contents of the OperationalStatus
498 // field.
499 func (host *BareMetalHost) OperationalStatus() OperationalStatus {
500         return host.Status.OperationalStatus
501 }
502
503 // HasError returns a boolean indicating whether there is an error
504 // set for the host.
505 func (host *BareMetalHost) HasError() bool {
506         return host.Status.ErrorMessage != ""
507 }
508
509 // CredentialsKey returns a NamespacedName suitable for loading the
510 // Secret containing the credentials associated with the host.
511 func (host *BareMetalHost) CredentialsKey() types.NamespacedName {
512         return types.NamespacedName{
513                 Name:      host.Spec.BMC.CredentialsName,
514                 Namespace: host.ObjectMeta.Namespace,
515         }
516 }
517
518 // NeedsHardwareInspection looks at the state of the host to determine
519 // if hardware inspection should be run.
520 func (host *BareMetalHost) NeedsHardwareInspection() bool {
521         if host.Spec.ExternallyProvisioned {
522                 // Never perform inspection if we already know something is
523                 // using the host and we didn't provision it.
524                 return false
525         }
526         if host.WasProvisioned() {
527                 // Never perform inspection if we have already provisioned
528                 // this host, because we don't want to reboot it.
529                 return false
530         }
531         return host.Status.HardwareDetails == nil
532 }
533
534 // NeedsProvisioning compares the settings with the provisioning
535 // status and returns true when more work is needed or false
536 // otherwise.
537 func (host *BareMetalHost) NeedsProvisioning() bool {
538         if host.Spec.ExternallyProvisioned {
539                 return false
540         }
541         if !host.Spec.Online {
542                 // The host is not supposed to be powered on.
543                 return false
544         }
545         if host.Spec.Image == nil {
546                 // Without an image, there is nothing to provision.
547                 return false
548         }
549         if host.Spec.Image.URL == "" {
550                 // We have an Image struct but it is empty
551                 return false
552         }
553         if host.Status.Provisioning.Image.URL == "" {
554                 // We have an image set, but not provisioned.
555                 return true
556         }
557         return false
558 }
559
560 // WasProvisioned returns true when we think we have placed an image
561 // on the host.
562 func (host *BareMetalHost) WasProvisioned() bool {
563         if host.Spec.ExternallyProvisioned {
564                 return false
565         }
566         if host.Status.Provisioning.Image.URL != "" {
567                 // We have an image provisioned.
568                 return true
569         }
570         return false
571 }
572
573 // NeedsDeprovisioning compares the settings with the provisioning
574 // status and returns true when the host should be deprovisioned.
575 func (host *BareMetalHost) NeedsDeprovisioning() bool {
576         if host.Spec.ExternallyProvisioned {
577                 return false
578         }
579         if host.Status.Provisioning.Image.URL == "" {
580                 return false
581         }
582         if host.Spec.Image == nil {
583                 return true
584         }
585         if host.Spec.Image.URL != host.Status.Provisioning.Image.URL {
586                 return true
587         }
588         return false
589 }
590
591 // UpdateGoodCredentials modifies the GoodCredentials portion of the
592 // Status struct to record the details of the secret containing
593 // credentials known to work.
594 func (host *BareMetalHost) UpdateGoodCredentials(currentSecret corev1.Secret) {
595         host.Status.GoodCredentials.Version = currentSecret.ObjectMeta.ResourceVersion
596         host.Status.GoodCredentials.Reference = &corev1.SecretReference{
597                 Name:      currentSecret.ObjectMeta.Name,
598                 Namespace: currentSecret.ObjectMeta.Namespace,
599         }
600 }
601
602 // UpdateTriedCredentials modifies the TriedCredentials portion of the
603 // Status struct to record the details of the secret containing
604 // credentials known to work.
605 func (host *BareMetalHost) UpdateTriedCredentials(currentSecret corev1.Secret) {
606         host.Status.TriedCredentials.Version = currentSecret.ObjectMeta.ResourceVersion
607         host.Status.TriedCredentials.Reference = &corev1.SecretReference{
608                 Name:      currentSecret.ObjectMeta.Name,
609                 Namespace: currentSecret.ObjectMeta.Namespace,
610         }
611 }
612
613 // NewEvent creates a new event associated with the object and ready
614 // to be published to the kubernetes API.
615 func (host *BareMetalHost) NewEvent(reason, message string) corev1.Event {
616         t := metav1.Now()
617         return corev1.Event{
618                 ObjectMeta: metav1.ObjectMeta{
619                         GenerateName: reason + "-",
620                         Namespace:    host.ObjectMeta.Namespace,
621                 },
622                 InvolvedObject: corev1.ObjectReference{
623                         Kind:       "BareMetalHost",
624                         Namespace:  host.Namespace,
625                         Name:       host.Name,
626                         UID:        host.UID,
627                         APIVersion: SchemeGroupVersion.Version,
628                 },
629                 Reason:  reason,
630                 Message: message,
631                 Source: corev1.EventSource{
632                         Component: "metal3-baremetal-controller",
633                 },
634                 FirstTimestamp:      t,
635                 LastTimestamp:       t,
636                 Count:               1,
637                 Type:                corev1.EventTypeNormal,
638                 ReportingController: "metal3.io/baremetal-controller",
639                 Related:             host.Spec.ConsumerRef,
640         }
641 }
642
643 // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
644
645 // BareMetalHostList contains a list of BareMetalHost
646 type BareMetalHostList struct {
647         metav1.TypeMeta `json:",inline"`
648         metav1.ListMeta `json:"metadata,omitempty"`
649         Items           []BareMetalHost `json:"items"`
650 }
651
652 func init() {
653         SchemeBuilder.Register(&BareMetalHost{}, &BareMetalHostList{})
654 }