blob: 207c6de9f15c20efa27371ad8d6ea7fd5f0e6136 [file] [log] [blame]
Samuel A. Falvo IIc007c272014-02-10 20:49:26 -08001package servers
2
3import (
4 "github.com/racker/perigee"
Samuel A. Falvo II41c9f612014-03-11 19:00:10 -07005 "fmt"
Samuel A. Falvo IIc007c272014-02-10 20:49:26 -08006)
7
8// ListResult abstracts the raw results of making a List() request against the
9// API. As OpenStack extensions may freely alter the response bodies of
10// structures returned to the client, you may only safely access the data
Samuel A. Falvo IIe246ac02014-02-13 23:20:09 -080011// provided through separate, type-safe accessors or methods.
Samuel A. Falvo IIc007c272014-02-10 20:49:26 -080012type ListResult map[string]interface{}
13
Samuel A. Falvo II41c9f612014-03-11 19:00:10 -070014// ServerResult abstracts a single server description,
15// as returned by the OpenStack provider.
16// As OpenStack extensions may freely alter the response bodies of the
17// structures returned to the client,
18// you may only safely access the data provided through
19// separate, type-safe accessors or methods.
Samuel A. Falvo IIce000732014-02-13 18:53:53 -080020type ServerResult map[string]interface{}
21
Samuel A. Falvo IIc007c272014-02-10 20:49:26 -080022// List makes a request against the API to list servers accessible to you.
23func List(c *Client) (ListResult, error) {
24 var lr ListResult
25
26 h, err := c.getListHeaders()
27 if err != nil {
28 return nil, err
29 }
30
31 err = perigee.Get(c.getListUrl(), perigee.Options{
Samuel A. Falvo IIe246ac02014-02-13 23:20:09 -080032 Results: &lr,
Samuel A. Falvo IIc007c272014-02-10 20:49:26 -080033 MoreHeaders: h,
34 })
35 return lr, err
36}
37
Samuel A. Falvo IIce000732014-02-13 18:53:53 -080038// Create requests a server to be provisioned to the user in the current tenant.
39func Create(c *Client, opts map[string]interface{}) (ServerResult, error) {
40 var sr ServerResult
41
42 h, err := c.getCreateHeaders()
43 if err != nil {
44 return nil, err
45 }
46
47 err = perigee.Post(c.getCreateUrl(), perigee.Options{
48 Results: &sr,
Samuel A. Falvo IIe246ac02014-02-13 23:20:09 -080049 ReqBody: map[string]interface{}{
Samuel A. Falvo IIce000732014-02-13 18:53:53 -080050 "server": opts,
51 },
52 MoreHeaders: h,
Samuel A. Falvo IIe246ac02014-02-13 23:20:09 -080053 OkCodes: []int{202},
Samuel A. Falvo IIce000732014-02-13 18:53:53 -080054 })
55 return sr, err
56}
57
58// Delete requests that a server previously provisioned be removed from your account.
59func Delete(c *Client, id string) error {
60 h, err := c.getDeleteHeaders()
61 if err != nil {
62 return err
63 }
64
65 err = perigee.Delete(c.getDeleteUrl(id), perigee.Options{
66 MoreHeaders: h,
Samuel A. Falvo IIe246ac02014-02-13 23:20:09 -080067 OkCodes: []int{204},
Samuel A. Falvo IIce000732014-02-13 18:53:53 -080068 })
69 return err
70}
71
72// GetDetail requests details on a single server, by ID.
73func GetDetail(c *Client, id string) (ServerResult, error) {
74 var sr ServerResult
75
76 h, err := c.getDetailHeaders()
77 if err != nil {
78 return nil, err
79 }
80
81 err = perigee.Get(c.getDetailUrl(id), perigee.Options{
Samuel A. Falvo IIe246ac02014-02-13 23:20:09 -080082 Results: &sr,
Samuel A. Falvo IIce000732014-02-13 18:53:53 -080083 MoreHeaders: h,
84 })
85 return sr, err
86}
87
Samuel A. Falvo II22d3b772014-02-13 19:27:05 -080088// Update requests that various attributes of the indicated server be changed.
89func Update(c *Client, id string, opts map[string]interface{}) (ServerResult, error) {
90 var sr ServerResult
91
92 h, err := c.getUpdateHeaders()
93 if err != nil {
94 return nil, err
95 }
96
97 err = perigee.Put(c.getUpdateUrl(id), perigee.Options{
98 Results: &sr,
99 ReqBody: map[string]interface{}{
100 "server": opts,
101 },
102 MoreHeaders: h,
103 })
104 return sr, err
105}
Samuel A. Falvo IIca5f9a32014-03-11 17:52:58 -0700106
107// ChangeAdminPassword alters the administrator or root password for a specified
108// server.
109func ChangeAdminPassword(c *Client, id, newPassword string) error {
110 h, err := c.getActionHeaders()
111 if err != nil {
112 return err
113 }
114
115 err = perigee.Post(c.getActionUrl(id), perigee.Options{
116 ReqBody: struct{C map[string]string `json:"changePassword"`}{
117 map[string]string{"adminPass": newPassword},
118 },
119 MoreHeaders: h,
120 OkCodes: []int{202},
121 })
122 return err
123}
Samuel A. Falvo II41c9f612014-03-11 19:00:10 -0700124
125// ArgumentError errors occur when an argument supplied to a package function
126// fails to fall within acceptable values. For example, the Reboot() function
127// expects the "how" parameter to be one of HardReboot or SoftReboot. These
128// constants are (currently) strings, leading someone to wonder if they can pass
129// other string values instead, perhaps in an effort to break the API of their
130// provider. Reboot() returns this error in this situation.
131//
132// Function identifies which function was called/which function is generating
133// the error.
134// Argument identifies which formal argument was responsible for producing the
135// error.
136// Value provides the value as it was passed into the function.
137type ArgumentError struct {
138 Function, Argument string
139 Value interface{}
140}
141
142// Error yields a useful diagnostic for debugging purposes.
143func (e *ArgumentError) Error() string {
144 return fmt.Sprintf("Bad argument in call to %s, formal parameter %s, value %#v", e.Function, e.Argument, e.Value)
145}
146
147func (e *ArgumentError) String() string {
148 return e.Error()
149}
150
151// These constants determine how a server should be rebooted.
152// See the Reboot() function for further details.
153const (
154 SoftReboot = "SOFT"
155 HardReboot = "HARD"
156 OSReboot = SoftReboot
157 PowerCycle = HardReboot
158)
159
160// Reboot requests that a given server reboot.
161// Two methods exist for rebooting a server:
162//
163// HardReboot (aka PowerCycle) -- restarts the server instance by physically
164// cutting power to the machine, or if a VM, terminating it at the hypervisor
165// level. It's done. Caput. Full stop. Then, after a brief while, power is
166// restored or the VM instance restarted.
167//
168// SoftReboot (aka OSReboot). This approach simply tells the OS to restart
169// under its own procedures. E.g., in Linux, asking it to enter runlevel 6,
170// or executing "sudo shutdown -r now", or by wasking Windows to restart the
171// machine.
172func Reboot(c *Client, id, how string) error {
173 if (how != SoftReboot) && (how != HardReboot) {
174 return &ArgumentError{
175 Function: "Reboot",
176 Argument: "how",
177 Value: how,
178 }
179 }
180
181 h, err := c.getActionHeaders()
182 if err != nil {
183 return err
184 }
185
186 err = perigee.Post(c.getActionUrl(id), perigee.Options{
187 ReqBody: struct{C map[string]string `json:"reboot"`}{
188 map[string]string{"type": how},
189 },
190 MoreHeaders: h,
191 OkCodes: []int{202},
192 })
193 return err
194}