Skip to content

Commit 97de49e

Browse files
committed
Add support for snapshot policies
1 parent afa7a18 commit 97de49e

4 files changed

Lines changed: 723 additions & 0 deletions

File tree

cloudstack/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ func Provider() *schema.Provider {
147147
"cloudstack_domain": resourceCloudStackDomain(),
148148
"cloudstack_network_service_provider": resourceCloudStackNetworkServiceProvider(),
149149
"cloudstack_role": resourceCloudStackRole(),
150+
"cloudstack_snapshot_policy": resourceCloudStackSnapshotPolicy(),
150151
},
151152

152153
ConfigureFunc: providerConfigure,
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
//
2+
// Licensed to the Apache Software Foundation (ASF) under one
3+
// or more contributor license agreements. See the NOTICE file
4+
// distributed with this work for additional information
5+
// regarding copyright ownership. The ASF licenses this file
6+
// to you under the Apache License, Version 2.0 (the
7+
// "License"); you may not use this file except in compliance
8+
// with the License. You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing,
13+
// software distributed under the License is distributed on an
14+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
// KIND, either express or implied. See the License for the
16+
// specific language governing permissions and limitations
17+
// under the License.
18+
//
19+
20+
package cloudstack
21+
22+
import (
23+
"fmt"
24+
"log"
25+
26+
"github.com/apache/cloudstack-go/v2/cloudstack"
27+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
28+
)
29+
30+
func resourceCloudStackSnapshotPolicy() *schema.Resource {
31+
return &schema.Resource{
32+
Create: resourceCloudstackSnapshotPolicyCreate,
33+
Read: resourceCloudstackSnapshotPolicyRead,
34+
Update: resourceCloudstackSnapshotPolicyUpdate,
35+
Delete: resourceCloudstackSnapshotPolicyDelete,
36+
37+
Schema: map[string]*schema.Schema{
38+
"volume_id": {
39+
Type: schema.TypeString,
40+
Required: true,
41+
},
42+
"interval_type": {
43+
Type: schema.TypeString,
44+
Required: true,
45+
},
46+
"max_snaps": {
47+
Type: schema.TypeInt,
48+
Required: true,
49+
},
50+
"schedule": {
51+
Type: schema.TypeString,
52+
Required: true,
53+
},
54+
"timezone": {
55+
Type: schema.TypeString,
56+
Required: true,
57+
},
58+
"zone_ids": {
59+
Type: schema.TypeList,
60+
Optional: true,
61+
Elem: &schema.Schema{
62+
Type: schema.TypeString,
63+
},
64+
},
65+
"custom_id": {
66+
Type: schema.TypeString,
67+
Optional: true,
68+
ForceNew: true,
69+
},
70+
"tags": tagsSchema(),
71+
},
72+
}
73+
}
74+
75+
func resourceCloudstackSnapshotPolicyCreate(d *schema.ResourceData, meta interface{}) error {
76+
cs := meta.(*cloudstack.CloudStackClient)
77+
78+
p := cs.Snapshot.NewCreateSnapshotPolicyParams(
79+
d.Get("interval_type").(string),
80+
d.Get("max_snaps").(int),
81+
d.Get("schedule").(string),
82+
d.Get("timezone").(string),
83+
d.Get("volume_id").(string),
84+
)
85+
86+
if v, ok := d.GetOk("zone_ids"); ok && v != nil {
87+
zoneIDs := []string{}
88+
for _, id := range v.([]interface{}) {
89+
zoneIDs = append(zoneIDs, id.(string))
90+
}
91+
p.SetZoneids(zoneIDs)
92+
}
93+
94+
snapshotPolicy, err := cs.Snapshot.CreateSnapshotPolicy(p)
95+
if err != nil {
96+
return fmt.Errorf("Error creating snapshot policy: %s", err)
97+
}
98+
99+
log.Printf("[DEBUG] CreateSnapshotPolicy response: %+v", snapshotPolicy)
100+
101+
if snapshotPolicy.Id == "" {
102+
log.Printf("[DEBUG] CloudStack returned empty ID, trying to find created policy by volume ID")
103+
104+
listParams := cs.Snapshot.NewListSnapshotPoliciesParams()
105+
listParams.SetVolumeid(d.Get("volume_id").(string))
106+
107+
resp, listErr := cs.Snapshot.ListSnapshotPolicies(listParams)
108+
if listErr != nil {
109+
return fmt.Errorf("Error listing snapshot policies to find created policy: %s", listErr)
110+
}
111+
112+
if resp.Count == 0 {
113+
return fmt.Errorf("No snapshot policies found for volume after creation")
114+
}
115+
116+
foundPolicy := resp.SnapshotPolicies[resp.Count-1]
117+
log.Printf("[DEBUG] Found policy with ID: %s", foundPolicy.Id)
118+
d.SetId(foundPolicy.Id)
119+
} else {
120+
d.SetId(snapshotPolicy.Id)
121+
}
122+
123+
log.Printf("[DEBUG] Snapshot policy created with ID: %s", d.Id())
124+
125+
return resourceCloudstackSnapshotPolicyRead(d, meta)
126+
}
127+
128+
func resourceCloudstackSnapshotPolicyRead(d *schema.ResourceData, meta interface{}) error {
129+
cs := meta.(*cloudstack.CloudStackClient)
130+
131+
if d.Id() == "" {
132+
log.Printf("[DEBUG] Snapshot policy ID is empty")
133+
return fmt.Errorf("Snapshot policy ID is empty")
134+
}
135+
136+
p := cs.Snapshot.NewListSnapshotPoliciesParams()
137+
p.SetId(d.Id())
138+
139+
resp, err := cs.Snapshot.ListSnapshotPolicies(p)
140+
if err != nil {
141+
return fmt.Errorf("Failed to list snapshot policies: %s", err)
142+
}
143+
144+
if resp.Count == 0 {
145+
log.Printf("[DEBUG] Snapshot policy %s not found, removing from state", d.Id())
146+
d.SetId("")
147+
return nil
148+
}
149+
150+
snapshotPolicy := resp.SnapshotPolicies[0]
151+
152+
d.Set("volume_id", snapshotPolicy.Volumeid)
153+
d.Set("interval_type", snapshotPolicy.Intervaltype)
154+
d.Set("max_snaps", snapshotPolicy.Maxsnaps)
155+
d.Set("schedule", snapshotPolicy.Schedule)
156+
d.Set("timezone", snapshotPolicy.Timezone)
157+
158+
if snapshotPolicy.Zone != nil {
159+
zoneIDs := []string{}
160+
for _, zone := range snapshotPolicy.Zone {
161+
if zoneMap, ok := zone.(map[string]interface{}); ok {
162+
if id, ok := zoneMap["id"].(string); ok {
163+
zoneIDs = append(zoneIDs, id)
164+
}
165+
}
166+
}
167+
d.Set("zone_ids", zoneIDs)
168+
} else {
169+
d.Set("zone_ids", nil)
170+
}
171+
172+
return nil
173+
}
174+
175+
func resourceCloudstackSnapshotPolicyUpdate(d *schema.ResourceData, meta interface{}) error {
176+
cs := meta.(*cloudstack.CloudStackClient)
177+
178+
p := cs.Snapshot.NewUpdateSnapshotPolicyParams()
179+
p.SetId(d.Id())
180+
if v, ok := d.GetOk("custom_id"); ok {
181+
p.SetCustomid(v.(string))
182+
}
183+
184+
_, err := cs.Snapshot.UpdateSnapshotPolicy(p)
185+
return err
186+
}
187+
188+
func resourceCloudstackSnapshotPolicyDelete(d *schema.ResourceData, meta interface{}) error {
189+
cs := meta.(*cloudstack.CloudStackClient)
190+
191+
p := cs.Snapshot.NewDeleteSnapshotPoliciesParams()
192+
p.SetId(d.Id())
193+
194+
_, err := cs.Snapshot.DeleteSnapshotPolicies(p)
195+
if err != nil {
196+
return fmt.Errorf("Failed to delete snapshot policy %s: %s", d.Id(), err)
197+
}
198+
199+
d.SetId("")
200+
201+
return nil
202+
}

0 commit comments

Comments
 (0)