Skip to content

Commit

Permalink
MGMT-16843: Extract host ignition before bootstrap
Browse files Browse the repository at this point in the history
https://issues.redhat.com/browse/MGMT-16843
Reordered the flow for bootstrap nodes to extract the host
ignition before starting bootstrap. This is so we can get the
requested hostname from the host ignition ahead of running bootkube
which will allow the requested hostname to be set.
  • Loading branch information
CrystalChun committed Feb 22, 2024
1 parent 662bf4c commit a3605aa
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 32 deletions.
39 changes: 28 additions & 11 deletions src/installer/installer.go
Expand Up @@ -108,11 +108,23 @@ func (i *installer) InstallNode() error {
}
ctx, cancel := context.WithCancel(context.Background())
bootstrapErrGroup, _ := errgroup.WithContext(ctx)
var ignitionPath string
//cancel the context in case this method ends
defer cancel()
isBootstrap := false
if i.Config.Role == string(models.HostRoleBootstrap) && i.HighAvailabilityMode != models.ClusterHighAvailabilityModeNone {
isBootstrap = true
i.Config.Role = string(models.HostRoleMaster)
ignitionPath, err = i.downloadHostIgnition()
if err != nil {
return err
}

if err = i.ops.ExtractFromIgnition(ignitionPath, "/etc/hostname"); err != nil {
i.log.Errorf("extract /etc/hostname from igntion failed %s", err)
return err
}

bootstrapErrGroup.Go(func() error {
return i.startBootstrap()
})
Expand All @@ -121,7 +133,6 @@ func (i *installer) InstallNode() error {
}

i.UpdateHostInstallProgress(models.HostStageInstalling, i.Config.Role)
var ignitionPath string

// i.HighAvailabilityMode is set as an empty string for workers
// regardless of the availability mode of the cluster they are joining
Expand All @@ -132,7 +143,7 @@ func (i *installer) InstallNode() error {
if err != nil {
return err
}
} else {
} else if !isBootstrap {
ignitionPath, err = i.downloadHostIgnition()
if err != nil {
return err
Expand Down Expand Up @@ -917,22 +928,28 @@ func (i *installer) updateConfiguringStatus(ctx context.Context) {
// createSingleNodeMasterIgnition will start the bootstrap flow and wait for bootkube
// when bootkube complete the single node master ignition will be under singleNodeMasterIgnitionPath
func (i *installer) createSingleNodeMasterIgnition() (string, error) {
if err := i.startBootstrap(); err != nil {
i.log.Errorf("Bootstrap failed %s", err)
return "", err
}
i.waitForBootkube(context.Background())
_, err := i.ops.ExecPrivilegeCommand(utils.NewLogWriter(i.log), "stat", singleNodeMasterIgnitionPath)
if err != nil {
if _, err := i.ops.ExecPrivilegeCommand(utils.NewLogWriter(i.log), "stat", singleNodeMasterIgnitionPath); err != nil {
i.log.Errorf("Failed to find single node master ignition: %s", err)
return "", err
}

i.Config.Role = string(models.HostRoleMaster)
err = i.updateSingleNodeIgnition(singleNodeMasterIgnitionPath)
if err != nil {
if err := i.updateSingleNodeIgnition(singleNodeMasterIgnitionPath); err != nil {
i.log.Errorf("get single node ignition failed failed %s", err)
return "", err
}

if err := i.ops.ExtractFromIgnition(singleNodeMasterIgnitionPath, "/etc/hostname"); err != nil {
i.log.Errorf("extract /etc/hostname from igntion failed %s", err)
return "", err
}

if err := i.startBootstrap(); err != nil {
i.log.Errorf("Bootstrap failed %s", err)
return "", err
}

i.waitForBootkube(context.Background())
return singleNodeMasterIgnitionPath, nil
}

Expand Down
43 changes: 22 additions & 21 deletions src/installer/installer_test.go
Expand Up @@ -336,6 +336,9 @@ var _ = Describe("installer HostRoleMaster role", func() {
extractSecretFromIgnitionSuccess := func() {
mockops.EXPECT().ExtractFromIgnition(filepath.Join(InstallDir, bootstrapIgn), dockerConfigFile).Return(nil).Times(1)
}
extractHostnameFromIgnitionSuccess := func() {
mockops.EXPECT().ExtractFromIgnition(filepath.Join(InstallDir, "master-host-id.ign"), "/etc/hostname").Return(nil).Times(1)
}
generateSshKeyPairSuccess := func() {
mockops.EXPECT().ExecPrivilegeCommand(gomock.Any(), "ssh-keygen", "-q", "-f", sshKeyPath, "-N", "").Return("OK", nil).Times(1)
}
Expand All @@ -348,6 +351,8 @@ var _ = Describe("installer HostRoleMaster role", func() {
mkdirSuccess(sshDir)
mkdirSuccess(InstallDir)
downloadFileSuccess(bootstrapIgn)
downloadHostIgnitionSuccess(infraEnvId, hostId, "master-host-id.ign")
extractHostnameFromIgnitionSuccess()
extractSecretFromIgnitionSuccess()
extractIgnitionToFS("Success", nil)
generateSshKeyPairSuccess()
Expand Down Expand Up @@ -383,7 +388,6 @@ var _ = Describe("installer HostRoleMaster role", func() {
resolvConfSuccess()
waitForControllerSuccessfully(conf.ClusterID)
//HostRoleMaster flow:
downloadHostIgnitionSuccess(infraEnvId, hostId, "master-host-id.ign")
writeToDiskSuccess(gomock.Any())
reportLogProgressSuccess()
setBootOrderSuccess(gomock.Any())
Expand Down Expand Up @@ -416,7 +420,6 @@ var _ = Describe("installer HostRoleMaster role", func() {
resolvConfSuccess()
waitForControllerSuccessfully(conf.ClusterID)
//HostRoleMaster flow:
downloadHostIgnitionSuccess(infraEnvId, hostId, "master-host-id.ign")
writeToDiskSuccess(gomock.Any())
reportLogProgressSuccess()
setBootOrderSuccess(gomock.Any())
Expand Down Expand Up @@ -449,7 +452,6 @@ var _ = Describe("installer HostRoleMaster role", func() {
resolvConfSuccess()
waitForControllerSuccessfully(conf.ClusterID)
//HostRoleMaster flow:
downloadHostIgnitionSuccess(infraEnvId, hostId, "master-host-id.ign")
writeToDiskSuccess(gomock.Any())
setBootOrderSuccess(gomock.Any())
uploadLogsSuccess(true)
Expand All @@ -474,13 +476,14 @@ var _ = Describe("installer HostRoleMaster role", func() {
mkdirSuccess(InstallDir)
mkdirSuccess(sshDir)
downloadFileSuccess(bootstrapIgn)
downloadHostIgnitionSuccess(infraEnvId, hostId, "master-host-id.ign")
extractHostnameFromIgnitionSuccess()
extractSecretFromIgnitionSuccess()
extractIgnitionToFS("Success", nil)
generateSshKeyPairSuccess()
err := fmt.Errorf("generate SSH keys failed")
mockops.EXPECT().CreateOpenshiftSshManifest(assistedInstallerSshManifest, sshManifestTmpl, sshPubKeyPath).Return(err).Times(1)
//HostRoleMaster flow:
downloadHostIgnitionSuccess(infraEnvId, hostId, "master-host-id.ign")
writeToDiskSuccess(gomock.Any())
setBootOrderSuccess(gomock.Any())
getEncapsulatedMcSuccess(nil)
Expand Down Expand Up @@ -510,7 +513,6 @@ var _ = Describe("installer HostRoleMaster role", func() {
resolvConfSuccess()
waitForControllerSuccessfully(conf.ClusterID)
//HostRoleMaster flow:
downloadHostIgnitionSuccess(infraEnvId, hostId, "master-host-id.ign")
writeToDiskSuccess(gomock.Any())
setBootOrderSuccess(gomock.Any())
uploadLogsSuccess(true)
Expand All @@ -533,6 +535,7 @@ var _ = Describe("installer HostRoleMaster role", func() {
mkdirSuccess(sshDir)
downloadFileSuccess(bootstrapIgn)
downloadHostIgnitionSuccess(infraEnvId, hostId, "master-host-id.ign")
extractHostnameFromIgnitionSuccess()
writeToDiskSuccess(gomock.Any())
setBootOrderSuccess(gomock.Any())
extractSecretFromIgnitionSuccess()
Expand All @@ -556,7 +559,6 @@ var _ = Describe("installer HostRoleMaster role", func() {
err := fmt.Errorf("Failed to restart NetworkManager")
restartNetworkManager(err)
//HostRoleMaster flow:
downloadHostIgnitionSuccess(infraEnvId, hostId, "master-host-id.ign")
writeToDiskSuccess(gomock.Any())
setBootOrderSuccess(gomock.Any())
getEncapsulatedMcSuccess(nil)
Expand Down Expand Up @@ -644,7 +646,6 @@ var _ = Describe("installer HostRoleMaster role", func() {
resolvConfSuccess()
waitForControllerSuccessfully(conf.ClusterID)
//HostRoleMaster flow:
downloadHostIgnitionSuccess(infraEnvId, hostId, "master-host-id.ign")
writeToDiskSuccess(gomock.Any())
setBootOrderSuccess(gomock.Any())
uploadLogsSuccess(true)
Expand Down Expand Up @@ -1072,18 +1073,25 @@ var _ = Describe("installer HostRoleMaster role", func() {
extractSecretFromIgnitionSuccess := func() {
mockops.EXPECT().ExtractFromIgnition(filepath.Join(InstallDir, bootstrapIgn), dockerConfigFile).Return(nil).Times(1)
}
extractHostnameFromIgnitionSuccess := func() {
mockops.EXPECT().ExtractFromIgnition(singleNodeMasterIgnitionPath, "/etc/hostname").Return(nil).Times(1)
}
verifySingleNodeMasterIgnitionSuccess := func() {
mockops.EXPECT().ExecPrivilegeCommand(gomock.Any(), "stat", singleNodeMasterIgnitionPath).Return("", nil).Times(1)
}
singleNodeBootstrapSetup := func() {
cleanInstallDevice()
mkdirSuccess(InstallDir)
mkdirSuccess(sshDir)
downloadFileSuccess(bootstrapIgn)
verifySingleNodeMasterIgnitionSuccess()
downloadHostIgnitionSuccess(infraEnvId, hostId, "master-host-id.ign")
singleNodeMergeIgnitionSuccess()
extractHostnameFromIgnitionSuccess()
extractSecretFromIgnitionSuccess()
extractIgnitionToFS("Success", nil)
daemonReload(nil)
}
verifySingleNodeMasterIgnitionSuccess := func() {
mockops.EXPECT().ExecPrivilegeCommand(gomock.Any(), "stat", singleNodeMasterIgnitionPath).Return("", nil).Times(1)
}

It("single node happy flow", func() {
updateProgressSuccess([][]string{{string(models.HostStageStartingInstallation), conf.Role},
Expand All @@ -1099,9 +1107,6 @@ var _ = Describe("installer HostRoleMaster role", func() {
waitForBootkubeSuccess()
bootkubeStatusSuccess()
//HostRoleMaster flow:
verifySingleNodeMasterIgnitionSuccess()
singleNodeMergeIgnitionSuccess()
downloadHostIgnitionSuccess(infraEnvId, hostId, "master-host-id.ign")
mockops.EXPECT().WriteImageToDisk(singleNodeMasterIgnitionPath, device, mockbmclient, nil).Return(nil).Times(1)
setBootOrderSuccess(gomock.Any())
uploadLogsSuccess(true)
Expand All @@ -1126,15 +1131,11 @@ var _ = Describe("installer HostRoleMaster role", func() {
})
It("Failed to find master ignition", func() {
updateProgressSuccess([][]string{{string(models.HostStageStartingInstallation), conf.Role},
{string(models.HostStageInstalling), string(models.HostRoleMaster)},
})
{string(models.HostStageInstalling), string(models.HostRoleMaster)},
})
// single node bootstrap flow
singleNodeBootstrapSetup()
checkLocalHostname("localhost", nil)
prepareControllerSuccess()
startServicesSuccess()
waitForBootkubeSuccess()
bootkubeStatusSuccess()
cleanInstallDevice()
mkdirSuccess(InstallDir)
//HostRoleMaster flow:
err := fmt.Errorf("Failed to find master ignition")
mockops.EXPECT().ExecPrivilegeCommand(gomock.Any(), "stat", singleNodeMasterIgnitionPath).Return("", err).Times(1)
Expand Down

0 comments on commit a3605aa

Please sign in to comment.