-
Notifications
You must be signed in to change notification settings - Fork 311
Support RAID and BIOS configuration for Baremetal Server #279
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 |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| package v1alpha1 | ||
|
|
||
| import ( | ||
| "github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes" | ||
| corev1 "k8s.io/api/core/v1" | ||
| metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
| "k8s.io/apimachinery/pkg/types" | ||
|
|
@@ -86,6 +87,10 @@ const ( | |
| // learn about the hardware components available there | ||
| StateInspecting ProvisioningState = "inspecting" | ||
|
|
||
| // StateCleaning means Ironic are running the referenced CleanSteps via | ||
| // manual cleaning for RAID and BIOS configuration | ||
| StateCleaning ProvisioningState = "cleaning" | ||
|
|
||
| // StatePowerManagementError means something went wrong trying to | ||
| // power the server on or off. | ||
| StatePowerManagementError ProvisioningState = "power management error" | ||
|
|
@@ -104,6 +109,49 @@ type BMCDetails struct { | |
| CredentialsName string `json:"credentialsName"` | ||
| } | ||
|
|
||
| type RAIDVolume struct { | ||
| // Size (Integer) of the logical disk to be created in GiB. If unspecified, "MAX" will be used. | ||
| SizeGB *int `json:"sizeGB"` | ||
|
|
||
| // RAID level for the logical disk. | ||
| RAIDLevel string `json:"raidLevel" required:"true"` | ||
|
|
||
| // Name of the volume. Should be unique within the Node. If not specified, volume name will be auto-generated. | ||
| VolumeName string `json:"volumeName,omitempty"` | ||
|
|
||
| // Set to true if this logical disk can share physical disks with other logical disks. | ||
| SharePhysicalDisks *bool `json:"sharePhysicalDisks,omitempty"` | ||
|
|
||
| // If this is not specified, disk type will not be a criterion to find backing physical disks | ||
| DiskType string `json:"diskType,omitempty"` | ||
|
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. What are valid values for disk type?
Contributor
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. It could be
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. OK, then DiskType should have an enum defined that restricts its values. |
||
|
|
||
| // If this is not specified, interface type will not be a criterion to find backing physical disks. | ||
| InterfaceType string `json:"interfaceType,omitempty"` | ||
|
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. What are valid values for interface type?
Contributor
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. The valid values for interface type are:
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. InterfaceType should have an enum defined that restricts its values. |
||
|
|
||
| // Integer, number of disks to use for the logical disk. Defaults to minimum number of disks required | ||
| // for the particular RAID level. | ||
| NumberOfPhysicalDisks int `json:"numberOfPhysicalDisks,omitempty"` | ||
|
|
||
| // The name of the controller as read by the RAID interface. | ||
| Controller string `json:"controller,omitempty"` | ||
|
|
||
| // A list of physical disks to use as read by the RAID interface. | ||
| PhysicalDisks []string `json:"physicalDisks,omitempty"` | ||
|
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. Do we really want to expose all advanced features of ironic RAID setup?
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. I would prefer if we start small. It's not clear how that relates to the PhysicalDisks parameter. Does ironic make its own choice if no list is presented?
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. Software Raid also doesn't support physical disk specification. Some of the drivers try to automatically do the right thing, other drivers (and their vendors) disagree with that model though... :( |
||
| } | ||
|
|
||
| // RAIDConfig contains the configuration that are required to config RAID in Bare Metal server | ||
| type RAIDConfig struct { | ||
|
|
||
| // The logical disk that will be root volume | ||
| RootVolume *RAIDVolume `json:"rootVolume,omitempty"` | ||
|
|
||
| // The list of logical disks | ||
| Volumes []RAIDVolume `json:"volumes,omitempty"` | ||
| } | ||
|
|
||
| // BIOSConfig contains the configuration that are required to config BIOS in Bare Metal server | ||
| type BIOSConfig map[string]interface{} | ||
|
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. As I said in an earlier review, the BIOS structure needs to have defined fields with appropriate types. If something is an on/off flag, then a boolean pointer. If something is a string, then a string. A map using interface is not going to be an acceptable API because it is impossible to validate it in the OpenAPI code and future versions of kubernetes are going to require more structural validation for CRDs.
Contributor
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. Because BIOS setting depend on vendor's driver, so I declare For BIOS validation, I also defined [1] https://github.com/metal3-io/baremetal-operator/pull/279/files#diff-334e60af5353ff0c1ef95211da871902R53
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. I realize it is going to make it more complicated to design an API that supports changing different settings on different types of hardware, but that's the task. A pass-through API is completely untenable, because it's not an API. We must decide on some way to describe every API parameter. That may mean abstracting some of the BIOS settings so the same inputs can apply on different types of hardware. It may mean providing a way to specify hardware-type-specific BIOS settings. We will not have an API that accepts an unspecified input and relies on validation happening after the fact.
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. I think part of the conundrum is how this has been handled from the actual vendor interfaces. There is no standardization there even on the exact same API redfish interface as vendors have freely named individual settings as they wish. :\ This can vary between models as well, so I'm really not sure if there is any better way than lettering the vendor data model being represented...
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. So in discussing this with @dhellmann, I think the only path forward for cross-vendor consistency with Metal3 is to define a set list of names. Such as a single VT/VTX CPU flag, such as "Virtualization", that may actually map to specific settings based upon underlying hardware types/Hardware Models. That allows for other backends at a later point in time if necessary. The conundrum is that settings can vary wildly based upon back-end hardware and the best thing to do is for the underlying specific settings to be implementation details for the supported platforms as opposed to try and pass-through the data structure that the underlying driver in ironic or that the BMC may be able to parse. |
||
|
|
||
| // BareMetalHostSpec defines the desired state of BareMetalHost | ||
| type BareMetalHostSpec struct { | ||
| // Important: Run "operator-sdk generate k8s" to regenerate code | ||
|
|
@@ -118,6 +166,12 @@ type BareMetalHostSpec struct { | |
| // How do we connect to the BMC? | ||
| BMC BMCDetails `json:"bmc,omitempty"` | ||
|
|
||
| // RAID configuration for bare metal server | ||
| RAID RAIDConfig `json:"raid,omitempty"` | ||
|
|
||
| // BIOS configurations for bare metal server | ||
| BIOS BIOSConfig `json:"bios,omitempty"` | ||
|
|
||
| // What is the name of the hardware profile for this host? It | ||
| // should only be necessary to set this when inspection cannot | ||
| // automatically determine the profile. | ||
|
|
@@ -351,6 +405,9 @@ type BareMetalHostStatus struct { | |
| // The hardware discovered to exist on the host. | ||
| HardwareDetails *HardwareDetails `json:"hardware,omitempty"` | ||
|
|
||
| // The executed CleanSteps on the host. | ||
| CleanSteps []nodes.CleanStep `json:"cleanSteps,omitempty"` | ||
|
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. Is it possible for us to determine the steps to follow without requiring the user to specify them? Even if we always just follow the same steps, I would rather not expose them through the API.
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. This is a read-only field, I'm not sure why we need it here.
Contributor
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. @dhellmann: This |
||
|
|
||
| // Information tracked by the provisioner. | ||
| Provisioning ProvisionStatus `json:"provisioning"` | ||
|
|
||
|
|
@@ -529,6 +586,18 @@ func (host *BareMetalHost) NeedsHardwareInspection() bool { | |
| return host.Status.HardwareDetails == nil | ||
| } | ||
|
|
||
| // NeedManualCleaning looks at the state of the host to determine | ||
| // if Clean Steps are needed to be run | ||
| func (host *BareMetalHost) NeedsManualCleaning(cleanSteps []nodes.CleanStep) bool { | ||
| if host.Status.CleanSteps != nil { | ||
| return false | ||
| } else if len(cleanSteps) > 0 { | ||
| // Never run manual cleaning if RAID or BIOS is not configured | ||
|
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. This comment is confusing. The way the CRD is defined above, cleaning steps can be configured independently of either the BIOS or RAID settings. Should the condition on line 594 be checking those parts of the struct, too?
Contributor
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. This BIOS struct depend on vendor driver, and it fit with BIOS struct in |
||
| return true | ||
| } | ||
| return false | ||
| } | ||
|
|
||
| // NeedsProvisioning compares the settings with the provisioning | ||
| // status and returns true when more work is needed or false | ||
| // otherwise. | ||
|
|
||
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.
"Cleaning" is an ironic concept, and we do not want to expose it through the metal3 API. We should be able to use the existing provisioning state to indicate that work is happening to provision the server.
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.
And at least we shouldn't call it "cleaning". It's confusing enough in ironic world :)
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.
Thanks for you comment. I will abandon
cleaningstate from this prototype, then execute the cleansteps in the other provision state. But I am confusing betweenregisteringandinspecting:(