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

Enable linked multiple flexible GPUs to VM #393

Closed
wants to merge 1 commit into from
Closed
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
238 changes: 129 additions & 109 deletions outscale/resource_outscale_flexible_gpu_link.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,20 @@ func resourceOutscaleOAPIFlexibleGpuLink() *schema.Resource {
return &schema.Resource{
Create: resourceOutscaleOAPIFlexibleGpuLinkCreate,
Read: resourceOutscaleOAPIFlexibleGpuLinkRead,
Update: resourceFlexibleGpuLinkUpdate,
Delete: resourceOutscaleOAPIFlexibleGpuLinkDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"flexible_gpu_id": {
Type: schema.TypeString,
"flexible_gpu_ids": {
Type: schema.TypeSet,
Required: true,
ForceNew: true,
MinItems: 1,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"vm_id": {
Type: schema.TypeString,
Expand All @@ -42,61 +46,31 @@ func resourceOutscaleOAPIFlexibleGpuLink() *schema.Resource {

func resourceOutscaleOAPIFlexibleGpuLinkCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*OutscaleClient).OSCAPI

flexGpuID := d.Get("flexible_gpu_id").(string)
vmId := d.Get("vm_id").(string)
GpuIdsList := utils.SetToStringSlice(d.Get("flexible_gpu_ids").(*schema.Set))

filter := &oscgo.FiltersFlexibleGpu{
FlexibleGpuIds: &[]string{flexGpuID},
}
reqFlex := &oscgo.ReadFlexibleGpusRequest{
Filters: filter,
}
reqLink := oscgo.LinkFlexibleGpuRequest{
FlexibleGpuId: flexGpuID,
VmId: vmId,
}
var resp oscgo.LinkFlexibleGpuResponse
err := resource.Retry(60*time.Second, func() *resource.RetryError {
var err error
rp, httpResp, err := conn.FlexibleGpuApi.LinkFlexibleGpu(
context.Background()).LinkFlexibleGpuRequest(reqLink).Execute()
if err != nil {
return utils.CheckThrottling(httpResp, err)
for _, flexGpuID := range GpuIdsList {
var resp oscgo.LinkFlexibleGpuResponse
reqLink := oscgo.LinkFlexibleGpuRequest{
FlexibleGpuId: flexGpuID,
VmId: vmId,
}
resp = rp
return nil
})

if err != nil {
return fmt.Errorf("Error Link flexibe gpu: %s", err.Error())
}

if !resp.HasResponseContext() {
return fmt.Errorf("Error there is not Link flexible gpu (%s)", err)
}

var respV oscgo.ReadFlexibleGpusResponse
err = resource.Retry(60*time.Second, func() *resource.RetryError {
rp, httpResp, err := conn.FlexibleGpuApi.ReadFlexibleGpus(context.Background()).
ReadFlexibleGpusRequest(*reqFlex).Execute()
err := resource.Retry(60*time.Second, func() *resource.RetryError {
var err error
rp, httpResp, err := conn.FlexibleGpuApi.LinkFlexibleGpu(
context.Background()).LinkFlexibleGpuRequest(reqLink).Execute()
if err != nil {
return utils.CheckThrottling(httpResp, err)
}
resp = rp
return nil
})
if err != nil {
return utils.CheckThrottling(httpResp, err)
return fmt.Errorf("Error Link flexibe gpu: %s", err.Error())
}
if !resp.HasResponseContext() {
return fmt.Errorf("Error there is not Link flexible gpu (%s)", err)
}
respV = rp
return nil
})

if err != nil {
return fmt.Errorf("error reading the FlexibleGpu %s", err)
}

if err := utils.IsResponseEmptyOrMutiple(len(respV.GetFlexibleGpus()), "FlexibleGpu"); err != nil {
return err
}

if (*respV.FlexibleGpus)[0].GetState() != "attaching" {
return fmt.Errorf("Unable to link Flexible GPU")
}

if err := changeShutdownBehavior(conn, vmId); err != nil {
Expand All @@ -108,19 +82,15 @@ func resourceOutscaleOAPIFlexibleGpuLinkCreate(d *schema.ResourceData, meta inte

func resourceOutscaleOAPIFlexibleGpuLinkRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*OutscaleClient).OSCAPI

flexGpuID := d.Get("flexible_gpu_id").(string)
if flexGpuID == "" {
flexGpuID = d.Id()
}
vmId := d.Get("vm_id").(string)
req := &oscgo.ReadFlexibleGpusRequest{
Filters: &oscgo.FiltersFlexibleGpu{
FlexibleGpuIds: &[]string{flexGpuID},
VmIds: &[]string{vmId},
},
}

var resp oscgo.ReadFlexibleGpusResponse
var err error

err = resource.Retry(60*time.Second, func() *resource.RetryError {
rp, httpResp, err := conn.FlexibleGpuApi.ReadFlexibleGpus(
context.Background()).
Expand All @@ -139,82 +109,132 @@ func resourceOutscaleOAPIFlexibleGpuLinkRead(d *schema.ResourceData, meta interf
d.SetId("")
return nil
}

fg := (*resp.FlexibleGpus)[0]
if err := d.Set("flexible_gpu_id", fg.GetFlexibleGpuId()); err != nil {
flexGpus := resp.GetFlexibleGpus()[:]
readGpuIdsLink := make([]string, len(flexGpus))
for k, flexGpu := range flexGpus {
readGpuIdsLink[k] = flexGpu.GetFlexibleGpuId()
}
if err := d.Set("flexible_gpu_ids", readGpuIdsLink); err != nil {
return err
}
if err := d.Set("vm_id", fg.GetVmId()); err != nil {
if err := d.Set("vm_id", vmId); err != nil {
return err
}
d.SetId(fg.GetFlexibleGpuId())

d.SetId(resource.UniqueId())
return nil
}

func resourceOutscaleOAPIFlexibleGpuLinkDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*OutscaleClient).OSCAPI

flexGpuID := d.Get("flexible_gpu_id").(string)
vmId := d.Get("vm_id").(string)

filter := &oscgo.FiltersFlexibleGpu{
FlexibleGpuIds: &[]string{flexGpuID},
}
reqFlex := &oscgo.ReadFlexibleGpusRequest{
Filters: filter,
}

req := &oscgo.UnlinkFlexibleGpuRequest{
FlexibleGpuId: flexGpuID,
}

GpuIdsList := utils.SetToStringSlice(d.Get("flexible_gpu_ids").(*schema.Set))
var err error
err = resource.Retry(20*time.Second, func() *resource.RetryError {
_, httpResp, err := conn.FlexibleGpuApi.UnlinkFlexibleGpu(
context.Background()).UnlinkFlexibleGpuRequest(*req).Execute()

for _, flexGpuID := range GpuIdsList {
req := &oscgo.UnlinkFlexibleGpuRequest{
FlexibleGpuId: flexGpuID,
}
err = resource.Retry(20*time.Second, func() *resource.RetryError {
_, httpResp, err := conn.FlexibleGpuApi.UnlinkFlexibleGpu(
context.Background()).UnlinkFlexibleGpuRequest(*req).Execute()
if err != nil {
return utils.CheckThrottling(httpResp, err)
}
return nil
})
if err != nil {
return utils.CheckThrottling(httpResp, err)
return err
}
return nil
})

if err != nil {
return err
}

var resp oscgo.ReadFlexibleGpusResponse
err = resource.Retry(60*time.Second, func() *resource.RetryError {
rp, httpResp, err := conn.FlexibleGpuApi.ReadFlexibleGpus(context.Background()).
ReadFlexibleGpusRequest(*reqFlex).Execute()
var resp oscgo.ReadFlexibleGpusResponse
reqFlex := &oscgo.ReadFlexibleGpusRequest{
Filters: &oscgo.FiltersFlexibleGpu{
FlexibleGpuIds: &[]string{flexGpuID},
},
}
err = resource.Retry(60*time.Second, func() *resource.RetryError {
rp, httpResp, err := conn.FlexibleGpuApi.ReadFlexibleGpus(context.Background()).
ReadFlexibleGpusRequest(*reqFlex).Execute()
if err != nil {
return utils.CheckThrottling(httpResp, err)
}
resp = rp
return nil
})
if err != nil {
return utils.CheckThrottling(httpResp, err)
return fmt.Errorf("error reading the FlexibleGpu %s", err)
}
resp = rp
return nil
})
if err != nil {
return fmt.Errorf("error reading the FlexibleGpu %s", err)
}

if len(*resp.FlexibleGpus) != 1 {
return fmt.Errorf("Unable to find Flexible GPU")
}
if (*resp.FlexibleGpus)[0].GetState() != "detaching" {
return fmt.Errorf("Unable to unlink Flexible GPU")
if len(*resp.FlexibleGpus) != 1 {
return fmt.Errorf("Unable to find Flexible GPU")
}
if (*resp.FlexibleGpus)[0].GetState() != "detaching" {
return fmt.Errorf("Unable to unlink Flexible GPU")
}
}

if err := changeShutdownBehavior(conn, vmId); err != nil {
if err := changeShutdownBehavior(conn, d.Get("vm_id").(string)); err != nil {
return fmt.Errorf("Unable to change ShutdownBehavior: %s\n", err)
}

d.SetId("")
return nil
}

func resourceFlexibleGpuLinkUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*OutscaleClient).OSCAPI
vmId := d.Get("vm_id").(string)
oldIds, newIds := d.GetChange("flexible_gpu_ids")

interIds := oldIds.(*schema.Set).Intersection(newIds.(*schema.Set))
toCreate := newIds.(*schema.Set).Difference(interIds)
toRemove := oldIds.(*schema.Set).Difference(interIds)
var err error

if toRemove.Len() > 0 {
for _, flexGpuID := range utils.SetToStringSlice(toRemove) {
req := &oscgo.UnlinkFlexibleGpuRequest{
FlexibleGpuId: flexGpuID,
}
err = resource.Retry(20*time.Second, func() *resource.RetryError {
_, httpResp, err := conn.FlexibleGpuApi.UnlinkFlexibleGpu(
context.Background()).UnlinkFlexibleGpuRequest(*req).Execute()
if err != nil {
return utils.CheckThrottling(httpResp, err)
}
return nil
})
if err != nil {
return err
}
}
}
if toCreate.Len() > 0 {
for _, flexGpuID := range utils.SetToStringSlice(toCreate) {
req := &oscgo.LinkFlexibleGpuRequest{
FlexibleGpuId: flexGpuID,
VmId: vmId,
}
err = resource.Retry(20*time.Second, func() *resource.RetryError {
_, httpResp, err := conn.FlexibleGpuApi.LinkFlexibleGpu(
context.Background()).LinkFlexibleGpuRequest(*req).Execute()
if err != nil {
return utils.CheckThrottling(httpResp, err)
}
return nil
})
if err != nil {
return err
}
}
}
if err := changeShutdownBehavior(conn, vmId); err != nil {
return fmt.Errorf("Unable to change ShutdownBehavior: %s\n", err)
}

return resourceOutscaleOAPIFlexibleGpuLinkRead(d, meta)
}

func changeShutdownBehavior(conn *oscgo.APIClient, vmId string) error {

var resp oscgo.ReadVmsResponse
err := resource.Retry(20*time.Second, func() *resource.RetryError {
rp, httpResp, err := conn.VmApi.ReadVms(context.Background()).ReadVmsRequest(oscgo.ReadVmsRequest{
Expand Down
14 changes: 9 additions & 5 deletions outscale/resource_outscale_flexible_gpu_link_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,21 @@ func testAccOutscaleOAPIFlexibleGpuLinkConfig(omi, vmType, region string) string

}

resource "outscale_flexible_gpu" "fGPU-1" {
resource "outscale_flexible_gpu" "fGPU-1" {
model_name = "nvidia-p6"
generation = "v5"
subregion_name = "%[3]sa"
subregion_name = "%[3]s"
delete_on_vm_deletion = true
}
resource "outscale_flexible_gpu" "fGPU-2" {
model_name = "nvidia-p6"
generation = "v5"
subregion_name = "%[3]s"
delete_on_vm_deletion = true
}

resource "outscale_flexible_gpu_link" "link_fGPU" {
flexible_gpu_id = outscale_flexible_gpu.fGPU-1.flexible_gpu_id
flexible_gpu_ids = [outscale_flexible_gpu.fGPU-1.flexible_gpu_id,outscale_flexible_gpu.fGPU-2.flexible_gpu_id]
vm_id = outscale_vm.basic.vm_id
}

`, omi, vmType, region)
}
Loading