blob: f8afb7364d5c3d6ab60496a0ed600ea1f56e560e [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 {
Jon Perrittdb0ae142016-03-13 00:33:41 -060017 Version string `json:"version"`
18 Type string `json:"type"`
Jamie Hannaford99eced52015-03-02 15:24:22 +010019}
20
Jon Perritt763e5922016-03-07 03:21:18 -060021// ToMap converts a DatastoreOpts to a map[string]string (for a request body)
Jon Perrittdb0ae142016-03-13 00:33:41 -060022func (opts DatastoreOpts) ToMap() (map[string]interface{}, error) {
23 return gophercloud.BuildRequestBody(opts, "")
Jamie Hannaford99eced52015-03-02 15:24:22 +010024}
25
esalipe10a27442017-02-14 06:11:01 +020026// NetworkOpts is used within CreateOpts to control a new server's network attachments.
27type NetworkOpts struct {
28 // UUID of a nova-network to attach to the newly provisioned server.
29 // Required unless Port is provided.
30 UUID string `json:"net-id,omitempty"`
31
32 // Port of a neutron network to attach to the newly provisioned server.
33 // Required unless UUID is provided.
34 Port string `json:"port-id,omitempty"`
35
36 // V4FixedIP [optional] specifies a fixed IPv4 address to be used on this network.
37 V4FixedIP string `json:"v4-fixed-ip,omitempty"`
38
39 // V6FixedIP [optional] specifies a fixed IPv6 address to be used on this network.
40 V6FixedIP string `json:"v6-fixed-ip,omitempty"`
41}
42
43// ToMap converts a NetworkOpts to a map[string]string (for a request body)
44func (opts NetworkOpts) ToMap() (map[string]interface{}, error) {
45 return gophercloud.BuildRequestBody(opts, "")
46}
47
Jamie Hannaford9fdda582015-02-10 12:15:43 +010048// CreateOpts is the struct responsible for configuring a new database instance.
49type CreateOpts struct {
50 // Either the integer UUID (in string form) of the flavor, or its URI
51 // reference as specified in the response from the List() call. Required.
52 FlavorRef string
Jamie Hannaford9fdda582015-02-10 12:15:43 +010053 // Specifies the volume size in gigabytes (GB). The value must be between 1
54 // and 300. Required.
55 Size int
Jamie Hannaford9fdda582015-02-10 12:15:43 +010056 // Name of the instance to create. The length of the name is limited to
57 // 255 characters and any characters are permitted. Optional.
58 Name string
Jamie Hannaford9fdda582015-02-10 12:15:43 +010059 // A slice of database information options.
Jamie Hannaford2e695a32015-11-16 16:36:10 +010060 Databases db.CreateOptsBuilder
Jamie Hannaford9fdda582015-02-10 12:15:43 +010061 // A slice of user information options.
Jamie Hannaford2e695a32015-11-16 16:36:10 +010062 Users users.CreateOptsBuilder
Jamie Hannaford99eced52015-03-02 15:24:22 +010063 // Options to configure the type of datastore the instance will use. This is
64 // optional, and if excluded will default to MySQL.
65 Datastore *DatastoreOpts
esalipe10a27442017-02-14 06:11:01 +020066 // Networks dictates how this server will be attached to available networks.
67 Networks []NetworkOpts
Jamie Hannaford9fdda582015-02-10 12:15:43 +010068}
69
Jamie Hannaford9793d942015-02-18 15:13:20 +010070// ToInstanceCreateMap will render a JSON map.
Jamie Hannaford9fdda582015-02-10 12:15:43 +010071func (opts CreateOpts) ToInstanceCreateMap() (map[string]interface{}, error) {
72 if opts.Size > 300 || opts.Size < 1 {
Jon Perritt763e5922016-03-07 03:21:18 -060073 err := gophercloud.ErrInvalidInput{}
Jon Perritt763e5922016-03-07 03:21:18 -060074 err.Argument = "instances.CreateOpts.Size"
75 err.Value = opts.Size
76 err.Info = "Size (GB) must be between 1-300"
77 return nil, err
Jamie Hannaford9fdda582015-02-10 12:15:43 +010078 }
Jon Perrittdb0ae142016-03-13 00:33:41 -060079
Jamie Hannaford9fdda582015-02-10 12:15:43 +010080 if opts.FlavorRef == "" {
Jon Perrittdb0ae142016-03-13 00:33:41 -060081 return nil, gophercloud.ErrMissingInput{Argument: "instances.CreateOpts.FlavorRef"}
Jamie Hannaford9fdda582015-02-10 12:15:43 +010082 }
83
84 instance := map[string]interface{}{
85 "volume": map[string]int{"size": opts.Size},
86 "flavorRef": opts.FlavorRef,
87 }
88
89 if opts.Name != "" {
90 instance["name"] = opts.Name
91 }
Jamie Hannaford2e695a32015-11-16 16:36:10 +010092 if opts.Databases != nil {
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +010093 dbs, err := opts.Databases.ToDBCreateMap()
Jamie Hannaford9fdda582015-02-10 12:15:43 +010094 if err != nil {
95 return nil, err
96 }
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +010097 instance["databases"] = dbs["databases"]
Jamie Hannaford9fdda582015-02-10 12:15:43 +010098 }
Jamie Hannaford2e695a32015-11-16 16:36:10 +010099 if opts.Users != nil {
Jamie Hannaford2ca55d82015-02-12 14:21:55 +0100100 users, err := opts.Users.ToUserCreateMap()
Jamie Hannaford9fdda582015-02-10 12:15:43 +0100101 if err != nil {
102 return nil, err
103 }
Jamie Hannaford2ca55d82015-02-12 14:21:55 +0100104 instance["users"] = users["users"]
Jamie Hannaford9fdda582015-02-10 12:15:43 +0100105 }
Jon Perritt763e5922016-03-07 03:21:18 -0600106 if opts.Datastore != nil {
107 datastore, err := opts.Datastore.ToMap()
108 if err != nil {
109 return nil, err
110 }
111 instance["datastore"] = datastore
112 }
Jamie Hannaford9fdda582015-02-10 12:15:43 +0100113
esalipe10a27442017-02-14 06:11:01 +0200114 if len(opts.Networks) > 0 {
115 networks := make([]map[string]interface{}, len(opts.Networks))
116 for i, net := range opts.Networks {
117 var err error
118 networks[i], err = net.ToMap()
119 if err != nil {
120 return nil, err
121 }
122 }
123 instance["nics"] = networks
124 }
125
Jamie Hannaford9fdda582015-02-10 12:15:43 +0100126 return map[string]interface{}{"instance": instance}, nil
127}
128
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100129// Create asynchronously provisions a new database instance. It requires the
130// user to specify a flavor and a volume size. The API service then provisions
131// the instance with the requested flavor and sets up a volume of the specified
132// size, which is the storage for the database instance.
133//
134// Although this call only allows the creation of 1 instance per request, you
135// can create an instance with multiple databases and users. The default
136// binding for a MySQL instance is port 3306.
Jon Perritt3860b512016-03-29 12:01:48 -0500137func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
Jon Perrittdb0ae142016-03-13 00:33:41 -0600138 b, err := opts.ToInstanceCreateMap()
Jamie Hannaford9fdda582015-02-10 12:15:43 +0100139 if err != nil {
Jon Perrittdb0ae142016-03-13 00:33:41 -0600140 r.Err = err
Jon Perritt3860b512016-03-29 12:01:48 -0500141 return
Jamie Hannaford9fdda582015-02-10 12:15:43 +0100142 }
Jon Perrittdb0ae142016-03-13 00:33:41 -0600143 _, r.Err = client.Post(baseURL(client), &b, &r.Body, &gophercloud.RequestOpts{OkCodes: []int{200}})
jrperritt29ae6b32016-04-13 12:59:37 -0500144 return
Jamie Hannaford9fdda582015-02-10 12:15:43 +0100145}
Jamie Hannaford90684242015-02-10 12:46:07 +0100146
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100147// List retrieves the status and information for all database instances.
Jamie Hannaford90684242015-02-10 12:46:07 +0100148func List(client *gophercloud.ServiceClient) pagination.Pager {
Jon Perrittdb0ae142016-03-13 00:33:41 -0600149 return pagination.NewPager(client, baseURL(client), func(r pagination.PageResult) pagination.Page {
Jamie Hannaford90684242015-02-10 12:46:07 +0100150 return InstancePage{pagination.LinkedPageBase{PageResult: r}}
Jon Perrittdb0ae142016-03-13 00:33:41 -0600151 })
Jamie Hannaford90684242015-02-10 12:46:07 +0100152}
Jamie Hannaford821015f2015-02-10 12:58:36 +0100153
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100154// Get retrieves the status and information for a specified database instance.
Jon Perritt3860b512016-03-29 12:01:48 -0500155func Get(client *gophercloud.ServiceClient, id string) (r GetResult) {
Jon Perrittdb0ae142016-03-13 00:33:41 -0600156 _, r.Err = client.Get(resourceURL(client, id), &r.Body, nil)
jrperritt29ae6b32016-04-13 12:59:37 -0500157 return
Jamie Hannaford821015f2015-02-10 12:58:36 +0100158}
Jamie Hannaford5b16b632015-02-10 13:36:23 +0100159
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100160// Delete permanently destroys the database instance.
Jon Perritt3860b512016-03-29 12:01:48 -0500161func Delete(client *gophercloud.ServiceClient, id string) (r DeleteResult) {
Jon Perrittdb0ae142016-03-13 00:33:41 -0600162 _, r.Err = client.Delete(resourceURL(client, id), nil)
jrperritt29ae6b32016-04-13 12:59:37 -0500163 return
Jamie Hannaford5b16b632015-02-10 13:36:23 +0100164}
Jamie Hannaford94164fa2015-02-10 13:58:45 +0100165
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100166// EnableRootUser enables the login from any host for the root user and
167// provides the user with a generated root password.
Jon Perritt3860b512016-03-29 12:01:48 -0500168func EnableRootUser(client *gophercloud.ServiceClient, id string) (r EnableRootUserResult) {
Jon Perrittdb0ae142016-03-13 00:33:41 -0600169 _, r.Err = client.Post(userRootURL(client, id), nil, &r.Body, &gophercloud.RequestOpts{OkCodes: []int{200}})
jrperritt29ae6b32016-04-13 12:59:37 -0500170 return
Jamie Hannaford94164fa2015-02-10 13:58:45 +0100171}
Jamie Hannaforda74d4252015-02-10 15:35:01 +0100172
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100173// IsRootEnabled checks an instance to see if root access is enabled. It returns
174// True if root user is enabled for the specified database instance or False
175// otherwise.
Jon Perritt3860b512016-03-29 12:01:48 -0500176func IsRootEnabled(client *gophercloud.ServiceClient, id string) (r IsRootEnabledResult) {
Jon Perrittdb0ae142016-03-13 00:33:41 -0600177 _, r.Err = client.Get(userRootURL(client, id), &r.Body, nil)
jrperritt29ae6b32016-04-13 12:59:37 -0500178 return
Jamie Hannaforda74d4252015-02-10 15:35:01 +0100179}
Jamie Hannaford219ca592015-02-10 15:59:05 +0100180
Jamie Hannaford75e8cc42015-11-16 14:09:25 +0100181// Restart will restart only the MySQL Instance. Restarting MySQL will
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100182// erase any dynamic configuration settings that you have made within MySQL.
183// The MySQL service will be unavailable until the instance restarts.
Jon Perritt3860b512016-03-29 12:01:48 -0500184func Restart(client *gophercloud.ServiceClient, id string) (r ActionResult) {
Jon Perrittdb0ae142016-03-13 00:33:41 -0600185 b := map[string]interface{}{"restart": struct{}{}}
186 _, r.Err = client.Post(actionURL(client, id), &b, nil, nil)
jrperritt29ae6b32016-04-13 12:59:37 -0500187 return
Jamie Hannaford219ca592015-02-10 15:59:05 +0100188}
189
Jamie Hannaford75e8cc42015-11-16 14:09:25 +0100190// Resize changes the memory size of the instance, assuming a valid
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100191// flavorRef is provided. It will also restart the MySQL service.
Jon Perritt3860b512016-03-29 12:01:48 -0500192func Resize(client *gophercloud.ServiceClient, id, flavorRef string) (r ActionResult) {
Jon Perrittdb0ae142016-03-13 00:33:41 -0600193 b := map[string]interface{}{"resize": map[string]string{"flavorRef": flavorRef}}
194 _, r.Err = client.Post(actionURL(client, id), &b, nil, nil)
jrperritt29ae6b32016-04-13 12:59:37 -0500195 return
Jamie Hannaford219ca592015-02-10 15:59:05 +0100196}
197
Jamie Hannaford56d0c2e2015-02-12 11:50:18 +0100198// ResizeVolume will resize the attached volume for an instance. It supports
199// only increasing the volume size and does not support decreasing the size.
200// The volume size is in gigabytes (GB) and must be an integer.
Jon Perritt3860b512016-03-29 12:01:48 -0500201func ResizeVolume(client *gophercloud.ServiceClient, id string, size int) (r ActionResult) {
Jon Perrittdb0ae142016-03-13 00:33:41 -0600202 b := map[string]interface{}{"resize": map[string]interface{}{"volume": map[string]int{"size": size}}}
203 _, r.Err = client.Post(actionURL(client, id), &b, nil, nil)
jrperritt29ae6b32016-04-13 12:59:37 -0500204 return
Jamie Hannaford219ca592015-02-10 15:59:05 +0100205}