-
Notifications
You must be signed in to change notification settings - Fork 673
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 IBMi Software License field to instance data source and resource #5082
Changes from 29 commits
a1c8988
96e6e56
b8a1e9c
6da86d8
4080e04
cada08f
5128fad
656af92
317bbfe
f8e43d3
4554254
9b4713c
63fc536
38c6c2d
478bf9e
9bcd4f3
f636d6d
11f7b22
093c1e4
0765213
87a0af3
d3f94bf
8fd5882
edea06f
3ad81bb
77fe080
a92033e
d62aa7f
45840c2
daaf139
ed52a74
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -353,6 +353,28 @@ func ResourceIBMPIInstance() *schema.Resource { | |
Computed: true, | ||
Description: "Minimum Virtual Cores Assigned to the PVMInstance", | ||
}, | ||
PIInstanceIBMiCSS: { | ||
Type: schema.TypeBool, | ||
Optional: true, | ||
Description: "IBMi Cloud Storage Solution", | ||
}, | ||
PIInstanceIBMiPHA: { | ||
Type: schema.TypeBool, | ||
Optional: true, | ||
Description: "IBMi Power High Availability", | ||
}, | ||
PIInstanceIBMiRDS: { | ||
Type: schema.TypeBool, | ||
Optional: false, | ||
Required: false, | ||
Computed: true, | ||
Description: "IBMi Rational Dev Studio", | ||
}, | ||
PIInstanceIBMiRDSUsers: { | ||
Type: schema.TypeInt, | ||
Optional: true, | ||
Description: "IBMi Rational Dev Studio Number of User Licenses", | ||
}, | ||
}, | ||
} | ||
} | ||
|
@@ -513,7 +535,17 @@ func resourceIBMPIInstanceRead(ctx context.Context, d *schema.ResourceData, meta | |
d.Set("min_virtual_cores", powervmdata.VirtualCores.Min) | ||
} | ||
d.Set(helpers.PIInstanceLicenseRepositoryCapacity, powervmdata.LicenseRepositoryCapacity) | ||
|
||
d.Set(PIInstanceDeploymentType, powervmdata.DeploymentType) | ||
if powervmdata.SoftwareLicenses != nil { | ||
d.Set(PIInstanceIBMiCSS, powervmdata.SoftwareLicenses.IbmiCSS) | ||
d.Set(PIInstanceIBMiPHA, powervmdata.SoftwareLicenses.IbmiPHA) | ||
d.Set(PIInstanceIBMiRDS, powervmdata.SoftwareLicenses.IbmiRDS) | ||
if *powervmdata.SoftwareLicenses.IbmiRDS { | ||
d.Set(PIInstanceIBMiRDSUsers, powervmdata.SoftwareLicenses.IbmiRDSUsers) | ||
} else { | ||
d.Set(PIInstanceIBMiRDSUsers, 0) | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
|
@@ -568,7 +600,6 @@ func resourceIBMPIInstanceUpdate(ctx context.Context, d *schema.ResourceData, me | |
} | ||
|
||
if d.HasChange(helpers.PIInstanceProcType) { | ||
|
||
// Stop the lpar | ||
if d.Get("status") == "SHUTOFF" { | ||
log.Printf("the lpar is in the shutoff state. Nothing to do . Moving on ") | ||
|
@@ -677,7 +708,6 @@ func resourceIBMPIInstanceUpdate(ctx context.Context, d *schema.ResourceData, me | |
// License repository capacity will be updated only if service instance is a vtl instance | ||
// might need to check if lrc was set | ||
if d.HasChange(helpers.PIInstanceLicenseRepositoryCapacity) { | ||
|
||
lrc := d.Get(helpers.PIInstanceLicenseRepositoryCapacity).(int64) | ||
body := &models.PVMInstanceUpdate{ | ||
LicenseRepositoryCapacity: lrc, | ||
|
@@ -738,7 +768,6 @@ func resourceIBMPIInstanceUpdate(ctx context.Context, d *schema.ResourceData, me | |
} | ||
|
||
if d.HasChange(helpers.PIPlacementGroupID) { | ||
|
||
pgClient := st.NewIBMPIPlacementGroupClient(ctx, sess, cloudInstanceID) | ||
|
||
oldRaw, newRaw := d.GetChange(helpers.PIPlacementGroupID) | ||
|
@@ -772,8 +801,37 @@ func resourceIBMPIInstanceUpdate(ctx context.Context, d *schema.ResourceData, me | |
} | ||
} | ||
} | ||
return resourceIBMPIInstanceRead(ctx, d, meta) | ||
if d.HasChanges(PIInstanceIBMiCSS, PIInstanceIBMiPHA, PIInstanceIBMiRDSUsers) { | ||
if d.Get("status") == "ACTIVE" { | ||
log.Printf("the lpar is in the Active state, continuing with update") | ||
} else { | ||
_, err = isWaitForPIInstanceAvailable(ctx, client, instanceID, "OK") | ||
if err != nil { | ||
return diag.FromErr(err) | ||
} | ||
} | ||
|
||
sl := &models.SoftwareLicenses{} | ||
sl.IbmiCSS = flex.PtrToBool(d.Get(PIInstanceIBMiCSS).(bool)) | ||
sl.IbmiPHA = flex.PtrToBool(d.Get(PIInstanceIBMiPHA).(bool)) | ||
ibmrdsUsers := d.Get(PIInstanceIBMiRDSUsers).(int) | ||
if ibmrdsUsers < 0 { | ||
return diag.Errorf("request with IBMi Rational Dev Studio property requires IBMi Rational Dev Studio number of users") | ||
} | ||
Comment on lines
+818
to
+820
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not a requirement but we should be using ValidateFunc (ValidateDiagFunc) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's probably a bit more than I want to change for this PR. Probably mark it as an enhancement. |
||
sl.IbmiRDS = flex.PtrToBool(ibmrdsUsers > 0) | ||
sl.IbmiRDSUsers = int64(ibmrdsUsers) | ||
|
||
updatebody := &models.PVMInstanceUpdate{SoftwareLicenses: sl} | ||
_, err = client.Update(instanceID, updatebody) | ||
if err != nil { | ||
return diag.FromErr(err) | ||
} | ||
_, err = isWaitForPIInstanceSoftwareLicenses(ctx, client, instanceID, sl) | ||
if err != nil { | ||
return diag.FromErr(err) | ||
} | ||
} | ||
return resourceIBMPIInstanceRead(ctx, d, meta) | ||
} | ||
|
||
func resourceIBMPIInstanceDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { | ||
|
@@ -873,6 +931,59 @@ func isPIInstanceRefreshFunc(client *st.IBMPIInstanceClient, id, instanceReadySt | |
} | ||
} | ||
|
||
func isWaitForPIInstanceSoftwareLicenses(ctx context.Context, client *st.IBMPIInstanceClient, id string, softwareLicenses *models.SoftwareLicenses) (interface{}, error) { | ||
log.Printf("Waiting for PIInstance Software Licenses (%s) to be updated ", id) | ||
|
||
queryTimeOut := activeTimeOut | ||
|
||
stateConf := &resource.StateChangeConf{ | ||
Pending: []string{"notdone"}, | ||
Target: []string{"done"}, | ||
Refresh: isPIInstanceSoftwareLicensesRefreshFunc(client, id, softwareLicenses), | ||
Delay: 90 * time.Second, | ||
MinTimeout: queryTimeOut, | ||
Timeout: 120 * time.Minute, | ||
} | ||
|
||
return stateConf.WaitForStateContext(ctx) | ||
} | ||
|
||
func isPIInstanceSoftwareLicensesRefreshFunc(client *st.IBMPIInstanceClient, id string, softwareLicenses *models.SoftwareLicenses) resource.StateRefreshFunc { | ||
return func() (interface{}, string, error) { | ||
|
||
pvm, err := client.Get(id) | ||
if err != nil { | ||
return nil, "", err | ||
} | ||
|
||
// Check that each software license we modified has been updated | ||
if softwareLicenses.IbmiCSS != nil { | ||
if *softwareLicenses.IbmiCSS != *pvm.SoftwareLicenses.IbmiCSS { | ||
return pvm, "notdone", nil | ||
} | ||
} | ||
|
||
if softwareLicenses.IbmiPHA != nil { | ||
if *softwareLicenses.IbmiPHA != *pvm.SoftwareLicenses.IbmiPHA { | ||
return pvm, "notdone", nil | ||
} | ||
} | ||
|
||
if softwareLicenses.IbmiRDS != nil { | ||
// If the update set IBMiRDS to false, don't check IBMiRDSUsers as it will be updated on the terraform side on the read | ||
if !*softwareLicenses.IbmiRDS { | ||
if *softwareLicenses.IbmiRDS != *pvm.SoftwareLicenses.IbmiRDS { | ||
return pvm, "notdone", nil | ||
} | ||
} else if (*softwareLicenses.IbmiRDS != *pvm.SoftwareLicenses.IbmiRDS) || (softwareLicenses.IbmiRDSUsers != pvm.SoftwareLicenses.IbmiRDSUsers) { | ||
return pvm, "notdone", nil | ||
} | ||
} | ||
|
||
return pvm, "done", nil | ||
} | ||
} | ||
|
||
func isWaitForPIInstanceShutoff(ctx context.Context, client *st.IBMPIInstanceClient, id string, instanceReadyStatus string) (interface{}, error) { | ||
log.Printf("Waiting for PIInstance (%s) to be shutoff and health active ", id) | ||
|
||
|
@@ -1336,18 +1447,15 @@ func createPVMInstance(d *schema.ResourceData, client *st.IBMPIInstanceClient, i | |
if spp, ok := d.GetOk(Arg_PIInstanceSharedProcessorPool); ok { | ||
body.SharedProcessorPool = spp.(string) | ||
} | ||
|
||
if lrc, ok := d.GetOk(helpers.PIInstanceLicenseRepositoryCapacity); ok { | ||
// check if using vtl image | ||
// check if vtl image is stock image | ||
imageData, err := imageClient.GetStockImage(imageid) | ||
imageData, err := imageClient.GetStockImage(imageid) | ||
if err != nil { | ||
// check if vtl image is cloud instance image | ||
imageData, err = imageClient.Get(imageid) | ||
if err != nil { | ||
// check if vtl image is cloud instance image | ||
imageData, err = imageClient.Get(imageid) | ||
if err != nil { | ||
return nil, fmt.Errorf("image doesn't exist. %e", err) | ||
} | ||
return nil, fmt.Errorf("image doesn't exist. %e", err) | ||
} | ||
} | ||
if lrc, ok := d.GetOk(helpers.PIInstanceLicenseRepositoryCapacity); ok { | ||
|
||
if imageData.Specifications.ImageType == "stock-vtl" { | ||
body.LicenseRepositoryCapacity = int64(lrc.(int)) | ||
|
@@ -1356,6 +1464,31 @@ func createPVMInstance(d *schema.ResourceData, client *st.IBMPIInstanceClient, i | |
} | ||
} | ||
|
||
if imageData.Specifications.OperatingSystem == OS_IBMI { | ||
// Default value | ||
falseBool := false | ||
sl := &models.SoftwareLicenses{ | ||
IbmiCSS: &falseBool, | ||
IbmiPHA: &falseBool, | ||
IbmiRDS: &falseBool, | ||
IbmiRDSUsers: 0, | ||
} | ||
if ibmiCSS, ok := d.GetOk(PIInstanceIBMiCSS); ok { | ||
sl.IbmiCSS = flex.PtrToBool(ibmiCSS.(bool)) | ||
} | ||
if ibmiPHA, ok := d.GetOk(PIInstanceIBMiPHA); ok { | ||
sl.IbmiPHA = flex.PtrToBool(ibmiPHA.(bool)) | ||
} | ||
if ibmrdsUsers, ok := d.GetOk(PIInstanceIBMiRDSUsers); ok { | ||
if ibmrdsUsers.(int) < 0 { | ||
return nil, fmt.Errorf("request with IBMi Rational Dev Studio property requires IBMi Rational Dev Studio number of users") | ||
} | ||
Comment on lines
+1483
to
+1485
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
sl.IbmiRDS = flex.PtrToBool(ibmrdsUsers.(int) > 0) | ||
sl.IbmiRDSUsers = int64(ibmrdsUsers.(int)) | ||
} | ||
body.SoftwareLicenses = sl | ||
} | ||
|
||
pvmList, err := client.Create(body) | ||
|
||
if err != nil { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kind of contradicting.
Here is the doc:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yussufsh I believe there is no contradiction, since the attribute is set by the provider as mention above if both false fir
Required
andOptional
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Computed cannot be used with Required.
Just Computed = true was enough.
Just common logic:
Required = true (cannot be Optional)
Optional = true (cannot be Required)