-
Notifications
You must be signed in to change notification settings - Fork 85
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Resource to prepare for NSXT cluster upgrade
Signed-off-by: Shizhao Liu <[email protected]>
- Loading branch information
Shizhao Liu
committed
Jan 9, 2024
1 parent
b8b33d1
commit 6b42c52
Showing
5 changed files
with
432 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
/* Copyright © 2023 VMware, Inc. All Rights Reserved. | ||
SPDX-License-Identifier: MPL-2.0 */ | ||
|
||
package nsxt | ||
|
||
import ( | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||
nsxModel "github.com/vmware/vsphere-automation-sdk-go/services/nsxt-mp/nsx/model" | ||
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt-mp/nsx/upgrade" | ||
) | ||
|
||
func resourceNsxtUpgradePrecheckAcknowledge() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceNsxtUpgradePrecheckAcknowledgeCreate, | ||
Read: resourceNsxtUpgradePrecheckAcknowledgeRead, | ||
Update: resourceNsxtUpgradePrecheckAcknowledgeUpdate, | ||
Delete: resourceNsxtUpgradePrecheckAcknowledgeDelete, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"precheck_id": { | ||
Type: schema.TypeList, | ||
Description: "IDs of failed prechecks that user wants to acknowledge before upgrade", | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"id": { | ||
Type: schema.TypeString, | ||
Description: "ID of failed precheck to acknowledge", | ||
Required: true, | ||
}, | ||
}, | ||
}, | ||
Required: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourceNsxtUpgradePrecheckAcknowledgeCreate(d *schema.ResourceData, m interface{}) error { | ||
id := d.Id() | ||
if id == "" { | ||
id = newUUID() | ||
} | ||
d.SetId(id) | ||
precheckIDs := interface2StringList(d.Get("precheck_id").([]interface{})) | ||
connector := getPolicyConnector(m) | ||
client := upgrade.NewPreUpgradeChecksClient(connector) | ||
for _, precheckID := range precheckIDs { | ||
err := client.Acknowledge(precheckID) | ||
if err != nil { | ||
return handleCreateError("NsxtUpgradePrecheckAcknowledge", id, err) | ||
} | ||
} | ||
return resourceNsxtUpgradePrecheckAcknowledgeRead(d, m) | ||
} | ||
|
||
func resourceNsxtUpgradePrecheckAcknowledgeRead(d *schema.ResourceData, m interface{}) error { | ||
id := d.Id() | ||
precheckWarnings, err := getPrecheckErrors(m, nsxModel.UpgradeCheckFailure_TYPE_WARNING) | ||
if err != nil { | ||
return handleReadError(d, "NsxtUpgradePrecheckAcknowledge", id, err) | ||
} | ||
err = setAcknowledgedPrecheckIDsInSchema(d, precheckWarnings) | ||
if err != nil { | ||
return handleReadError(d, "NsxtUpgradePrecheckAcknowledge", id, err) | ||
} | ||
return nil | ||
} | ||
|
||
func setAcknowledgedPrecheckIDsInSchema(d *schema.ResourceData, precheckWarnings []nsxModel.UpgradeCheckFailure) error { | ||
var precheckWarningIDs []map[string]interface{} | ||
for _, precheckWarning := range precheckWarnings { | ||
elem := make(map[string]interface{}) | ||
if !(*precheckWarning.NeedsAck) { | ||
id := *precheckWarning.Id | ||
elem["id"] = id | ||
precheckWarningIDs = append(precheckWarningIDs, elem) | ||
} | ||
} | ||
return d.Set("precheck_id", precheckWarningIDs) | ||
} | ||
|
||
func resourceNsxtUpgradePrecheckAcknowledgeUpdate(d *schema.ResourceData, m interface{}) error { | ||
return nil | ||
} | ||
|
||
func resourceNsxtUpgradePrecheckAcknowledgeDelete(d *schema.ResourceData, m interface{}) error { | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,263 @@ | ||
/* Copyright © 2023 VMware, Inc. All Rights Reserved. | ||
SPDX-License-Identifier: MPL-2.0 */ | ||
|
||
package nsxt | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"time" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt-mp/nsx" | ||
nsxModel "github.com/vmware/vsphere-automation-sdk-go/services/nsxt-mp/nsx/model" | ||
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt-mp/nsx/upgrade" | ||
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt-mp/nsx/upgrade/bundles" | ||
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt-mp/nsx/upgrade/eula" | ||
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt-mp/nsx/upgrade/pre_upgrade_checks" | ||
) | ||
|
||
// URL to the upgrade bundle of an NSX build >= 4.1.1, will be used to upgrade UC if need to upload precheck bundle on NSX version < 4.1.1 | ||
const nsxt412UpgradeBundleURL string = "http://build-squid.eng.vmware.com/build/mts/release/bora-23074069/publish/upgrade/VMware-NSX-upgrade-bundle-4.1.2.2.0.23074069.mub" | ||
const nsxt412Version string = "4.1.2" | ||
|
||
func resourceNsxtUpgradePrepare() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceNsxtUpgradePrepareCreate, | ||
Read: resourceNsxtUpgradePrepareRead, | ||
Update: resourceNsxtUpgradePrepareUpdate, | ||
Delete: resourceNsxtUpgradePrepareDelete, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"upgrade_bundle_url": { | ||
Type: schema.TypeString, | ||
Description: "URL of the NSXT Upgrade bundle", | ||
Required: true, | ||
}, | ||
"precheck_bundle_url": { | ||
Type: schema.TypeString, | ||
Description: "URL of the NSXT Upgrade precheck bundle", | ||
Optional: true, | ||
}, | ||
"version": { | ||
Type: schema.TypeString, | ||
Description: "Version for the upgrade", | ||
Required: true, | ||
}, | ||
"accept_user_agreement": { | ||
Type: schema.TypeBool, | ||
Description: "Whether to accept the user agreement", | ||
Required: true, | ||
}, | ||
"failed_prechecks": { | ||
Type: schema.TypeList, | ||
Description: "List of failed prechecks for the upgrade, only include warnings, if precheck failed with error then the resource creation will fail", | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"id": { | ||
Type: schema.TypeString, | ||
Description: "ID of failed precheck", | ||
Computed: true, | ||
}, | ||
"message": { | ||
Type: schema.TypeString, | ||
Description: "Message of the failed precheck", | ||
Computed: true, | ||
}, | ||
}, | ||
}, | ||
Computed: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func uploadPrecheckAndUpgradeBundle(d *schema.ResourceData, m interface{}) error { | ||
upgradeBundleURL := d.Get("upgrade_bundle_url").(string) | ||
precheckBundleURL := d.Get("precheck_bundle_url").(string) | ||
upgradeBundleType := nsxModel.UpgradeBundleFetchRequest_BUNDLE_TYPE_UPGRADE | ||
precheckBundleType := nsxModel.UpgradeBundleFetchRequest_BUNDLE_TYPE_PRE_UPGRADE | ||
version := d.Get("version").(string) | ||
installParam := false | ||
c := m.(nsxtClients) | ||
userName := c.NsxtClientConfig.UserName | ||
password := c.NsxtClientConfig.Password | ||
// Upgrade coordinator on NSX version lower than 4.1.1 does not support uploading precheck bundle, | ||
// however this can be solved by upgrading the UC using a manager bundle from higher version. | ||
// Therefore if current NSX version is lower than 4.1.1 and precheck bundle is specified, | ||
// we first upload the Manager bundle from higher version (does not have to be upgrade target version) | ||
// Then upgrade precheck bundles. | ||
if nsxVersionLower("4.1.1") && len(precheckBundleURL) > 0 { | ||
url := nsxt412UpgradeBundleURL | ||
version := nsxt412Version | ||
err := uploadUpgradeBundle(m, url, userName, password, upgradeBundleType, version, installParam) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
if len(precheckBundleURL) > 0 { | ||
err := uploadUpgradeBundle(m, precheckBundleURL, userName, password, precheckBundleType, version, installParam) | ||
if err != nil { | ||
return fmt.Errorf("Failed to upload precheck bundle: %s", err) | ||
} | ||
} | ||
err := uploadUpgradeBundle(m, upgradeBundleURL, userName, password, upgradeBundleType, version, installParam) | ||
if err != nil { | ||
return fmt.Errorf("Failed to upload upgrade bundle: %s", err) | ||
} | ||
return nil | ||
} | ||
|
||
func uploadUpgradeBundle(m interface{}, url string, userName string, password string, bundleType string, version string, installParam bool) error { | ||
connector := getPolicyConnector(m) | ||
client := upgrade.NewBundlesClient(connector) | ||
bundleFetchRequest := nsxModel.UpgradeBundleFetchRequest{ | ||
BundleType: &bundleType, | ||
Password: &password, | ||
Username: &userName, | ||
Url: &url, | ||
Version: &version, | ||
} | ||
bundleID, err := client.Create(bundleFetchRequest, &installParam) | ||
if err != nil { | ||
return fmt.Errorf("Failed to upload upgrade bundle with ID %s: %s", bundleID, err) | ||
} | ||
return waitForBundleUpload(m, *bundleID.BundleId) | ||
} | ||
|
||
func acceptUserAgreement(d *schema.ResourceData, m interface{}) error { | ||
connector := getPolicyConnector(m) | ||
acceptUserAgreement := d.Get("accept_user_agreement").(bool) | ||
if !acceptUserAgreement { | ||
return fmt.Errorf("To proceed with upgrade, you must accept user agreement") | ||
} | ||
client := eula.NewAcceptClient(connector) | ||
err := client.Create() | ||
if err != nil { | ||
return handleCreateError("NsxtUpgradePrepare", "", err) | ||
} | ||
return nil | ||
} | ||
|
||
func executePreupgradeChecks(m interface{}) error { | ||
connector := getPolicyConnector(m) | ||
client := nsx.NewUpgradeClient(connector) | ||
return client.Executepreupgradechecks(nil, nil, nil, nil, nil, nil) | ||
} | ||
|
||
func getPrecheckErrors(m interface{}, typeParam string) ([]nsxModel.UpgradeCheckFailure, error) { | ||
connector := getPolicyConnector(m) | ||
client := pre_upgrade_checks.NewFailuresClient(connector) | ||
resultList, err := client.List(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, &typeParam, nil, nil) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return resultList.Results, nil | ||
} | ||
|
||
func setFailedPrechecksInSchema(d *schema.ResourceData, precheckWarnings []nsxModel.UpgradeCheckFailure) error { | ||
var failedPrechecksList []map[string]interface{} | ||
for _, warning := range precheckWarnings { | ||
id := *warning.Id | ||
message := *(warning.Message.Message) | ||
elem := make(map[string]interface{}) | ||
elem["id"] = id | ||
elem["message"] = message | ||
failedPrechecksList = append(failedPrechecksList, elem) | ||
} | ||
return d.Set("failed_prechecks", failedPrechecksList) | ||
} | ||
|
||
func resourceNsxtUpgradePrepareCreate(d *schema.ResourceData, m interface{}) error { | ||
id := d.Id() | ||
if id == "" { | ||
id = newUUID() | ||
} | ||
d.SetId(id) | ||
err := prepareForUpgrade(d, m) | ||
if err != nil { | ||
return handleCreateError("NsxtUpgradePrepare", id, err) | ||
} | ||
return resourceNsxtUpgradePrepareRead(d, m) | ||
} | ||
|
||
func prepareForUpgrade(d *schema.ResourceData, m interface{}) error { | ||
// 1. Upload upgrade bundle and wait for upload to complete, | ||
// UC will be automatically upgraded after this step | ||
err := uploadPrecheckAndUpgradeBundle(d, m) | ||
if err != nil { | ||
return fmt.Errorf("Failed to upload upgrade bundle: %s", err) | ||
} | ||
// 2. Accept user agreement | ||
err = acceptUserAgreement(d, m) | ||
if err != nil { | ||
return err | ||
} | ||
// 3. Execute pre-upgrade checks | ||
err = executePreupgradeChecks(m) | ||
if err != nil { | ||
return fmt.Errorf("Failed to execute pre-upgrade checks: %s", err) | ||
} | ||
// 4. Check if there is error in prechecks | ||
precheckFailures, err := getPrecheckErrors(m, nsxModel.UpgradeCheckFailure_TYPE_FAILURE) | ||
if err != nil { | ||
return fmt.Errorf("Failed to get precheck errors: %s", err) | ||
} | ||
if len(precheckFailures) > 0 { | ||
return fmt.Errorf("Encounter errors in precheck %s", *(precheckFailures[0].Message.Message)) | ||
} | ||
return nil | ||
} | ||
|
||
func resourceNsxtUpgradePrepareRead(d *schema.ResourceData, m interface{}) error { | ||
id := d.Id() | ||
precheckWarnings, err := getPrecheckErrors(m, nsxModel.UpgradeCheckFailure_TYPE_WARNING) | ||
if err != nil { | ||
return handleReadError(d, "NsxtUpgradePrepare", id, err) | ||
} | ||
err = setFailedPrechecksInSchema(d, precheckWarnings) | ||
if err != nil { | ||
return handleReadError(d, "NsxtUpgradePrepare", id, err) | ||
} | ||
return nil | ||
} | ||
|
||
func resourceNsxtUpgradePrepareUpdate(d *schema.ResourceData, m interface{}) error { | ||
id := d.Id() | ||
err := prepareForUpgrade(d, m) | ||
if err != nil { | ||
return handleUpdateError("NsxtUpgradePrepare", id, err) | ||
} | ||
return resourceNsxtUpgradePrepareRead(d, m) | ||
} | ||
|
||
func resourceNsxtUpgradePrepareDelete(d *schema.ResourceData, m interface{}) error { | ||
return nil | ||
} | ||
|
||
func waitForBundleUpload(m interface{}, bundleID string) error { | ||
connector := getPolicyConnector(m) | ||
client := bundles.NewUploadStatusClient(connector) | ||
// c := m.(nsxtClients) | ||
// Todo: | ||
// 1. utilize Min/Max RetryInterval in provider config | ||
interval := 20000 | ||
maxRetry := 50 | ||
for i := 0; i < 50; i++ { | ||
uploadStatus, err := client.Get(bundleID) | ||
if err != nil { | ||
return err | ||
} | ||
if *uploadStatus.Status == nsxModel.UpgradeBundleUploadStatus_STATUS_FAILED { | ||
return fmt.Errorf("Failed to upload upgrade bundle with id %s", bundleID) | ||
} | ||
if *uploadStatus.Status == nsxModel.UpgradeBundleUploadStatus_STATUS_SUCCESS { | ||
log.Printf("[DEBUG]: successfully uploaded upgrade bundle %s", bundleID) | ||
return nil | ||
} | ||
// interval := (rand.Intn(max-min) + min) | ||
time.Sleep(time.Duration(interval) * time.Millisecond) | ||
log.Printf("[DEBUG]: Waited %d ms before retrying getting upgrade bundle upload status", interval) | ||
} | ||
return fmt.Errorf("Upload bundle %s exceed timeout %v seconds", bundleID, (interval*maxRetry)/1000) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
--- | ||
subcategory: "Beta" | ||
layout: "nsxt" | ||
page_title: "NSXT: nsxt_upgrade_precheck_acknowledge" | ||
description: A resource to acknowledge failed NSXT upgrade prechecks. | ||
--- | ||
|
||
# nsxt_upgrade_precheck_acknowledge | ||
|
||
This resource provides a method for acknowledging the failed prechecks | ||
for NSXT upgrade. | ||
|
||
## Example Usage | ||
|
||
```hcl | ||
resource "nsxt_upgrade_precheck_acknowledge" "test" { | ||
precheck_id { | ||
id = "backupOperationCheck" | ||
} | ||
} | ||
``` | ||
|
||
## Argument Reference | ||
|
||
The following arguments are supported: | ||
|
||
* `precheck_id` - (Required) List of ids of failed prechecks user want to acknowledge. | ||
* `id` - (Required) Id of failed prechecks. | ||
|
||
## Importing | ||
|
||
Importing is not supported for this resource. |
Oops, something went wrong.