Extend BaremetalHost CRD to support BIOS configuration in baremetal server#302
Conversation
3293442 to
54f16f0
Compare
|
Can one of the admins verify this patch? |
dhellmann
left a comment
There was a problem hiding this comment.
This looks like a nicely minimal set of new options. I have a few questions about things like names that I would like for us to work out because we're setting precedents, but the overall approach looks OK.
| type BIOSConfig struct { | ||
|
|
||
| // Select the boot mode of the system. Allowed values are Uefi, LegacyBios | ||
| // +kubebuilder:validation:Enum=Uefi,LegacyBios |
There was a problem hiding this comment.
I think we want the enum values to be all lower case.
"LegacyBios" feels redundant. Is there another type of legacy boot interface? Should we just call it "bios"?
There was a problem hiding this comment.
I think we want the enum values to be all lower case.
Done. I will start the enum with lower case.
Should we just call it "bios"?
Hmm, I think bios may make the user confuse. legacy is better, I think.
|
|
||
| // Hyper-threading technology allows a single physical processor core to appear as several | ||
| // logical processors. This supports following options: true, false. | ||
| HyperthreadingEnabled bool `json:"hyperthreadingEnabled,omitempty"` |
There was a problem hiding this comment.
Do all processor types support this?
I'm thinking about how many different axes we have for deciding if a BIOS setting is relevant to a given host, and whether we need some way to separate the ones that aren't applicable in some cases. Do we want to put them in their own struct (with a name like DellIntelBIOS or DellR640BIOS or something) or if we want to just keep the option list very short, abstract things as you've done here, and have the implementation ignore anything that isn't relevant for its platform. I could see either approach working.
There was a problem hiding this comment.
If we want to put some optional BIOS setting that depend on a given host (given hardware driver), I think we can declare extraArgs in CRD with interface type as I have done in previous PR:
extraArgs interface{} `json:"optionalSettings,omitempty"`The YAML file may look like:
bios:
bootMode: uefi
extraArgs:
setting1: "value1"
setting2: "value2"But in this case, the validator for these settings must be defined in indicated hardware driver (iRMC, iLO, ...), not in metal3's API.
How to you think about it?
There was a problem hiding this comment.
If we want to put some optional BIOS setting that depend on a given host (given hardware driver), I think we can declare
extraArgsin CRD withinterfacetype as I have done in previous PR:extraArgs interface{} `json:"optionalSettings,omitempty"`The YAML file may look like:
bios: bootMode: uefi extraArgs: setting1: "value1" setting2: "value2"But in this case, the validator for these settings must be defined in indicated hardware driver (iRMC, iLO, ...), not in metal3's API.
How to you think about it?
No, we can't do that. It's bad API design to have informal fields like that, but beyond the design issue I know that in the near future kubernetes is going to require more formal validation for CRDs to ensure that the structure of the data passed in matches what is expected and does not include any "extra" fields. This requirement was presented as addressing a security issue that comes up when someone stores extra fields in a resource today and then in the future that resource definition changes to include the fields, because the existing data would never have been validated.
So, we must find a way to do this by declaring everything explicitly.
| HyperthreadingEnabled bool `json:"hyperthreadingEnabled,omitempty"` | ||
|
|
||
| // Supports the virtualization of platform hardware. This supports following options: true, false. | ||
| VirtualizationEnabled bool `json:"virtualizationEnabled,omitempty"` |
There was a problem hiding this comment.
We should think about the naming for boolean options like this one and the previous one so we can establish a good naming convention.
FooEnabled can be read as either "foo is enabled" or "foo should be enabled".
EnableFoo or UseFoo are more imperative forms. I'm not sure about using those in a declarative interface.
For the Online flag, I didn't include a verb at all, because I thought the verb was implicit in a declarative interface ("make the online setting match what I give you in this field"). Does that approach make sense, too? Should we call this flag "Virtualization" and the previous one "Hyperthreading"?
I'm curious about the opinions of other reviewers.
There was a problem hiding this comment.
FooEnabled can be read as either "foo is enabled" or "foo should be enabled".
EnableFoo or UseFoo are more imperative forms. I'm not sure about using those in a declarative interface.
+1 I think EnableFoo is better in our case. I will change to EnableFoo :)
|
|
||
| // Select the boot mode of the system. Allowed values are Uefi, LegacyBios | ||
| // +kubebuilder:validation:Enum=Uefi,LegacyBios | ||
| BootMode string `json:"bootMode,omitempty"` |
There was a problem hiding this comment.
Can we use an enum type internally, too? I'm not sure how well special string types mix with kubebuilder.
There was a problem hiding this comment.
Ok. I will define the enum type in go lang :)
There was a problem hiding this comment.
This field is now handled separately and should be removed here.
b389751 to
8ad874a
Compare
|
Just FYI since Doug had reviewed this - he's off on vacation for a couple of weeks. Let me know if this can wait until he's back, or if you'd really like this looked at sooner and I'll pick it up. |
Thanks @russellb |
8ad874a to
e9f98f1
Compare
| // BIOS settings for bare metal server | ||
| BIOS *BIOSConfig `json:"bios,omitempty"` |
There was a problem hiding this comment.
I would like to update BIOS property from BIOSConfig to *BIOSConfig in order to make it be nil in the case of bios is not set in BaremetalHost YAML file
stbenjam
left a comment
There was a problem hiding this comment.
One question but I think this looks good to me otherwise
|
|
||
| // Allowed boot mode from metal3 | ||
| const ( | ||
| Uefi BootMode = "uefi" |
There was a problem hiding this comment.
Could this be named UEFI instead (all caps), as it's an acronym?
There was a problem hiding this comment.
Thanks @stbenjam . I will update this name to UEFI :)
|
I found an interesting pattern in Hive today, where they also have platform-specific settings. They use a struct with pointers to platform-specific structs as a sort of "union" type. https://github.com/openshift/hive/blob/master/pkg/apis/hive/v1alpha1/clusterdeployment_types.go#L309 |
longkb
left a comment
There was a problem hiding this comment.
I found an interesting pattern in Hive today, where they also have platform-specific settings. They use a struct with pointers to platform-specific structs as a sort of "union" type. https://github.com/openshift/hive/blob/master/pkg/apis/hive/v1alpha1/clusterdeployment_types.go#L309
That's great! Thanks @dhellmann
If we apply this pattern. Our bios configuration should look like:
bios:
irmc:
bootMode: "uefi"
enableHyperThreading: trueAm I right? :)
|
|
||
| // Allowed boot mode from metal3 | ||
| const ( | ||
| Uefi BootMode = "uefi" |
There was a problem hiding this comment.
Thanks @stbenjam . I will update this name to UEFI :)
| // BIOS settings for bare metal server | ||
| BIOS *BIOSConfig `json:"bios,omitempty"` |
|
Having platform specific schema for this interface seems reasonable, but how can we handle differences in vendor support for specific settings on different hardware? E.g as above something like: Is fine to expose features that may only be applicable when using irmc vs redfish or whatever, but how can we handle features which are accessible via e.g redfish but only when hardware exists - is there a standard subset we can reasonably expect? I guess there will be some common features like bootmode, hyperthreading, virtualization support etch which probably are common, but my concern is when there are more "advanced" settings which depend on the installed hardware we may find it difficult to define a static schema that can support it? |
Shouldn't the user receive an error if they try to change a setting that cannot be applied because the host doesn't have the relevant hardware? I would expect that to trigger a provisioning failure. The platform-specific options can still be optional, even if they're well-defined. |
|
|
||
| // Select the boot mode of the system. Allowed values are uefi, legacy | ||
| // +kubebuilder:validation:Enum=uefi,legacy | ||
| BootMode BootMode `json:"bootMode,omitempty"` |
There was a problem hiding this comment.
Why mixing boot mode with BIOS configuration? Ironic has a different API for dealing with it (through capabilities), let's make it top level.
There was a problem hiding this comment.
Why mixing boot mode with BIOS configuration? Ironic has a different API for dealing with it (through capabilities), let's make it top level.
How does the user of the hardware change the setting directly? It's a BIOS setting, isn't it?
There was a problem hiding this comment.
I would expect to see something like:
bios:
bootMode: "uefi"
irmc:
enableHyperThreading: true
There was a problem hiding this comment.
Why mixing boot mode with BIOS configuration? Ironic has a different API for dealing with it (through capabilities), let's make it top level.
Yes, you're right. But some vendors also support configure boot mode via BIOS setting.
There was a problem hiding this comment.
I would expect to see something like:
bios: bootMode: "uefi" irmc: enableHyperThreading: true
Thanks. bios will include some common settings and vendor's settings as your suggestion :)
There was a problem hiding this comment.
I don't know what other folks think, but I think it would make more sense to just have a boolean legacyMode.
On a non-x86 architecture it wouldn't make a lot of sense to pass "legacy" and it would definitely make no sense to pass "uefi". It seems less awkward to just have a boolean that is ignored on architectures that don't need it.
There was a problem hiding this comment.
I agree this should be a top-level item and separate. I don't think it should be a boolean, what if we need to support something else later? It can be omitted in either case.
There was a problem hiding this comment.
Yeah, moving bootMode out of this struct makes sense to me.
There was a problem hiding this comment.
Having platform specific schema for this interface seems reasonable, but how can we handle differences in vendor support for specific settings on different hardware?
E.g as above something like:
bios: irmc: bootMode: "uefi" enableHyperThreading: trueIs fine to expose features that may only be applicable when using irmc vs redfish or whatever, but how can we handle features which are accessible via e.g redfish but only when hardware exists - is there a standard subset we can reasonably expect?
I guess there will be some common features like bootmode, hyperthreading, virtualization support etch which probably are common, but my concern is when there are more "advanced" settings which depend on the installed hardware we may find it difficult to define a static schema that can support it?
If we get Driver from BMC access [1], we can know which hardware type are using now, and which advanced BIOS setting is supported by the installed hardware.
|
|
||
| // Select the boot mode of the system. Allowed values are uefi, legacy | ||
| // +kubebuilder:validation:Enum=uefi,legacy | ||
| BootMode BootMode `json:"bootMode,omitempty"` |
There was a problem hiding this comment.
Why mixing boot mode with BIOS configuration? Ironic has a different API for dealing with it (through capabilities), let's make it top level.
Yes, you're right. But some vendors also support configure boot mode via BIOS setting.
|
|
||
| // Select the boot mode of the system. Allowed values are uefi, legacy | ||
| // +kubebuilder:validation:Enum=uefi,legacy | ||
| BootMode BootMode `json:"bootMode,omitempty"` |
There was a problem hiding this comment.
I would expect to see something like:
bios: bootMode: "uefi" irmc: enableHyperThreading: true
Thanks. bios will include some common settings and vendor's settings as your suggestion :)
e9f98f1 to
b14b80c
Compare
|
I have update |
|
|
||
| // Allowed boot mode from metal3 | ||
| const ( | ||
| Uefi BootMode = "UEFI" |
There was a problem hiding this comment.
The variable name should be UEFI as well
| } | ||
|
|
||
| // BIOSConfig contains the configuration that you want to configure BIOS settings in Bare metal server | ||
| type BIOSConfig struct { |
There was a problem hiding this comment.
What do people think about calling this something else like BootConfig? UEFI is not BIOS.
There was a problem hiding this comment.
I don't know where the line is between BIOS and UEFI. Are the other hardware-related settings that we can configure BIOS even if the boot mode is UEFI? Are these just "hardware settings" or are they all related to how the hardware boots?
There was a problem hiding this comment.
BIOS became something of a generic term at some point during the 25 year period when it was more or less the only game in town for booting in the PC architecture. Technically BIOS and UEFI are different firmware standards for PCs, and we not only want to support both but also firmware for completely different architectures (e.g. OpenFirmware). Practically, I don't think anybody would be overly confused by BIOSConfig.
I would describe these as hardware settings that have to be configured prior to boot, i.e. in the firmware. BootConfig is not an unreasonable name, and seems preferable.
There was a problem hiding this comment.
Based on the discussion in the metal3-docs proposal, this should be renamed "Firmware" -- metal3-io/metal3-docs#63
b14b80c to
0272578
Compare
Can't we use the Redfish API to ask the BMC what it is? |
@dhellmann For iRMC I can get its BMC type through the following command: # curl -s -k -u <username>:<password> -H "Content-type: application/json" -X GET https://<ip-address>/redfish/v1/Managers
{
"@odata.id":"\/redfish\/v1\/Managers",
"@odata.type":"#ManagerCollection.ManagerCollection",
"Name":"Manager Collection",
"Members@odata.count":1,
"Members":[
{
"@odata.id":"\/redfish\/v1\/Managers\/iRMC"
}
],
"Oem":{
},
"@Redfish.Copyright":"Copyright 2014-2020 DMTF. For the full DMTF copyright policy, see http:\/\/www.dmtf.org\/about\/policies\/copyright",
"@odata.etag":"1618479521"
}But I'm not sure if this is a standard method(@dtantsur Do you know a better way? ). In addition, I think we also need to be able to get this information through By the way, could you please review this patch? As what demonCoder95 has said above, I also believe that this patch is ready to be merged. |
|
I have rebase this PR, but it seems that I need to re-execute |
|
/test-integration |
|
@andfasano @dhellmann @dtantsur @zaneb This PR has been launched for more than a year and has been recognized by some people,and we have another job that depends on this PR. So I want to know what else needs to be done to help this PR merge? |
Thanks for pointing this out, I hadn't really thought about that earlier. I do think we have some implementation options for this in future. For example, we can now get a list of all the available BIOS options from Ironic, which we're going to use to implement Bob's proposal metal3-io/metal3-docs#173. So we could make a list of all the names that e.g. VirtualizationEnabled is known by on hardware platforms that we know about and then compare it to the list of available BIOS settings for the Host to see which one shows up. The existence of at least one plausible way of implementing this API makes me inclined to go ahead with this PR, so I am not removing my approval. |
But Bob's proposal is mainly about defining a new CR for managing firmware settings (and they could be many), whereas in the current one the public API of BMH is directly modified to address just three of them. I also have some concerns similar to the ones raised by @dtantsur but mostly focusing on the fact that new fields for BMH are going to be defined. I think that a more general approach could allow folks to focus on the settings they are currently interested in but will not affect too much the scalability. |
|
They have different purposes. Bulk set is good for onboarding a bunch of servers from a particular manufacturer. But if you want to e.g. create a Kubernetes node on baremetal with hyperthreading disabled froma pool of hardware, then there should be a vendor-independent way of requesting this in the API. |
|
Ok, so it looks like the current approach and the one in #901 could coexists, addressing some of my concerns. AFAICS the current BMH interface will remain vendor-neutral and will be expanded when required/needed. FWIW, this PR had a pretty long history, and currently it supports the configuration of the /lgtm |
|
Thanks. I will open a new PR to fix the documentation. |
|
@Hellcatlk: Cannot trigger testing until a trusted user reviews the PR and leaves an DetailsIn response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
Signed-off-by: zouyu <zouy.fnst@cn.fujitsu.com>
Signed-off-by: zouyu <zouy.fnst@cn.fujitsu.com>
Signed-off-by: zouyu <zouy.fnst@cn.fujitsu.com>
Signed-off-by: zouyu <zouy.fnst@cn.fujitsu.com>
Signed-off-by: Zou Yu <zouy.fnst@cn.fujitsu.com>
Signed-off-by: Zou Yu <zouy.fnst@cn.fujitsu.com>
Signed-off-by: Zou Yu <zouy.fnst@cn.fujitsu.com>
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: zaneb The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
|
/test |
|
@Hellcatlk: Cannot trigger testing until a trusted user reviews the PR and leaves an DetailsIn response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
|
@andfasano I'm sorry, I updated the PR because CI failed. Could you |
|
/test-integration |
|
/lgtm |
|
/test-integration |
|
@Hellcatlk if you set your membership of the org to public then you won't have to have someone add ok-to-test to your PRs any more. The bot unfortunately can't see you if your membership is set to private. |
Thank you for your reminder, I have set the membership to public now. |
@andfasano I found this part in the design:
I think this part is already expressed our support only |
|
@Hellcatlk I was mainly referring to the BMO docs https://github.com/metal3-io/baremetal-operator/blob/master/docs/api.md (or if there's any other relevant part where a user could easily find the supported platforms) |
This commit aims to add
BIOSConfigas new property intoBareMetalHostSpec. The BaremetalHost CRD is also extend withbiosfield. This option allow Metal3 user to set BIOS settings (#207) via
biosfieldin YAML file.
Co-Authored-By: Dao Cong Tien tiendc@vn.fujitsu.com
Co-Authored-By: Nguyen Phuong An annp@vn.fujitsu.com
Signed-off-byKim Bao Long longkb@vn.fujitsu.com