blob: fc971fd02d4932a3d5bf230ddd33f6db07e01f84 [file] [log] [blame]
Jamie Hannaford9fdda582015-02-10 12:15:43 +01001package instances
2
3import (
4 "fmt"
5
Jamie Hannaford9fdda582015-02-10 12:15:43 +01006 "github.com/rackspace/gophercloud"
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +01007 db "github.com/rackspace/gophercloud/openstack/db/v1/databases"
Jamie Hannaford3aba0b12015-02-13 14:33:39 +01008 "github.com/rackspace/gophercloud/openstack/db/v1/users"
Jamie Hannaford90684242015-02-10 12:46:07 +01009 "github.com/rackspace/gophercloud/pagination"
Jamie Hannaford9fdda582015-02-10 12:15:43 +010010)
11
12// CreateOptsBuilder is the top-level interface for create options.
13type CreateOptsBuilder interface {
14 ToInstanceCreateMap() (map[string]interface{}, error)
15}
16
Jamie Hannaford9fdda582015-02-10 12:15:43 +010017// CreateOpts is the struct responsible for configuring a new database instance.
18type CreateOpts struct {
19 // Either the integer UUID (in string form) of the flavor, or its URI
20 // reference as specified in the response from the List() call. Required.
21 FlavorRef string
22
23 // Specifies the volume size in gigabytes (GB). The value must be between 1
24 // and 300. Required.
25 Size int
26
27 // Name of the instance to create. The length of the name is limited to
28 // 255 characters and any characters are permitted. Optional.
29 Name string
30
31 // A slice of database information options.
Jamie Hannaford85f10332015-02-12 11:51:37 +010032 Databases db.BatchCreateOpts
Jamie Hannaford9fdda582015-02-10 12:15:43 +010033
34 // A slice of user information options.
Jamie Hannaford2ca55d82015-02-12 14:21:55 +010035 Users users.BatchCreateOpts
Jamie Hannaford9fdda582015-02-10 12:15:43 +010036}
37
38func (opts CreateOpts) ToInstanceCreateMap() (map[string]interface{}, error) {
39 if opts.Size > 300 || opts.Size < 1 {
40 return nil, fmt.Errorf("Size (GB) must be between 1-300")
41 }
42 if opts.FlavorRef == "" {
43 return nil, fmt.Errorf("FlavorRef is a required field")
44 }
45
46 instance := map[string]interface{}{
47 "volume": map[string]int{"size": opts.Size},
48 "flavorRef": opts.FlavorRef,
49 }
50
51 if opts.Name != "" {
52 instance["name"] = opts.Name
53 }
54 if len(opts.Databases) > 0 {
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +010055 dbs, err := opts.Databases.ToDBCreateMap()
Jamie Hannaford9fdda582015-02-10 12:15:43 +010056 if err != nil {
57 return nil, err
58 }
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +010059 instance["databases"] = dbs["databases"]
Jamie Hannaford9fdda582015-02-10 12:15:43 +010060 }
61 if len(opts.Users) > 0 {
Jamie Hannaford2ca55d82015-02-12 14:21:55 +010062 users, err := opts.Users.ToUserCreateMap()
Jamie Hannaford9fdda582015-02-10 12:15:43 +010063 if err != nil {
64 return nil, err
65 }
Jamie Hannaford2ca55d82015-02-12 14:21:55 +010066 instance["users"] = users["users"]
Jamie Hannaford9fdda582015-02-10 12:15:43 +010067 }
68
69 return map[string]interface{}{"instance": instance}, nil
70}
71
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +010072// Create asynchronously provisions a new database instance. It requires the
73// user to specify a flavor and a volume size. The API service then provisions
74// the instance with the requested flavor and sets up a volume of the specified
75// size, which is the storage for the database instance.
76//
77// Although this call only allows the creation of 1 instance per request, you
78// can create an instance with multiple databases and users. The default
79// binding for a MySQL instance is port 3306.
Jamie Hannaford9fdda582015-02-10 12:15:43 +010080func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
81 var res CreateResult
82
83 reqBody, err := opts.ToInstanceCreateMap()
84 if err != nil {
85 res.Err = err
86 return res
87 }
88
Jamie Hannaforda50d1352015-02-18 11:38:38 +010089 _, res.Err = client.Request("POST", baseURL(client), gophercloud.RequestOpts{
90 JSONBody: &reqBody,
91 JSONResponse: &res.Body,
92 OkCodes: []int{200},
Jamie Hannaford9fdda582015-02-10 12:15:43 +010093 })
94
Jamie Hannaford9fdda582015-02-10 12:15:43 +010095 return res
96}
Jamie Hannaford90684242015-02-10 12:46:07 +010097
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +010098// List retrieves the status and information for all database instances.
Jamie Hannaford90684242015-02-10 12:46:07 +010099func List(client *gophercloud.ServiceClient) pagination.Pager {
100 createPageFn := func(r pagination.PageResult) pagination.Page {
101 return InstancePage{pagination.LinkedPageBase{PageResult: r}}
102 }
103
104 return pagination.NewPager(client, baseURL(client), createPageFn)
105}
Jamie Hannaford821015f2015-02-10 12:58:36 +0100106
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100107// Get retrieves the status and information for a specified database instance.
Jamie Hannaford821015f2015-02-10 12:58:36 +0100108func Get(client *gophercloud.ServiceClient, id string) GetResult {
109 var res GetResult
110
Jamie Hannaforda50d1352015-02-18 11:38:38 +0100111 _, res.Err = client.Request("GET", resourceURL(client, id), gophercloud.RequestOpts{
112 JSONResponse: &res.Body,
113 OkCodes: []int{200},
Jamie Hannaford821015f2015-02-10 12:58:36 +0100114 })
115
Jamie Hannaford821015f2015-02-10 12:58:36 +0100116 return res
117}
Jamie Hannaford5b16b632015-02-10 13:36:23 +0100118
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100119// Delete permanently destroys the database instance.
Jamie Hannaford5b16b632015-02-10 13:36:23 +0100120func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
121 var res DeleteResult
122
Jamie Hannaforda50d1352015-02-18 11:38:38 +0100123 _, res.Err = client.Request("DELETE", resourceURL(client, id), gophercloud.RequestOpts{
124 OkCodes: []int{202},
Jamie Hannaford5b16b632015-02-10 13:36:23 +0100125 })
126
Jamie Hannaford5b16b632015-02-10 13:36:23 +0100127 return res
128}
Jamie Hannaford94164fa2015-02-10 13:58:45 +0100129
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100130// EnableRootUser enables the login from any host for the root user and
131// provides the user with a generated root password.
Jamie Hannaford94164fa2015-02-10 13:58:45 +0100132func EnableRootUser(client *gophercloud.ServiceClient, id string) UserRootResult {
133 var res UserRootResult
134
Jamie Hannaforda50d1352015-02-18 11:38:38 +0100135 _, res.Err = client.Request("POST", userRootURL(client, id), gophercloud.RequestOpts{
136 JSONResponse: &res.Body,
137 OkCodes: []int{200},
Jamie Hannaford94164fa2015-02-10 13:58:45 +0100138 })
139
Jamie Hannaford94164fa2015-02-10 13:58:45 +0100140 return res
141}
Jamie Hannaforda74d4252015-02-10 15:35:01 +0100142
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100143// IsRootEnabled checks an instance to see if root access is enabled. It returns
144// True if root user is enabled for the specified database instance or False
145// otherwise.
Jamie Hannaforda74d4252015-02-10 15:35:01 +0100146func IsRootEnabled(client *gophercloud.ServiceClient, id string) (bool, error) {
147 var res gophercloud.Result
148
Jamie Hannaforda50d1352015-02-18 11:38:38 +0100149 _, err := client.Request("GET", userRootURL(client, id), gophercloud.RequestOpts{
150 JSONResponse: &res.Body,
151 OkCodes: []int{200},
Jamie Hannaforda74d4252015-02-10 15:35:01 +0100152 })
153
154 return res.Body.(map[string]interface{})["rootEnabled"] == true, err
155}
Jamie Hannaford219ca592015-02-10 15:59:05 +0100156
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100157// RestartService will restart only the MySQL Instance. Restarting MySQL will
158// erase any dynamic configuration settings that you have made within MySQL.
159// The MySQL service will be unavailable until the instance restarts.
Jamie Hannaford219ca592015-02-10 15:59:05 +0100160func RestartService(client *gophercloud.ServiceClient, id string) ActionResult {
161 var res ActionResult
162
Jamie Hannaforda50d1352015-02-18 11:38:38 +0100163 _, res.Err = client.Request("POST", actionURL(client, id), gophercloud.RequestOpts{
164 JSONBody: map[string]bool{"restart": true},
165 OkCodes: []int{202},
Jamie Hannaford219ca592015-02-10 15:59:05 +0100166 })
167
Jamie Hannaford219ca592015-02-10 15:59:05 +0100168 return res
169}
170
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100171// ResizeInstance changes the memory size of the instance, assuming a valid
172// flavorRef is provided. It will also restart the MySQL service.
Jamie Hannaford219ca592015-02-10 15:59:05 +0100173func ResizeInstance(client *gophercloud.ServiceClient, id, flavorRef string) ActionResult {
174 var res ActionResult
175
176 reqBody := map[string]map[string]string{
177 "resize": map[string]string{
178 "flavorRef": flavorRef,
179 },
180 }
181
Jamie Hannaforda50d1352015-02-18 11:38:38 +0100182 _, res.Err = client.Request("POST", actionURL(client, id), gophercloud.RequestOpts{
183 JSONBody: reqBody,
184 OkCodes: []int{202},
Jamie Hannaford219ca592015-02-10 15:59:05 +0100185 })
186
Jamie Hannaford219ca592015-02-10 15:59:05 +0100187 return res
188}
189
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100190// ResizeVolume will resize the attached volume for an instance. It supports
191// only increasing the volume size and does not support decreasing the size.
192// The volume size is in gigabytes (GB) and must be an integer.
Jamie Hannaford219ca592015-02-10 15:59:05 +0100193func ResizeVolume(client *gophercloud.ServiceClient, id string, size int) ActionResult {
194 var res ActionResult
195
196 reqBody := map[string]map[string]map[string]int{
197 "resize": map[string]map[string]int{
198 "volume": map[string]int{"size": size},
199 },
200 }
201
Jamie Hannaforda50d1352015-02-18 11:38:38 +0100202 _, res.Err = client.Request("POST", actionURL(client, id), gophercloud.RequestOpts{
203 JSONBody: reqBody,
204 OkCodes: []int{202},
Jamie Hannaford219ca592015-02-10 15:59:05 +0100205 })
206
Jamie Hannaford219ca592015-02-10 15:59:05 +0100207 return res
208}