Skip to content

Commit

Permalink
Update task handling of hypervisor cluster create
Browse files Browse the repository at this point in the history
Update the polling of a hypervisor cluster create task.  In the case of
hypervisor create, the `sourceResourceUri` field in the final task response
points to a `system` and not the hypervisor cluster that has just been created.
(This differs from the task behaviour for datastores.)

Switch to instead extract the hypervisor cluster uuid from the returned task
body's `associatedResources` list. (Note that the `associatedResources` list
for datastores is empty, so we cannot consistently use this approach.)

```
  "associatedResources": [
    {
      "name": "cluster1",
      "resourceUri": "/virtualization/v1beta1/hypervisor-clusters/298a299e-78f5-5acb-86ce-4e9fdc290ab7",
      "type": "hypervisor-cluster"
    }
  ]

```

This change avoids terraform erroring after a successful hypervisor create.
  • Loading branch information
stuart-mclaren-hpe committed Nov 14, 2024
1 parent 0ccc6fa commit f203f27
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 23 deletions.
11 changes: 6 additions & 5 deletions internal/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
package constants

const (
ProviderType = "hpegl"
ProviderBlock = "pc"
NameFilter = "name eq "
HciClusterUUIDFilter = "hciClusterUuid eq "
AndFilter = " and "
ProviderType = "hpegl"
ProviderBlock = "pc"
NameFilter = "name eq "
HciClusterUUIDFilter = "hciClusterUuid eq "
AndFilter = " and "
TaskHypervisorCluster = "hypervisor-cluster" // task's "associatedResources" string
)
20 changes: 7 additions & 13 deletions internal/poll/operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ import (
)

// AsyncOperation polls an asynchronous operation until it completes.
// It returns the URI of the source resource of the operation.
// It returns the response of the async operation.
func AsyncOperation(
ctx context.Context,
client client.PCBeClient,
OperationID string,
diagsP *diag.Diagnostics,
) *string {
) dataservices.V1beta1AsyncOperationsItemAsyncOperationsGetResponseable {
maxPolls := int(client.Config.MaxPolls)
pollWaitTime := time.Duration(client.Config.PollInterval) * time.Second

Expand All @@ -35,7 +35,6 @@ func AsyncOperation(
V1beta1AsyncOperationsAsyncOperationsItemRequestBuilderGetRequestConfiguration{}

for count := 1; ; count++ {

opResp, err = asyncClient.DataServices().
V1beta1().
AsyncOperations().
Expand All @@ -51,33 +50,29 @@ func AsyncOperation(
}

if opResp == nil {
msg := "nil op response"
(*diagsP).AddError(
"error polling async operation "+OperationID,
msg,
"nil op response",
)

return nil
}

opRespState := opResp.GetState()
if opRespState == nil {
msg := "operation has nil state"
(*diagsP).AddError(
"error polling async operation "+OperationID,
msg,
"operation has nil state",
)

return nil
}

// TODO: (API) Use enum not string for state when FF-28181 is fixed
if *opRespState == "FAILED" {
msg := "operation state FAILED"

(*diagsP).AddError(
"error polling async operation "+OperationID,
msg,
"operation state FAILED",
)

return nil
Expand All @@ -89,10 +84,9 @@ func AsyncOperation(
}

if count == maxPolls {
msg := "max polls exceeded"
(*diagsP).AddError(
"error polling async operation "+OperationID,
msg,
"max polls exceeded",
)

return nil
Expand All @@ -101,5 +95,5 @@ func AsyncOperation(
time.Sleep(pollWaitTime)
}

return opResp.GetSourceResourceUri()
return opResp
}
46 changes: 42 additions & 4 deletions internal/resources/hypervisorcluster/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"path"

"github.com/HewlettPackard/hpegl-pcbe-terraform-resources/internal/client"
"github.com/HewlettPackard/hpegl-pcbe-terraform-resources/internal/constants"
"github.com/HewlettPackard/hpegl-pcbe-terraform-resources/internal/poll"
"github.com/HewlettPackard/hpegl-pcbe-terraform-resources/internal/sdk/systems/privatecloudbusiness"
"github.com/HewlettPackard/hpegl-pcbe-terraform-resources/internal/sdk/virt/virtualization"
Expand Down Expand Up @@ -289,12 +290,12 @@ func doCreate(
location := sysHeaderOpts.GetResponseHeaders().Get("Location")[0]
sysHeaderOpts.ResponseHeaders.Clear()
operationID := path.Base(location)
sourceURI := poll.AsyncOperation(ctx, client, operationID, diagsP)
opResp := poll.AsyncOperation(ctx, client, operationID, diagsP)
if (*diagsP).HasError() {
return
}

if sourceURI == nil {
if opResp == nil {
(*diagsP).AddError(
"error creating hypervisorcluster",
"async operation did not return a source uri",
Expand All @@ -303,8 +304,45 @@ func doCreate(
return
}

// Set id in state as early as possible
hypervisorClusterID := path.Base(*sourceURI)
if len(opResp.GetAssociatedResources()) != 1 {
(*diagsP).AddError(
"error creating hypervisorcluster",
fmt.Sprintf("could not parse async operation. "+
"Unexpected length of associatedResources (%d)",
len(opResp.GetAssociatedResources()),
),
)

return

}

if opResp.GetAssociatedResources()[0].GetTypeEscaped() == nil {
(*diagsP).AddError(
"error creating hypervisorcluster",
fmt.Sprintf("could not parse async operation. "+
"associatedResources is nil",
),
)

return
}

if *(opResp.GetAssociatedResources()[0].GetTypeEscaped()) !=
constants.TaskHypervisorCluster {
(*diagsP).AddError(
"error creating hypervisorcluster",
fmt.Sprintf("could not parse async operation. "+
"Unexpected type for associatedResources (%s)",
*(opResp.GetAssociatedResources()[0].GetTypeEscaped()),
),
)

return
}

// Allow setting id in state as early as possible
hypervisorClusterID := path.Base(*(opResp.GetAssociatedResources()[0].GetResourceUri()))
(*dataP).Id = types.StringValue(hypervisorClusterID)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"associatedResources":[],"createdAt":"2024-07-12T13:29:49.396923456Z","customerId":"aeb7487a336f11ec9ad0c2951b4ee305","displayName":"Deleting the virtual machine 'mclaren18'","endedAt":"2024-07-12T13:29:50.440016018Z","error":null,"estimatedRunningDurationMinutes":300,"generation":3,"groups":[{"id":"aeb7487a336f11ec9ad0c2951b4ee305","name":"Default Group"}],"hasChildOperations":false,"healthStatus":"OK","id":"99992745-532b-404c-860c-20a6571b92c3","logMessages":[{"message":"delete task is created","timestamp":"2024-07-12T13:29:49.396929492Z"},{"message":"delete task is running","timestamp":"2024-07-12T13:29:49.396930707Z"},{"message":"attempting to delete the virtual machine","timestamp":"2024-07-12T13:29:49.566952371Z"},{"message":"delete task completed","timestamp":"2024-07-12T13:29:50.440017383Z"}],"name":"delete","parent":null,"progressPercent":100,"recommendations":[],"resourceUri":"/data-services/v1beta1/async-operations/99992745-532b-404c-860c-20a6571b92c3","rootOperation":{"id":"99992745-532b-404c-860c-20a6571b92c3","name":"","resourceUri":"/data-services/v1beta1/async-operations/99992745-532b-404c-860c-20a6571b92c3","type":"task"},"services":["private-cloud-business-edition","backup-and-recovery"],"sourceResourceUri":"/virtualization/v1beta1/hypervisor-clusters/298a299e-78f5-5acb-86ce-4e9fdc290ab7","startedAt":"2024-07-12T13:29:49.396925772Z","state":"SUCCEEDED","subtreeOperationCount":0,"suggestedPollingIntervalSeconds":30,"type":"task","updatedAt":"2024-07-12T13:29:50.456819656Z","userId":"[email protected]"}
{"associatedResources":[{"name":"mclaren01","resourceUri":"/virtualization/v1beta1/hypervisor-clusters/298a299e-78f5-5acb-86ce-4e9fdc290ab7","type" :"hypervisor-cluster"}],"createdAt":"2024-07-12T13:29:49.396923456Z","customerId":"aeb7487a336f11ec9ad0c2951b4ee305","displayName":"Deleting the virtual machine 'mclaren18'","endedAt":"2024-07-12T13:29:50.440016018Z","error":null,"estimatedRunningDurationMinutes":300,"generation":3,"groups":[{"id":"aeb7487a336f11ec9ad0c2951b4ee305","name":"Default Group"}],"hasChildOperations":false,"healthStatus":"OK","id":"99992745-532b-404c-860c-20a6571b92c3","logMessages":[{"message":"delete task is created","timestamp":"2024-07-12T13:29:49.396929492Z"},{"message":"delete task is running","timestamp":"2024-07-12T13:29:49.396930707Z"},{"message":"attempting to delete the virtual machine","timestamp":"2024-07-12T13:29:49.566952371Z"},{"message":"delete task completed","timestamp":"2024-07-12T13:29:50.440017383Z"}],"name":"delete","parent":null,"progressPercent":100,"recommendations":[],"resourceUri":"/data-services/v1beta1/async-operations/99992745-532b-404c-860c-20a6571b92c3","rootOperation":{"id":"99992745-532b-404c-860c-20a6571b92c3","name":"","resourceUri":"/data-services/v1beta1/async-operations/99992745-532b-404c-860c-20a6571b92c3","type":"task"},"services":["private-cloud-business-edition","backup-and-recovery"],"sourceResourceUri":"/private-cloud-business/v1beta1/systems/126fd201-9e6e-5e31-9ffb-a766265b1fd3","startedAt":"2024-07-12T13:29:49.396925772Z","state":"SUCCEEDED","subtreeOperationCount":0,"suggestedPollingIntervalSeconds":30,"type":"task","updatedAt":"2024-07-12T13:29:50.456819656Z","userId":"[email protected]"}

0 comments on commit f203f27

Please sign in to comment.