Skip to content

Bug OCPBUGS-98696: Embed IP_OPTIONS kargs in provisioning ISO#182

Closed
jacob-anders wants to merge 2 commits into
openshift:mainfrom
jacob-anders:fix-provisioning-iso-kargs
Closed

Bug OCPBUGS-98696: Embed IP_OPTIONS kargs in provisioning ISO#182
jacob-anders wants to merge 2 commits into
openshift:mainfrom
jacob-anders:fix-provisioning-iso-kargs

Conversation

@jacob-anders

@jacob-anders jacob-anders commented Jul 17, 2026

Copy link
Copy Markdown

In OCP 4.22, the installer reuses the bootstrap VM's live ISO as the provisioning ISO served to target bare metal nodes. The bootstrap ISO has console=ttyS0 embedded in its kargs area, which causes lockups on hardware that requires specific serial port configuration (baud rate, parity, etc). Additionally, ip=dhcp — previously embedded by the now-removed copy-metal/extract-machine-os.sh step — is missing.

Pass the IP_OPTIONS environment variable (e.g. "ip=dhcp") as kernel arguments to NewRHCOSStreamReader when serving ISO images. The isoeditor replaces the entire kargs placeholder area in the ISO's GRUB config, so console=ttyS0 is overwritten with ip=dhcp, restoring parity with the 4.21 provisioning ISO kernel command line.

Summary by CodeRabbit

  • New Features

    • ISO image creation now supports passing kernel arguments and IP options into the image stream.
  • Bug Fixes

    • Improved handling of empty kernel-argument values during ISO image processing, with a fallback to serve the ISO when kernel-argument streaming isn’t available.

In OCP 4.22, the installer reuses the bootstrap VM's live ISO as the
provisioning ISO served to target bare metal nodes. The bootstrap ISO
has console=ttyS0 embedded in its kargs area, which causes lockups on
hardware that requires specific serial port configuration (baud rate,
parity, etc). Additionally, ip=dhcp — previously embedded by the
now-removed copy-metal/extract-machine-os.sh step — is missing.

Pass the IP_OPTIONS environment variable (e.g. "ip=dhcp") as kernel
arguments to NewRHCOSStreamReader when serving ISO images. The
isoeditor replaces the entire kargs placeholder area in the ISO's
GRUB config, so console=ttyS0 is overwritten with ip=dhcp, restoring
parity with the 4.21 provisioning ISO kernel command line.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@openshift-ci
openshift-ci Bot requested review from elfosardo and honza July 17, 2026 06:14
@openshift-ci

openshift-ci Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: jacob-anders
Once this PR has been reviewed and has the lgtm label, please assign elfosardo for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 79770541-e062-4367-a739-59b78ca618b1

📥 Commits

Reviewing files that changed from the base of the PR and between 9837cdf and 6aa2b60.

📒 Files selected for processing (1)
  • pkg/imagehandler/basefile.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/imagehandler/basefile.go

Walkthrough

Changes

The ISO image path now stores configured kernel arguments and passes them to the RHCOS stream reader during Ignition insertion, with a fallback to reader creation without kernel arguments. NewImageHandler forwards IP options, and related tests use the updated constructor and struct literal.

ISO kernel arguments

Layer / File(s) Summary
Store and apply ISO kernel arguments
pkg/imagehandler/basefile.go
baseIso stores kernel arguments, conditionally passes them to the RHCOS stream reader, and retries without them if reader creation fails.
Wire constructor changes and update tests
pkg/imagehandler/imagehandler.go, pkg/imagehandler/imagehandler_test.go
NewImageHandler supplies IP options to ISO construction, while tests update constructor calls and base ISO initialization.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant NewImageHandler
  participant baseIso
  participant RHCOSStreamReader
  NewImageHandler->>baseIso: construct with IP options
  baseIso->>RHCOSStreamReader: create reader with kernel argument bytes
  RHCOSStreamReader-->>baseIso: return reader or error
  baseIso->>RHCOSStreamReader: retry without kernel arguments on error
Loading

Suggested reviewers: honza, zaneb, elfosardo

🚥 Pre-merge checks | ✅ 15
✅ Passed checks (15 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the change to embed IP_OPTIONS kernel arguments in the provisioning ISO and includes the linked bug ID.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Stable And Deterministic Test Names ✅ Passed PASS: The only changed file is pkg/imagehandler/basefile.go; no Ginkgo test titles were added or modified, and no dynamic test-name patterns appear in the patch.
Test Structure And Quality ✅ Passed PASS: pkg/imagehandler tests are plain testing unit tests; no Ginkgo blocks, cluster ops, or async waits were added, so the checklist is not applicable.
Microshift Test Compatibility ✅ Passed The actual PR diff only changes pkg/imagehandler/basefile.go; no new Ginkgo e2e tests or MicroShift-sensitive APIs/features were added.
Single Node Openshift (Sno) Test Compatibility ✅ Passed No new Ginkgo/e2e tests were added; touched tests are plain Go unit tests and introduce no multi-node or SNO-unsafe assumptions.
Topology-Aware Scheduling Compatibility ✅ Passed Patch only plumbs IP_OPTIONS into ISO kargs and updates tests; no scheduling constraints, topology checks, or manifests/controllers were added.
Ote Binary Stdout Contract ✅ Passed Touched code only adds ISO kernel-arg handling; no init/TestMain/suite setup or stdout writes appear in process-level code.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; the touched tests are plain Go unit tests and show no IPv4 hardcodes or external connectivity requirements.
No-Weak-Crypto ✅ Passed Touched files only change ISO kargs handling and tests; no weak crypto, custom crypto, or secret comparisons found.
Container-Privileges ✅ Passed PASS: The PR only changes pkg/imagehandler/basefile.go; searches found no privileged/hostPID/hostNetwork/hostIPC/SYS_ADMIN/allowPrivilegeEscalation settings.
No-Sensitive-Data-In-Logs ✅ Passed The PR only threads IP_OPTIONS into ISO handling and adds a fallback; it introduces no new logging or sensitive-value emission in the touched files.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@dtantsur

Copy link
Copy Markdown
Member

/cc @zaneb

@jacob-anders you need to attach a bug number instead of [main]

@openshift-ci
openshift-ci Bot requested a review from zaneb July 17, 2026 12:06
@jacob-anders jacob-anders changed the title [main] Embed IP_OPTIONS kargs in provisioning ISO Bug OCPBUGS-98696: Embed IP_OPTIONS kargs in provisioning ISO Jul 17, 2026
@openshift-ci-robot openshift-ci-robot added jira/severity-important Referenced Jira bug's severity is important for the branch this PR is targeting. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. labels Jul 17, 2026
@openshift-ci-robot

Copy link
Copy Markdown

@jacob-anders: This pull request references Jira Issue OCPBUGS-98696, which is valid.

3 validation(s) were run on this bug
  • bug is open, matching expected state (open)
  • bug target version (5.0.0) matches configured target version for branch (5.0.0)
  • bug is in the state POST, which is one of the valid states (NEW, ASSIGNED, POST)

The bug has been updated to refer to the pull request using the external bug tracker.

Details

In response to this:

In OCP 4.22, the installer reuses the bootstrap VM's live ISO as the provisioning ISO served to target bare metal nodes. The bootstrap ISO has console=ttyS0 embedded in its kargs area, which causes lockups on hardware that requires specific serial port configuration (baud rate, parity, etc). Additionally, ip=dhcp — previously embedded by the now-removed copy-metal/extract-machine-os.sh step — is missing.

Pass the IP_OPTIONS environment variable (e.g. "ip=dhcp") as kernel arguments to NewRHCOSStreamReader when serving ISO images. The isoeditor replaces the entire kargs placeholder area in the ISO's GRUB config, so console=ttyS0 is overwritten with ip=dhcp, restoring parity with the 4.21 provisioning ISO kernel command line.

Summary by CodeRabbit

  • New Features

  • ISO image creation now supports passing kernel arguments and IP options into the image stream.

  • Bug Fixes

  • Improved handling of empty kernel-argument values during ISO image processing.

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 openshift-eng/jira-lifecycle-plugin repository.

@jacob-anders

Copy link
Copy Markdown
Author

/cc @zaneb

@jacob-anders you need to attach a bug number instead of [main]

Done. I was making some cluster-bot builds for 5.0 and 4.22 so wanted to make sure I remember which is which, can tidy this up now.

@jacob-anders

Copy link
Copy Markdown
Author

/retest

When the source ISO already has kargs embedded (e.g. console=ttyS0 set
by the installer's createLiveVolume), the COREOS_KARG_EMBED_AREA regex
no longer matches, causing NewRHCOSStreamReader to fail. This prevented
ICC from serving the provisioning ISO at all, breaking node provisioning.

Retry without kargs modification so provisioning continues to work even
when the embed area cannot be rewritten.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jacob-anders

Copy link
Copy Markdown
Author

/retest-required

@jacob-anders

Copy link
Copy Markdown
Author

/test e2e-metal-ipi-ovn-ipv4

@jacob-anders

Copy link
Copy Markdown
Author

/test e2e-metal-ipi-serial-ipv4

@jacob-anders

Copy link
Copy Markdown
Author

/retest-required

@jacob-anders

Copy link
Copy Markdown
Author

/test e2e-metal-ipi-ovn-ipv6

@jacob-anders

Copy link
Copy Markdown
Author

/retest-required

1 similar comment
@jacob-anders

Copy link
Copy Markdown
Author

/retest-required

@jacob-anders

Copy link
Copy Markdown
Author

/test e2e-metal-ipi-ovn-ipv4
/test e2e-metal-ipi-ovn-ipv6
/test e2e-metal-ipi-virtualmedia

@jacob-anders

Copy link
Copy Markdown
Author

/test e2e-metal-ipi-virtualmedia

1 similar comment
@jacob-anders

Copy link
Copy Markdown
Author

/test e2e-metal-ipi-virtualmedia

@jacob-anders

Copy link
Copy Markdown
Author

/retest-required

1 similar comment
@jacob-anders

Copy link
Copy Markdown
Author

/retest-required

@zaneb zaneb left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think your diagnosis is correct: I neglected to add a mechanism for setting the IP_OPTIONS when I stopped using copy-metal. Then later the console=ttyS0 arg was added and the IPA image inherited it.

However, a couple of problems with this fix:

The isoeditor replaces the entire kargs placeholder area in the ISO's GRUB config, so console=ttyS0 is overwritten with ip=dhcp

Claude is lying to you here, this is made up. The embed area as detected by assisted-image-service starts after any existing args. So arguments are only appended.

When the source ISO already has kargs embedded (e.g. console=ttyS0 set
by the installer's createLiveVolume), the COREOS_KARG_EMBED_AREA regex
no longer matches, causing NewRHCOSStreamReader to fail.

This commit effectively undoes the effect of the previous one, it's saying that the fix always fails so we will always fall back to the previous code. So if it's right then this PR can have no effect.

Most likely the reason for the failure is that NewRHCOSStreamReader (as used in the installer, not here) does not automatically re-add the newline at the end of the kernel args, unlike some of the other (cough better-designed) APIs for kargs in assisted-image-service.

Finally, looking at the original commit that added the IP_OPTIONS to i-c-c:

The IP_OPTIONS we need to use for the provisioned node (which has to
pull its Ignition from the external network) are not necessarily the
same as the ones used for starting IPA (which has to talk to ironic via
the provisioning network if it exists).

So the IP_OPTIONS we have here are the wrong ones - they're the ones that the cluster node should get, but we want the ones that IPA should get. Previously the bootstrap was setting it to ${PROVISIONING_IP_OPTIONS} in the ISO, whereas i-c-c gets ${EXTERNAL_IP_OPTIONS}.

Sooo... this is really 2 bugs:

  1. Failing to set the ip= karg. The easiest way to handle this would be to set it in the bootstrap VM, since I'm pretty sure the bootstrap should have the same setting as the IPAs we are booting (i.e. ${PROVISIONING_IP_OPTIONS})?
  2. Presence of the console=ttyS0 option breaking some hardware. There's no easy way to overwrite this. TBH it's probably easiest to just add the baud/parity data to it.

}
reader, err := isoeditor.NewRHCOSStreamReader(biso.filename, ignition, nil, kargsBytes)
if err != nil && kargsBytes != nil {
// The kargs embed area may already be occupied (e.g. the installer

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this. The embed area calculated by NewRHCOSStreamReader() by definition begins after the bit that is occupied. There's no reason to think this ought to fail unless the image is corrupt or in an unexpected format. Which I'd rather know about in CI than have it start silently failing to set the kargs.

switch osImage.kind {
case imageKindISO:
isoFiles[key] = newBaseIso(filePath)
isoFiles[key] = newBaseIso(filePath, envInputs.IpOptions)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we were overwriting the existing kargs, we would also need to pass the FIPS mode here; that is another thing that was set in copy-iso. However, at the moment that will already be set for us in the ISO used to create the bootstrap VM so we are ok.

reader, err := isoeditor.NewRHCOSStreamReader(biso.filename, ignition, nil, kargsBytes)
if err != nil && kargsBytes != nil {
// The kargs embed area may already be occupied (e.g. the installer
// embedded console= params into this ISO). Fall back to serving the

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handling this case is the whole point of the PR according to Claude, so weird to me that it would have us ignore it.

@openshift-ci

openshift-ci Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

@jacob-anders: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e-metal-ipi-serial-ipv4 6aa2b60 link true /test e2e-metal-ipi-serial-ipv4
ci/prow/e2e-metal-ipi-virtualmedia 6aa2b60 link true /test e2e-metal-ipi-virtualmedia
ci/prow/e2e-metal-ipi-ovn-ipv6 6aa2b60 link true /test e2e-metal-ipi-ovn-ipv6

Full PR test history. Your PR dashboard.

Details

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-sigs/prow repository. I understand the commands that are listed here.

@jacob-anders

jacob-anders commented Jul 21, 2026

Copy link
Copy Markdown
Author

I think your diagnosis is correct: I neglected to add a mechanism for setting the IP_OPTIONS when I stopped using copy-metal. Then later the console=ttyS0 arg was added and the IPA image inherited it.

However, a couple of problems with this fix:

The isoeditor replaces the entire kargs placeholder area in the ISO's GRUB config, so console=ttyS0 is overwritten with ip=dhcp

Claude is lying to you here, this is made up. The embed area as detected by assisted-image-service starts after any existing args. So arguments are only appended.

When the source ISO already has kargs embedded (e.g. console=ttyS0 set
by the installer's createLiveVolume), the COREOS_KARG_EMBED_AREA regex
no longer matches, causing NewRHCOSStreamReader to fail.

This commit effectively undoes the effect of the previous one, it's saying that the fix always fails so we will always fall back to the previous code. So if it's right then this PR can have no effect.

Most likely the reason for the failure is that NewRHCOSStreamReader (as used in the installer, not here) does not automatically re-add the newline at the end of the kernel args, unlike some of the other (cough better-designed) APIs for kargs in assisted-image-service.

Finally, looking at the original commit that added the IP_OPTIONS to i-c-c:

The IP_OPTIONS we need to use for the provisioned node (which has to
pull its Ignition from the external network) are not necessarily the
same as the ones used for starting IPA (which has to talk to ironic via
the provisioning network if it exists).

So the IP_OPTIONS we have here are the wrong ones - they're the ones that the cluster node should get, but we want the ones that IPA should get. Previously the bootstrap was setting it to ${PROVISIONING_IP_OPTIONS} in the ISO, whereas i-c-c gets ${EXTERNAL_IP_OPTIONS}.

Thank you for your review, Zane. Claude misled me a fair bit and since I work less with these parts of the code it was hard for me to realise this.

Sooo... this is really 2 bugs:

1. Failing to set the `ip=` karg. The easiest way to handle this would be to set it in the bootstrap VM, since I'm pretty sure the bootstrap should have the same setting as the IPAs we are booting (i.e. `${PROVISIONING_IP_OPTIONS}`)?

2. Presence of the `console=ttyS0` option breaking some hardware. There's no easy way to overwrite this. TBH it's probably easiest to just add the baud/parity data to it.

I have to say I do like the idea of just adding those two fixes to the bootstrap and retesting. I will disregard existing changes try this and report back.

@jacob-anders

Copy link
Copy Markdown
Author

This direction was a dead end, we took a different approach in openshift/installer#10702 and this seems to resolve the issue. Closing this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

jira/severity-important Referenced Jira bug's severity is important for the branch this PR is targeting. jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants