github.com/minamijoyo/terraform@v0.7.8-0.20161029001309-18b3736ba44b/builtin/providers/scaleway/resource_scaleway_volume_attachment.go (about)

     1  package scaleway
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  
     7  	"github.com/hashicorp/terraform/helper/schema"
     8  	"github.com/scaleway/scaleway-cli/pkg/api"
     9  )
    10  
    11  func resourceScalewayVolumeAttachment() *schema.Resource {
    12  	return &schema.Resource{
    13  		Create: resourceScalewayVolumeAttachmentCreate,
    14  		Read:   resourceScalewayVolumeAttachmentRead,
    15  		Delete: resourceScalewayVolumeAttachmentDelete,
    16  		Schema: map[string]*schema.Schema{
    17  			"server": &schema.Schema{
    18  				Type:     schema.TypeString,
    19  				Required: true,
    20  				ForceNew: true,
    21  			},
    22  			"volume": &schema.Schema{
    23  				Type:     schema.TypeString,
    24  				Required: true,
    25  				ForceNew: true,
    26  			},
    27  		},
    28  	}
    29  }
    30  
    31  func resourceScalewayVolumeAttachmentCreate(d *schema.ResourceData, m interface{}) error {
    32  	scaleway := m.(*Client).scaleway
    33  
    34  	var startServerAgain = false
    35  
    36  	// guard against server shutdown/ startup race conditiond
    37  	serverID := d.Get("server").(string)
    38  	scalewayMutexKV.Lock(serverID)
    39  	defer scalewayMutexKV.Unlock(serverID)
    40  
    41  	server, err := scaleway.GetServer(serverID)
    42  	if err != nil {
    43  		fmt.Printf("Failed getting server: %q", err)
    44  		return err
    45  	}
    46  
    47  	// volumes can only be modified when the server is powered off
    48  	if server.State != "stopped" {
    49  		startServerAgain = true
    50  
    51  		if err := scaleway.PostServerAction(server.Identifier, "poweroff"); err != nil {
    52  			return err
    53  		}
    54  	}
    55  	if err := waitForServerState(scaleway, server.Identifier, "stopped"); err != nil {
    56  		return err
    57  	}
    58  
    59  	volumes := make(map[string]api.ScalewayVolume)
    60  	for i, volume := range server.Volumes {
    61  		volumes[i] = volume
    62  	}
    63  
    64  	vol, err := scaleway.GetVolume(d.Get("volume").(string))
    65  	if err != nil {
    66  		return err
    67  	}
    68  	volumes[fmt.Sprintf("%d", len(volumes)+1)] = *vol
    69  
    70  	// the API request requires most volume attributes to be unset to succeed
    71  	for k, v := range volumes {
    72  		v.Size = 0
    73  		v.CreationDate = ""
    74  		v.Organization = ""
    75  		v.ModificationDate = ""
    76  		v.VolumeType = ""
    77  		v.Server = nil
    78  		v.ExportURI = ""
    79  
    80  		volumes[k] = v
    81  	}
    82  
    83  	var req = api.ScalewayServerPatchDefinition{
    84  		Volumes: &volumes,
    85  	}
    86  	if err := scaleway.PatchServer(serverID, req); err != nil {
    87  		return fmt.Errorf("Failed attaching volume to server: %q", err)
    88  	}
    89  
    90  	if startServerAgain {
    91  		if err := scaleway.PostServerAction(serverID, "poweron"); err != nil {
    92  			return err
    93  		}
    94  		if err := waitForServerState(scaleway, serverID, "running"); err != nil {
    95  			return err
    96  		}
    97  	}
    98  
    99  	d.SetId(fmt.Sprintf("scaleway-server:%s/volume/%s", serverID, d.Get("volume").(string)))
   100  
   101  	return resourceScalewayVolumeAttachmentRead(d, m)
   102  }
   103  
   104  func resourceScalewayVolumeAttachmentRead(d *schema.ResourceData, m interface{}) error {
   105  	scaleway := m.(*Client).scaleway
   106  
   107  	server, err := scaleway.GetServer(d.Get("server").(string))
   108  	if err != nil {
   109  		if serr, ok := err.(api.ScalewayAPIError); ok {
   110  			log.Printf("[DEBUG] Error reading server: %q\n", serr.APIMessage)
   111  
   112  			if serr.StatusCode == 404 {
   113  				d.SetId("")
   114  				return nil
   115  			}
   116  		}
   117  		return err
   118  	}
   119  
   120  	if _, err := scaleway.GetVolume(d.Get("volume").(string)); err != nil {
   121  		if serr, ok := err.(api.ScalewayAPIError); ok {
   122  			log.Printf("[DEBUG] Error reading volume: %q\n", serr.APIMessage)
   123  
   124  			if serr.StatusCode == 404 {
   125  				d.SetId("")
   126  				return nil
   127  			}
   128  		}
   129  		return err
   130  	}
   131  
   132  	for _, volume := range server.Volumes {
   133  		if volume.Identifier == d.Get("volume").(string) {
   134  			return nil
   135  		}
   136  	}
   137  
   138  	log.Printf("[DEBUG] Volume %q not attached to server %q\n", d.Get("volume").(string), d.Get("server").(string))
   139  	d.SetId("")
   140  	return nil
   141  }
   142  
   143  func resourceScalewayVolumeAttachmentDelete(d *schema.ResourceData, m interface{}) error {
   144  	scaleway := m.(*Client).scaleway
   145  	var startServerAgain = false
   146  
   147  	// guard against server shutdown/ startup race conditiond
   148  	serverID := d.Get("server").(string)
   149  	scalewayMutexKV.Lock(serverID)
   150  	defer scalewayMutexKV.Unlock(serverID)
   151  
   152  	server, err := scaleway.GetServer(serverID)
   153  	if err != nil {
   154  		return err
   155  	}
   156  
   157  	// volumes can only be modified when the server is powered off
   158  	if server.State != "stopped" {
   159  		startServerAgain = true
   160  		if err := scaleway.PostServerAction(server.Identifier, "poweroff"); err != nil {
   161  			return err
   162  		}
   163  	}
   164  	if err := waitForServerState(scaleway, server.Identifier, "stopped"); err != nil {
   165  		return err
   166  	}
   167  
   168  	volumes := make(map[string]api.ScalewayVolume)
   169  	for _, volume := range server.Volumes {
   170  		if volume.Identifier != d.Get("volume").(string) {
   171  			volumes[fmt.Sprintf("%d", len(volumes))] = volume
   172  		}
   173  	}
   174  
   175  	// the API request requires most volume attributes to be unset to succeed
   176  	for k, v := range volumes {
   177  		v.Size = 0
   178  		v.CreationDate = ""
   179  		v.Organization = ""
   180  		v.ModificationDate = ""
   181  		v.VolumeType = ""
   182  		v.Server = nil
   183  		v.ExportURI = ""
   184  
   185  		volumes[k] = v
   186  	}
   187  
   188  	var req = api.ScalewayServerPatchDefinition{
   189  		Volumes: &volumes,
   190  	}
   191  	if err := scaleway.PatchServer(serverID, req); err != nil {
   192  		return err
   193  	}
   194  
   195  	if startServerAgain {
   196  		if err := scaleway.PostServerAction(serverID, "poweron"); err != nil {
   197  			return err
   198  		}
   199  		if err := waitForServerState(scaleway, serverID, "running"); err != nil {
   200  			return err
   201  		}
   202  	}
   203  
   204  	d.SetId("")
   205  
   206  	return nil
   207  }