github.com/nicgrayson/terraform@v0.4.3-0.20150415203910-c4de50829380/builtin/providers/cloudstack/resource_cloudstack_template.go (about) 1 package cloudstack 2 3 import ( 4 "fmt" 5 "log" 6 "strings" 7 "time" 8 9 "github.com/hashicorp/terraform/helper/schema" 10 "github.com/xanzy/go-cloudstack/cloudstack" 11 ) 12 13 func resourceCloudStackTemplate() *schema.Resource { 14 return &schema.Resource{ 15 Create: resourceCloudStackTemplateCreate, 16 Read: resourceCloudStackTemplateRead, 17 Update: resourceCloudStackTemplateUpdate, 18 Delete: resourceCloudStackTemplateDelete, 19 20 Schema: map[string]*schema.Schema{ 21 "name": &schema.Schema{ 22 Type: schema.TypeString, 23 Required: true, 24 }, 25 26 "display_text": &schema.Schema{ 27 Type: schema.TypeString, 28 Optional: true, 29 Computed: true, 30 }, 31 32 "format": &schema.Schema{ 33 Type: schema.TypeString, 34 Required: true, 35 }, 36 37 "hypervisor": &schema.Schema{ 38 Type: schema.TypeString, 39 Required: true, 40 ForceNew: true, 41 }, 42 43 "os_type": &schema.Schema{ 44 Type: schema.TypeString, 45 Required: true, 46 }, 47 48 "url": &schema.Schema{ 49 Type: schema.TypeString, 50 Required: true, 51 ForceNew: true, 52 }, 53 54 "zone": &schema.Schema{ 55 Type: schema.TypeString, 56 Required: true, 57 ForceNew: true, 58 }, 59 60 "is_dynamically_scalable": &schema.Schema{ 61 Type: schema.TypeBool, 62 Optional: true, 63 Computed: true, 64 }, 65 66 "is_extractable": &schema.Schema{ 67 Type: schema.TypeBool, 68 Optional: true, 69 Computed: true, 70 ForceNew: true, 71 }, 72 73 "is_featured": &schema.Schema{ 74 Type: schema.TypeBool, 75 Optional: true, 76 Computed: true, 77 ForceNew: true, 78 }, 79 80 "is_public": &schema.Schema{ 81 Type: schema.TypeBool, 82 Optional: true, 83 Computed: true, 84 }, 85 86 "password_enabled": &schema.Schema{ 87 Type: schema.TypeBool, 88 Optional: true, 89 Computed: true, 90 }, 91 92 "is_ready": &schema.Schema{ 93 Type: schema.TypeBool, 94 Computed: true, 95 }, 96 97 "is_ready_timeout": &schema.Schema{ 98 Type: schema.TypeInt, 99 Optional: true, 100 Default: 300, 101 }, 102 }, 103 } 104 } 105 106 func resourceCloudStackTemplateCreate(d *schema.ResourceData, meta interface{}) error { 107 cs := meta.(*cloudstack.CloudStackClient) 108 109 name := d.Get("name").(string) 110 111 // Compute/set the display text 112 displaytext := d.Get("display_text").(string) 113 if displaytext == "" { 114 displaytext = name 115 } 116 117 // Retrieve the os_type UUID 118 ostypeid, e := retrieveUUID(cs, "os_type", d.Get("os_type").(string)) 119 if e != nil { 120 return e.Error() 121 } 122 123 // Retrieve the zone UUID 124 zoneid, e := retrieveUUID(cs, "zone", d.Get("zone").(string)) 125 if e != nil { 126 return e.Error() 127 } 128 129 // Create a new parameter struct 130 p := cs.Template.NewRegisterTemplateParams( 131 displaytext, 132 d.Get("format").(string), 133 d.Get("hypervisor").(string), 134 name, 135 ostypeid, 136 d.Get("url").(string), 137 zoneid) 138 139 // Set optional parameters 140 if v, ok := d.GetOk("is_dynamically_scalable"); ok { 141 p.SetIsdynamicallyscalable(v.(bool)) 142 } 143 144 if v, ok := d.GetOk("is_extractable"); ok { 145 p.SetIsextractable(v.(bool)) 146 } 147 148 if v, ok := d.GetOk("is_featured"); ok { 149 p.SetIsfeatured(v.(bool)) 150 } 151 152 if v, ok := d.GetOk("is_public"); ok { 153 p.SetIspublic(v.(bool)) 154 } 155 156 if v, ok := d.GetOk("password_enabled"); ok { 157 p.SetPasswordenabled(v.(bool)) 158 } 159 160 // Create the new template 161 r, err := cs.Template.RegisterTemplate(p) 162 if err != nil { 163 return fmt.Errorf("Error creating template %s: %s", name, err) 164 } 165 166 d.SetId(r.RegisterTemplate[0].Id) 167 168 // Wait until the template is ready to use, or timeout with an error... 169 currentTime := time.Now().Unix() 170 timeout := int64(d.Get("is_ready_timeout").(int)) 171 for { 172 err := resourceCloudStackTemplateRead(d, meta) 173 if err != nil { 174 return err 175 } 176 177 if d.Get("is_ready").(bool) { 178 return nil 179 } 180 181 if time.Now().Unix()-currentTime > timeout { 182 return fmt.Errorf("Timeout while waiting for template to become ready") 183 } 184 time.Sleep(5 * time.Second) 185 } 186 } 187 188 func resourceCloudStackTemplateRead(d *schema.ResourceData, meta interface{}) error { 189 cs := meta.(*cloudstack.CloudStackClient) 190 191 // Get the template details 192 t, count, err := cs.Template.GetTemplateByID(d.Id(), "executable") 193 if err != nil { 194 if count == 0 { 195 log.Printf( 196 "[DEBUG] Template %s no longer exists", d.Get("name").(string)) 197 d.SetId("") 198 return nil 199 } 200 201 return err 202 } 203 204 d.Set("name", t.Name) 205 d.Set("display_text", t.Displaytext) 206 d.Set("format", t.Format) 207 d.Set("hypervisor", t.Hypervisor) 208 d.Set("os_type", t.Ostypename) 209 d.Set("zone", t.Zonename) 210 d.Set("is_dynamically_scalable", t.Isdynamicallyscalable) 211 d.Set("is_extractable", t.Isextractable) 212 d.Set("is_featured", t.Isfeatured) 213 d.Set("is_public", t.Ispublic) 214 d.Set("password_enabled", t.Passwordenabled) 215 d.Set("is_ready", t.Isready) 216 217 return nil 218 } 219 220 func resourceCloudStackTemplateUpdate(d *schema.ResourceData, meta interface{}) error { 221 cs := meta.(*cloudstack.CloudStackClient) 222 name := d.Get("name").(string) 223 224 // Create a new parameter struct 225 p := cs.Template.NewUpdateTemplateParams(d.Id()) 226 227 if d.HasChange("name") { 228 p.SetName(name) 229 } 230 231 if d.HasChange("display_text") { 232 p.SetDisplaytext(d.Get("display_text").(string)) 233 } 234 235 if d.HasChange("format") { 236 p.SetFormat(d.Get("format").(string)) 237 } 238 239 if d.HasChange("is_dynamically_scalable") { 240 p.SetIsdynamicallyscalable(d.Get("is_dynamically_scalable").(bool)) 241 } 242 243 if d.HasChange("os_type") { 244 ostypeid, e := retrieveUUID(cs, "os_type", d.Get("os_type").(string)) 245 if e != nil { 246 return e.Error() 247 } 248 p.SetOstypeid(ostypeid) 249 } 250 251 if d.HasChange("password_enabled") { 252 p.SetPasswordenabled(d.Get("password_enabled").(bool)) 253 } 254 255 _, err := cs.Template.UpdateTemplate(p) 256 if err != nil { 257 return fmt.Errorf("Error updating template %s: %s", name, err) 258 } 259 260 return resourceCloudStackTemplateRead(d, meta) 261 } 262 263 func resourceCloudStackTemplateDelete(d *schema.ResourceData, meta interface{}) error { 264 cs := meta.(*cloudstack.CloudStackClient) 265 266 // Create a new parameter struct 267 p := cs.Template.NewDeleteTemplateParams(d.Id()) 268 269 // Delete the template 270 log.Printf("[INFO] Deleting template: %s", d.Get("name").(string)) 271 _, err := cs.Template.DeleteTemplate(p) 272 if err != nil { 273 // This is a very poor way to be told the UUID does no longer exist :( 274 if strings.Contains(err.Error(), fmt.Sprintf( 275 "Invalid parameter id value=%s due to incorrect long value format, "+ 276 "or entity does not exist", d.Id())) { 277 return nil 278 } 279 280 return fmt.Errorf("Error deleting template %s: %s", d.Get("name").(string), err) 281 } 282 return nil 283 }