Skip to content
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

Add Upgrade Run Resource #1085

Merged
merged 1 commit into from
Feb 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions nsxt/data_source_nsxt_edge_upgrade_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
var (
edgeUpgradeGroup = "EDGE"
hostUpgradeGroup = "HOST"
mpUpgradeGroup = "MP"
)

func dataSourceNsxtEdgeUpgradeGroup() *schema.Resource {
Expand Down
159 changes: 159 additions & 0 deletions nsxt/data_source_nsxt_upgrade_postcheck.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/* Copyright © 2024 VMware, Inc. All Rights Reserved.
SPDX-License-Identifier: MPL-2.0 */

package nsxt

import (
"fmt"
"time"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt-mp/nsx/model"
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt-mp/nsx/upgrade/upgrade_unit_groups"
)

var (
// Default waiting setup in seconds
defaultUpgradePostcheckInterval = 30
defaultUpgradePostcheckTimeout = 1800
defaultUpgradePostcheckDelay = 30
)

func dataSourceNsxtUpgradePostCheck() *schema.Resource {
return &schema.Resource{
Read: dataSourceNsxtUpgradePostCheckRead,

Schema: map[string]*schema.Schema{
"upgrade_run_id": {
Type: schema.TypeString,
Description: "ID of corresponding nsxt_upgrade_run resource",
Required: true,
},
"type": {
Type: schema.TypeString,
Description: "Component Type",
Required: true,
ValidateFunc: validation.StringInSlice([]string{edgeUpgradeGroup, hostUpgradeGroup}, false),
},
"timeout": {
Type: schema.TypeInt,
Description: "Post-check status checks timeout in seconds",
Optional: true,
Default: defaultUpgradePostcheckTimeout,
ValidateFunc: validation.IntAtLeast(1),
},
"interval": {
Type: schema.TypeInt,
Description: "Interval to check Post-check status in seconds",
Optional: true,
Default: defaultUpgradePostcheckInterval,
ValidateFunc: validation.IntAtLeast(1),
},
"delay": {
Type: schema.TypeInt,
Description: "Initial delay to start Post-check status checks in seconds",
Optional: true,
Default: defaultUpgradePostcheckDelay,
ValidateFunc: validation.IntAtLeast(0),
},
"failed_group": {
Type: schema.TypeList,
Description: "Upgrade unit groups that failed in upgrade post-checks",
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"id": {
Type: schema.TypeString,
Description: "Unique identifier of upgrade unit group",
Required: true,
},
"status": {
Type: schema.TypeString,
Description: "Status of execution of upgrade post-checks",
Computed: true,
},
"details": {
Type: schema.TypeString,
Description: "Details about current execution of upgrade post-checks",
Computed: true,
},
"failure_count": {
Type: schema.TypeInt,
Description: "Total count of generated failures or warnings in last execution of upgrade post-checks",
Computed: true,
},
},
},
},
},
}
}

func dataSourceNsxtUpgradePostCheckRead(d *schema.ResourceData, m interface{}) error {
connector := getPolicyConnector(m)
aggregateInfoClient := upgrade_unit_groups.NewAggregateInfoClient(connector)
component := d.Get("type").(string)
timeout := d.Get("timeout").(int)
interval := d.Get("interval").(int)
delay := d.Get("delay").(int)

stateConf := &resource.StateChangeConf{
Pending: []string{model.UpgradeChecksExecutionStatus_STATUS_IN_PROGRESS},
Target: []string{model.UpgradeChecksExecutionStatus_STATUS_COMPLETED},
Refresh: func() (interface{}, string, error) {
listRes, err := aggregateInfoClient.List(&component, nil, nil, nil, nil, nil, nil, nil)
if err != nil {
return nil, "", fmt.Errorf("failed to retrieve %s upgrade post-check results: %v", component, err)
}
for _, res := range listRes.Results {
if *res.PostUpgradeStatus.Status == model.UpgradeChecksExecutionStatus_STATUS_IN_PROGRESS {
return res.PostUpgradeStatus, model.UpgradeChecksExecutionStatus_STATUS_IN_PROGRESS, nil
}
}
// Return UpgradeChecksExecutionStatus_STATUS_COMPLETED here doesn't mean all UpgradeUnitGroup post-checks are completed.
// Just to stop polling the states as none of UpgradeUnitGroup is in in_progress state.
return listRes, model.UpgradeChecksExecutionStatus_STATUS_COMPLETED, nil
},
Timeout: time.Duration(timeout) * time.Second,
PollInterval: time.Duration(interval) * time.Second,
Delay: time.Duration(delay) * time.Second,
}

_, err := stateConf.WaitForState()
if err != nil {
return err
}

listRes, err := aggregateInfoClient.List(&component, nil, nil, nil, nil, nil, nil, nil)
if err != nil {
return fmt.Errorf("failed to retrieve %s upgrade post-check result: %v", component, err)
}
var failedGroup []map[string]interface{}
for _, res := range listRes.Results {
failureCounts := 0
if res.PostUpgradeStatus.FailureCount != nil {
failureCounts = int(*res.PostUpgradeStatus.FailureCount)
} else if res.PostUpgradeStatus.NodeWithIssuesCount != nil {
failureCounts = int(*res.PostUpgradeStatus.NodeWithIssuesCount)
}
if res.PostUpgradeStatus.Status != nil && *res.PostUpgradeStatus.Status != model.UpgradeChecksExecutionStatus_STATUS_COMPLETED || failureCounts > 0 {
elem := make(map[string]interface{}, 4)
elem["status"] = *res.PostUpgradeStatus.Status
GraysonWu marked this conversation as resolved.
Show resolved Hide resolved
elem["failure_count"] = failureCounts
if res.Id != nil {
elem["id"] = *res.Id
}
if res.PostUpgradeStatus.Details != nil {
elem["details"] = *res.PostUpgradeStatus.Details
}
failedGroup = append(failedGroup, elem)
}
}
if len(failedGroup) > 0 {
d.Set("failed_group", failedGroup)
}

return nil
}
14 changes: 14 additions & 0 deletions nsxt/policy_errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,20 @@ func isNotFoundError(err error) bool {
return false
}

func isServiceUnavailableError(err error) bool {
if _, ok := err.(errors.ServiceUnavailable); ok {
return true
}
return false
}

func isTimeoutError(err error) bool {
if _, ok := err.(errors.TimedOut); ok {
return true
}
return false
}

func handleCreateError(resourceType string, resource string, err error) error {
msg := fmt.Sprintf("Failed to create %s %s", resourceType, resource)
return logAPIError(msg, err)
Expand Down
6 changes: 6 additions & 0 deletions nsxt/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ func Provider() *schema.Provider {
"nsxt_edge_upgrade_group": dataSourceNsxtEdgeUpgradeGroup(),
"nsxt_host_upgrade_group": dataSourceNsxtHostUpgradeGroup(),
"nsxt_policy_gateway_interface_realization_info": dataSourceNsxtPolicyGatewayInterfaceRealizationInfo(),
"nsxt_upgrade_postcheck": dataSourceNsxtUpgradePostCheck(),
},

ResourcesMap: map[string]*schema.Resource{
Expand Down Expand Up @@ -471,6 +472,7 @@ func Provider() *schema.Provider {
"nsxt_policy_lb_tcp_monitor_profile": resourceNsxtPolicyLBTcpMonitorProfile(),
"nsxt_policy_lb_udp_monitor_profile": resourceNsxtPolicyLBUdpMonitorProfile(),
"nsxt_policy_tier0_gateway_gre_tunnel": resourceNsxtPolicyTier0GatewayGRETunnel(),
"nsxt_upgrade_run": resourceNsxtUpgradeRun(),
},

ConfigureFunc: providerConfigure,
Expand Down Expand Up @@ -1062,6 +1064,10 @@ func getPolicyConnector(clients interface{}) client.Connector {
return getPolicyConnectorWithHeaders(clients, nil, false, true)
}

func getPolicyConnectorWithoutRetry(clients interface{}) client.Connector {
return getPolicyConnectorWithHeaders(clients, nil, false, false)
}

// Standalone policy connector, possibly for different endpoint,
// for the purpose of special tasks (such as joining manager cluster node)
// Does not initialize global connection settings
Expand Down
Loading
Loading