blob: 8e33dfe4755aa309be513ecde585a38f5901dd2b [file] [log] [blame]
Jamie Hannaford9fdda582015-02-10 12:15:43 +01001package instances
2
3import (
Jon Perritt27249f42016-02-18 10:35:59 -06004 "github.com/gophercloud/gophercloud"
5 db "github.com/gophercloud/gophercloud/openstack/db/v1/databases"
6 "github.com/gophercloud/gophercloud/openstack/db/v1/users"
7 "github.com/gophercloud/gophercloud/pagination"
Jamie Hannaford9fdda582015-02-10 12:15:43 +01008)
9
10// CreateOptsBuilder is the top-level interface for create options.
11type CreateOptsBuilder interface {
12 ToInstanceCreateMap() (map[string]interface{}, error)
13}
14
Jamie Hannaford99eced52015-03-02 15:24:22 +010015// DatastoreOpts represents the configuration for how an instance stores data.
16type DatastoreOpts struct {
17 Version string
18 Type string
19}
20
Jon Perritt763e5922016-03-07 03:21:18 -060021// ToMap converts a DatastoreOpts to a map[string]string (for a request body)
Jamie Hannaford99eced52015-03-02 15:24:22 +010022func (opts DatastoreOpts) ToMap() (map[string]string, error) {
23 return map[string]string{
24 "version": opts.Version,
25 "type": opts.Type,
26 }, nil
27}
28
Jamie Hannaford9fdda582015-02-10 12:15:43 +010029// CreateOpts is the struct responsible for configuring a new database instance.
30type CreateOpts struct {
31 // Either the integer UUID (in string form) of the flavor, or its URI
32 // reference as specified in the response from the List() call. Required.
33 FlavorRef string
34
35 // Specifies the volume size in gigabytes (GB). The value must be between 1
36 // and 300. Required.
37 Size int
38
39 // Name of the instance to create. The length of the name is limited to
40 // 255 characters and any characters are permitted. Optional.
41 Name string
42
43 // A slice of database information options.
Jamie Hannaford2e695a32015-11-16 16:36:10 +010044 Databases db.CreateOptsBuilder
Jamie Hannaford9fdda582015-02-10 12:15:43 +010045
46 // A slice of user information options.
Jamie Hannaford2e695a32015-11-16 16:36:10 +010047 Users users.CreateOptsBuilder
Jamie Hannaford99eced52015-03-02 15:24:22 +010048
49 // Options to configure the type of datastore the instance will use. This is
50 // optional, and if excluded will default to MySQL.
51 Datastore *DatastoreOpts
Jamie Hannaford9fdda582015-02-10 12:15:43 +010052}
53
Jamie Hannaford9793d942015-02-18 15:13:20 +010054// ToInstanceCreateMap will render a JSON map.
Jamie Hannaford9fdda582015-02-10 12:15:43 +010055func (opts CreateOpts) ToInstanceCreateMap() (map[string]interface{}, error) {
56 if opts.Size > 300 || opts.Size < 1 {
Jon Perritt763e5922016-03-07 03:21:18 -060057 err := gophercloud.ErrInvalidInput{}
58 err.Function = "instances.ToInstanceCreateMap"
59 err.Argument = "instances.CreateOpts.Size"
60 err.Value = opts.Size
61 err.Info = "Size (GB) must be between 1-300"
62 return nil, err
Jamie Hannaford9fdda582015-02-10 12:15:43 +010063 }
64 if opts.FlavorRef == "" {
Jon Perritt763e5922016-03-07 03:21:18 -060065 err := gophercloud.ErrMissingInput{}
66 err.Function = "instances.ToInstanceCreateMap"
67 err.Argument = "instances.CreateOpts.FlavorRef"
68 return nil, err
Jamie Hannaford9fdda582015-02-10 12:15:43 +010069 }
70
71 instance := map[string]interface{}{
72 "volume": map[string]int{"size": opts.Size},
73 "flavorRef": opts.FlavorRef,
74 }
75
76 if opts.Name != "" {
77 instance["name"] = opts.Name
78 }
Jamie Hannaford2e695a32015-11-16 16:36:10 +010079 if opts.Databases != nil {
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +010080 dbs, err := opts.Databases.ToDBCreateMap()
Jamie Hannaford9fdda582015-02-10 12:15:43 +010081 if err != nil {
82 return nil, err
83 }
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +010084 instance["databases"] = dbs["databases"]
Jamie Hannaford9fdda582015-02-10 12:15:43 +010085 }
Jamie Hannaford2e695a32015-11-16 16:36:10 +010086 if opts.Users != nil {
Jamie Hannaford2ca55d82015-02-12 14:21:55 +010087 users, err := opts.Users.ToUserCreateMap()
Jamie Hannaford9fdda582015-02-10 12:15:43 +010088 if err != nil {
89 return nil, err
90 }
Jamie Hannaford2ca55d82015-02-12 14:21:55 +010091 instance["users"] = users["users"]
Jamie Hannaford9fdda582015-02-10 12:15:43 +010092 }
Jon Perritt763e5922016-03-07 03:21:18 -060093 if opts.Datastore != nil {
94 datastore, err := opts.Datastore.ToMap()
95 if err != nil {
96 return nil, err
97 }
98 instance["datastore"] = datastore
99 }
Jamie Hannaford9fdda582015-02-10 12:15:43 +0100100
101 return map[string]interface{}{"instance": instance}, nil
102}
103
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100104// Create asynchronously provisions a new database instance. It requires the
105// user to specify a flavor and a volume size. The API service then provisions
106// the instance with the requested flavor and sets up a volume of the specified
107// size, which is the storage for the database instance.
108//
109// Although this call only allows the creation of 1 instance per request, you
110// can create an instance with multiple databases and users. The default
111// binding for a MySQL instance is port 3306.
Jamie Hannaford9fdda582015-02-10 12:15:43 +0100112func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
113 var res CreateResult
114
115 reqBody, err := opts.ToInstanceCreateMap()
116 if err != nil {
117 res.Err = err
118 return res
119 }
120
Jon Perritta33da232016-03-02 04:43:08 -0600121 _, res.Err = client.Request("POST", baseURL(client), &gophercloud.RequestOpts{
Jamie Hannaforda50d1352015-02-18 11:38:38 +0100122 JSONBody: &reqBody,
123 JSONResponse: &res.Body,
124 OkCodes: []int{200},
Jamie Hannaford9fdda582015-02-10 12:15:43 +0100125 })
126
Jamie Hannaford9fdda582015-02-10 12:15:43 +0100127 return res
128}
Jamie Hannaford90684242015-02-10 12:46:07 +0100129
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100130// List retrieves the status and information for all database instances.
Jamie Hannaford90684242015-02-10 12:46:07 +0100131func List(client *gophercloud.ServiceClient) pagination.Pager {
132 createPageFn := func(r pagination.PageResult) pagination.Page {
133 return InstancePage{pagination.LinkedPageBase{PageResult: r}}
134 }
135
136 return pagination.NewPager(client, baseURL(client), createPageFn)
137}
Jamie Hannaford821015f2015-02-10 12:58:36 +0100138
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100139// Get retrieves the status and information for a specified database instance.
Jamie Hannaford821015f2015-02-10 12:58:36 +0100140func Get(client *gophercloud.ServiceClient, id string) GetResult {
141 var res GetResult
142
Jon Perritta33da232016-03-02 04:43:08 -0600143 _, res.Err = client.Request("GET", resourceURL(client, id), &gophercloud.RequestOpts{
Jamie Hannaforda50d1352015-02-18 11:38:38 +0100144 JSONResponse: &res.Body,
145 OkCodes: []int{200},
Jamie Hannaford821015f2015-02-10 12:58:36 +0100146 })
147
Jamie Hannaford821015f2015-02-10 12:58:36 +0100148 return res
149}
Jamie Hannaford5b16b632015-02-10 13:36:23 +0100150
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100151// Delete permanently destroys the database instance.
Jamie Hannaford5b16b632015-02-10 13:36:23 +0100152func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
153 var res DeleteResult
154
Jon Perritta33da232016-03-02 04:43:08 -0600155 _, res.Err = client.Request("DELETE", resourceURL(client, id), &gophercloud.RequestOpts{
Jamie Hannaforda50d1352015-02-18 11:38:38 +0100156 OkCodes: []int{202},
Jamie Hannaford5b16b632015-02-10 13:36:23 +0100157 })
158
Jamie Hannaford5b16b632015-02-10 13:36:23 +0100159 return res
160}
Jamie Hannaford94164fa2015-02-10 13:58:45 +0100161
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100162// EnableRootUser enables the login from any host for the root user and
163// provides the user with a generated root password.
Jamie Hannaford94164fa2015-02-10 13:58:45 +0100164func EnableRootUser(client *gophercloud.ServiceClient, id string) UserRootResult {
165 var res UserRootResult
166
Jon Perritta33da232016-03-02 04:43:08 -0600167 _, res.Err = client.Request("POST", userRootURL(client, id), &gophercloud.RequestOpts{
Jamie Hannaforda50d1352015-02-18 11:38:38 +0100168 JSONResponse: &res.Body,
169 OkCodes: []int{200},
Jamie Hannaford94164fa2015-02-10 13:58:45 +0100170 })
171
Jamie Hannaford94164fa2015-02-10 13:58:45 +0100172 return res
173}
Jamie Hannaforda74d4252015-02-10 15:35:01 +0100174
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100175// IsRootEnabled checks an instance to see if root access is enabled. It returns
176// True if root user is enabled for the specified database instance or False
177// otherwise.
Jamie Hannaforda74d4252015-02-10 15:35:01 +0100178func IsRootEnabled(client *gophercloud.ServiceClient, id string) (bool, error) {
179 var res gophercloud.Result
180
Jon Perritta33da232016-03-02 04:43:08 -0600181 _, err := client.Request("GET", userRootURL(client, id), &gophercloud.RequestOpts{
Jamie Hannaforda50d1352015-02-18 11:38:38 +0100182 JSONResponse: &res.Body,
183 OkCodes: []int{200},
Jamie Hannaforda74d4252015-02-10 15:35:01 +0100184 })
185
186 return res.Body.(map[string]interface{})["rootEnabled"] == true, err
187}
Jamie Hannaford219ca592015-02-10 15:59:05 +0100188
Jamie Hannaford75e8cc42015-11-16 14:09:25 +0100189// Restart will restart only the MySQL Instance. Restarting MySQL will
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100190// erase any dynamic configuration settings that you have made within MySQL.
191// The MySQL service will be unavailable until the instance restarts.
Jamie Hannaford75e8cc42015-11-16 14:09:25 +0100192func Restart(client *gophercloud.ServiceClient, id string) ActionResult {
Jamie Hannaford219ca592015-02-10 15:59:05 +0100193 var res ActionResult
194
Jon Perritta33da232016-03-02 04:43:08 -0600195 _, res.Err = client.Request("POST", actionURL(client, id), &gophercloud.RequestOpts{
Jamie Hannafordd2b755f2015-10-07 14:01:57 +0200196 JSONBody: map[string]interface{}{"restart": struct{}{}},
Jamie Hannaforda50d1352015-02-18 11:38:38 +0100197 OkCodes: []int{202},
Jamie Hannaford219ca592015-02-10 15:59:05 +0100198 })
199
Jamie Hannaford219ca592015-02-10 15:59:05 +0100200 return res
201}
202
Jamie Hannaford75e8cc42015-11-16 14:09:25 +0100203// Resize changes the memory size of the instance, assuming a valid
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100204// flavorRef is provided. It will also restart the MySQL service.
Jamie Hannaford75e8cc42015-11-16 14:09:25 +0100205func Resize(client *gophercloud.ServiceClient, id, flavorRef string) ActionResult {
Jamie Hannaford219ca592015-02-10 15:59:05 +0100206 var res ActionResult
207
Jamie Hannaford7d51cf12015-02-25 14:50:06 +0100208 type resize struct {
209 FlavorRef string `json:"flavorRef"`
Jamie Hannaford219ca592015-02-10 15:59:05 +0100210 }
211
Jamie Hannaford7d51cf12015-02-25 14:50:06 +0100212 type req struct {
213 Resize resize `json:"resize"`
214 }
215
216 reqBody := req{Resize: resize{FlavorRef: flavorRef}}
217
Jon Perritta33da232016-03-02 04:43:08 -0600218 _, res.Err = client.Request("POST", actionURL(client, id), &gophercloud.RequestOpts{
Jamie Hannaforda50d1352015-02-18 11:38:38 +0100219 JSONBody: reqBody,
220 OkCodes: []int{202},
Jamie Hannaford219ca592015-02-10 15:59:05 +0100221 })
222
Jamie Hannaford219ca592015-02-10 15:59:05 +0100223 return res
224}
225
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100226// ResizeVolume will resize the attached volume for an instance. It supports
227// only increasing the volume size and does not support decreasing the size.
228// The volume size is in gigabytes (GB) and must be an integer.
Jamie Hannaford219ca592015-02-10 15:59:05 +0100229func ResizeVolume(client *gophercloud.ServiceClient, id string, size int) ActionResult {
230 var res ActionResult
231
Jamie Hannaford7d51cf12015-02-25 14:50:06 +0100232 type volume struct {
233 Size int `json:"size"`
Jamie Hannaford219ca592015-02-10 15:59:05 +0100234 }
235
Jamie Hannaford7d51cf12015-02-25 14:50:06 +0100236 type resize struct {
237 Volume volume `json:"volume"`
238 }
239
240 type req struct {
241 Resize resize `json:"resize"`
242 }
243
244 reqBody := req{Resize: resize{Volume: volume{Size: size}}}
245
Jon Perritta33da232016-03-02 04:43:08 -0600246 _, res.Err = client.Request("POST", actionURL(client, id), &gophercloud.RequestOpts{
Jamie Hannaforda50d1352015-02-18 11:38:38 +0100247 JSONBody: reqBody,
248 OkCodes: []int{202},
Jamie Hannaford219ca592015-02-10 15:59:05 +0100249 })
250
Jamie Hannaford219ca592015-02-10 15:59:05 +0100251 return res
252}