-
Notifications
You must be signed in to change notification settings - Fork 311
Implement an Unmanaged (discovered) state #563
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -122,6 +122,10 @@ const ( | |
| // StateNone means the state is unknown | ||
| StateNone ProvisioningState = "" | ||
|
|
||
| // StateUnmanaged means there is insufficient information available to | ||
| // register the host | ||
| StateUnmanaged ProvisioningState = "unmanaged" | ||
|
|
||
| // StateRegistrationError means there was an error registering the | ||
| // host with the backend | ||
| StateRegistrationError ProvisioningState = "registration error" | ||
|
|
@@ -637,6 +641,11 @@ func (host *BareMetalHost) getLabel(name string) string { | |
| return host.Labels[name] | ||
| } | ||
|
|
||
| // HasBMCDetails returns true if the BMC details are set | ||
| func (host *BareMetalHost) HasBMCDetails() bool { | ||
| return host.Spec.BMC.Address != "" || host.Spec.BMC.CredentialsName != "" | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. looks like this assumes that |
||
| } | ||
|
|
||
| // NeedsHardwareProfile returns true if the profile is not set | ||
| func (host *BareMetalHost) NeedsHardwareProfile() bool { | ||
| return host.Status.HardwareProfile == "" | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -43,6 +43,7 @@ import ( | |
| const ( | ||
| hostErrorRetryDelay = time.Second * 10 | ||
| pauseRetryDelay = time.Second * 30 | ||
| unmanagedRetryDelay = time.Minute * 10 | ||
| rebootAnnotationPrefix = "reboot.metal3.io" | ||
| ) | ||
|
|
||
|
|
@@ -247,14 +248,21 @@ func (r *ReconcileBareMetalHost) Reconcile(request reconcile.Request) (result re | |
| // Retrieve the BMC details from the host spec and validate host | ||
| // BMC details and build the credentials for talking to the | ||
| // management controller. | ||
| bmcCreds, bmcCredsSecret, err := r.buildAndValidateBMCCredentials(request, host) | ||
| if err != nil || bmcCreds == nil { | ||
| if !host.DeletionTimestamp.IsZero() { | ||
| // If we are in the process of deletion, try with empty credentials | ||
| bmcCreds = &bmc.Credentials{} | ||
| bmcCredsSecret = &corev1.Secret{} | ||
| } else { | ||
| return r.credentialsErrorResult(err, request, host) | ||
| var bmcCreds *bmc.Credentials | ||
| var bmcCredsSecret *corev1.Secret | ||
| switch host.Status.Provisioning.State { | ||
| case metal3v1alpha1.StateNone, metal3v1alpha1.StateUnmanaged: | ||
| bmcCreds = &bmc.Credentials{} | ||
|
zaneb marked this conversation as resolved.
|
||
| default: | ||
| bmcCreds, bmcCredsSecret, err = r.buildAndValidateBMCCredentials(request, host) | ||
| if err != nil || bmcCreds == nil { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could we have a default username without a password? does it make sense to check if there are no credentials or if user or password are empty?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's what |
||
| if !host.DeletionTimestamp.IsZero() { | ||
| // If we are in the process of deletion, try with empty credentials | ||
| bmcCreds = &bmc.Credentials{} | ||
| bmcCredsSecret = &corev1.Secret{} | ||
| } else { | ||
| return r.credentialsErrorResult(err, request, host) | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -340,30 +348,6 @@ func recordActionFailure(info *reconcileInfo, errorType metal3v1alpha1.ErrorType | |
|
|
||
| func (r *ReconcileBareMetalHost) credentialsErrorResult(err error, request reconcile.Request, host *metal3v1alpha1.BareMetalHost) (reconcile.Result, error) { | ||
| switch err.(type) { | ||
| // We treat an empty bmc address and empty bmc credentials fields as a | ||
| // trigger the host needs to be put into a discovered status. We also set | ||
| // an error message (but not an error state) on the host so we can understand | ||
| // what we may be waiting on. Editing the host to set these values will | ||
| // cause the host to be reconciled again so we do not Requeue. | ||
| case *EmptyBMCAddressError, *EmptyBMCSecretError: | ||
| credentialsInvalid.Inc() | ||
| dirty := host.SetOperationalStatus(metal3v1alpha1.OperationalStatusDiscovered) | ||
| if dirty { | ||
| // Set the host error message directly | ||
| // as we cannot use SetErrorCondition which | ||
| // overwrites our discovered state | ||
| host.Status.ErrorMessage = err.Error() | ||
| host.Status.ErrorType = "" | ||
| saveErr := r.saveHostStatus(host) | ||
| if saveErr != nil { | ||
| return reconcile.Result{Requeue: true}, saveErr | ||
| } | ||
| // Only publish the event if we do not have an error | ||
| // after saving so that we only publish one time. | ||
| r.publishEvent(request, | ||
| host.NewEvent("Discovered", fmt.Sprintf("Discovered host with unusable BMC details: %s", err.Error()))) | ||
| } | ||
| return reconcile.Result{}, nil | ||
| // In the event a credential secret is defined, but we cannot find it | ||
| // we requeue the host as we will not know if they create the secret | ||
| // at some point in the future. | ||
|
|
@@ -379,12 +363,14 @@ func (r *ReconcileBareMetalHost) credentialsErrorResult(err error, request recon | |
| r.publishEvent(request, host.NewEvent("BMCCredentialError", err.Error())) | ||
| } | ||
| return reconcile.Result{Requeue: true, RequeueAfter: hostErrorRetryDelay}, nil | ||
| // If we have found the secret but it is missing the required fields | ||
| // or the BMC address is defined but malformed we set the | ||
| // If a managed Host is missing a BMC address or secret, or | ||
| // we have found the secret but it is missing the required fields, | ||
| // or the BMC address is defined but malformed, we set the | ||
| // host into an error state but we do not Requeue it | ||
| // as fixing the secret or the host BMC info will trigger | ||
| // the host to be reconciled again | ||
| case *bmc.CredentialsValidationError, *bmc.UnknownBMCTypeError: | ||
| case *EmptyBMCAddressError, *EmptyBMCSecretError, | ||
| *bmc.CredentialsValidationError, *bmc.UnknownBMCTypeError: | ||
| credentialsInvalid.Inc() | ||
| _, saveErr := r.setErrorCondition(request, host, metal3v1alpha1.RegistrationError, err.Error()) | ||
| if saveErr != nil { | ||
|
|
@@ -460,6 +446,13 @@ func (r *ReconcileBareMetalHost) actionDeleting(prov provisioner.Provisioner, in | |
| return deleteComplete{} | ||
| } | ||
|
|
||
| func (r *ReconcileBareMetalHost) actionUnmanaged(prov provisioner.Provisioner, info *reconcileInfo) actionResult { | ||
| if info.host.HasBMCDetails() { | ||
| return actionComplete{} | ||
| } | ||
| return actionContinueNoWrite{actionContinue{unmanagedRetryDelay}} | ||
| } | ||
|
|
||
| // Test the credentials by connecting to the management controller. | ||
| func (r *ReconcileBareMetalHost) actionRegistering(prov provisioner.Provisioner, info *reconcileInfo) actionResult { | ||
| info.log.Info("registering and validating access to management controller", | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it need to be both? Could it be either?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Working assumption:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Come to think of it, it's academic anyway because both are required fields within the BMC struct. So you can only specify both or neither.