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 }