1package instances 2 3import ( 4 "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" 8) 9 10// CreateOptsBuilder is the top-level interface for create options. 11type CreateOptsBuilder interface { 12 ToInstanceCreateMap() (map[string]interface{}, error) 13} 14 15// DatastoreOpts represents the configuration for how an instance stores data. 16type DatastoreOpts struct { 17 Version string `json:"version"` 18 Type string `json:"type"` 19} 20 21// ToMap converts a DatastoreOpts to a map[string]string (for a request body) 22func (opts DatastoreOpts) ToMap() (map[string]interface{}, error) { 23 return gophercloud.BuildRequestBody(opts, "") 24} 25 26// 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 48// 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 53 // Specifies the volume size in gigabytes (GB). The value must be between 1 54 // and 300. Required. 55 Size int 56 // 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 59 // A slice of database information options. 60 Databases db.CreateOptsBuilder 61 // A slice of user information options. 62 Users users.CreateOptsBuilder 63 // 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 66 // Networks dictates how this server will be attached to available networks. 67 Networks []NetworkOpts 68} 69 70// ToInstanceCreateMap will render a JSON map. 71func (opts CreateOpts) ToInstanceCreateMap() (map[string]interface{}, error) { 72 if opts.Size > 300 || opts.Size < 1 { 73 err := gophercloud.ErrInvalidInput{} 74 err.Argument = "instances.CreateOpts.Size" 75 err.Value = opts.Size 76 err.Info = "Size (GB) must be between 1-300" 77 return nil, err 78 } 79 80 if opts.FlavorRef == "" { 81 return nil, gophercloud.ErrMissingInput{Argument: "instances.CreateOpts.FlavorRef"} 82 } 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 } 92 if opts.Databases != nil { 93 dbs, err := opts.Databases.ToDBCreateMap() 94 if err != nil { 95 return nil, err 96 } 97 instance["databases"] = dbs["databases"] 98 } 99 if opts.Users != nil { 100 users, err := opts.Users.ToUserCreateMap() 101 if err != nil { 102 return nil, err 103 } 104 instance["users"] = users["users"] 105 } 106 if opts.Datastore != nil { 107 datastore, err := opts.Datastore.ToMap() 108 if err != nil { 109 return nil, err 110 } 111 instance["datastore"] = datastore 112 } 113 114 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 126 return map[string]interface{}{"instance": instance}, nil 127} 128 129// 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. 137func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) { 138 b, err := opts.ToInstanceCreateMap() 139 if err != nil { 140 r.Err = err 141 return 142 } 143 _, r.Err = client.Post(baseURL(client), &b, &r.Body, &gophercloud.RequestOpts{OkCodes: []int{200}}) 144 return 145} 146 147// List retrieves the status and information for all database instances. 148func List(client *gophercloud.ServiceClient) pagination.Pager { 149 return pagination.NewPager(client, baseURL(client), func(r pagination.PageResult) pagination.Page { 150 return InstancePage{pagination.LinkedPageBase{PageResult: r}} 151 }) 152} 153 154// Get retrieves the status and information for a specified database instance. 155func Get(client *gophercloud.ServiceClient, id string) (r GetResult) { 156 _, r.Err = client.Get(resourceURL(client, id), &r.Body, nil) 157 return 158} 159 160// Delete permanently destroys the database instance. 161func Delete(client *gophercloud.ServiceClient, id string) (r DeleteResult) { 162 _, r.Err = client.Delete(resourceURL(client, id), nil) 163 return 164} 165 166// EnableRootUser enables the login from any host for the root user and 167// provides the user with a generated root password. 168func EnableRootUser(client *gophercloud.ServiceClient, id string) (r EnableRootUserResult) { 169 _, r.Err = client.Post(userRootURL(client, id), nil, &r.Body, &gophercloud.RequestOpts{OkCodes: []int{200}}) 170 return 171} 172 173// 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. 176func IsRootEnabled(client *gophercloud.ServiceClient, id string) (r IsRootEnabledResult) { 177 _, r.Err = client.Get(userRootURL(client, id), &r.Body, nil) 178 return 179} 180 181// Restart will restart only the MySQL Instance. Restarting MySQL will 182// erase any dynamic configuration settings that you have made within MySQL. 183// The MySQL service will be unavailable until the instance restarts. 184func Restart(client *gophercloud.ServiceClient, id string) (r ActionResult) { 185 b := map[string]interface{}{"restart": struct{}{}} 186 _, r.Err = client.Post(actionURL(client, id), &b, nil, nil) 187 return 188} 189 190// Resize changes the memory size of the instance, assuming a valid 191// flavorRef is provided. It will also restart the MySQL service. 192func Resize(client *gophercloud.ServiceClient, id, flavorRef string) (r ActionResult) { 193 b := map[string]interface{}{"resize": map[string]string{"flavorRef": flavorRef}} 194 _, r.Err = client.Post(actionURL(client, id), &b, nil, nil) 195 return 196} 197 198// 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. 201func ResizeVolume(client *gophercloud.ServiceClient, id string, size int) (r ActionResult) { 202 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) 204 return 205} 206 207// AttachConfigurationGroup will attach configuration group to the instance 208func AttachConfigurationGroup(client *gophercloud.ServiceClient, instanceID string, configID string) (r ConfigurationResult) { 209 b := map[string]interface{}{"instance": map[string]interface{}{"configuration": configID}} 210 _, r.Err = client.Put(resourceURL(client, instanceID), &b, nil, &gophercloud.RequestOpts{OkCodes: []int{202}}) 211 return 212} 213 214// DetachConfigurationGroup will dettach configuration group from the instance 215func DetachConfigurationGroup(client *gophercloud.ServiceClient, instanceID string) (r ConfigurationResult) { 216 b := map[string]interface{}{"instance": map[string]interface{}{}} 217 _, r.Err = client.Put(resourceURL(client, instanceID), &b, nil, &gophercloud.RequestOpts{OkCodes: []int{202}}) 218 return 219} 220