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