OLD | NEW |
1 // The nova package provides a way to access the OpenStack Compute APIs. | 1 // The nova package provides a way to access the OpenStack Compute APIs. |
2 // See http://docs.openstack.org/api/openstack-compute/2/content/. | 2 // See http://docs.openstack.org/api/openstack-compute/2/content/. |
3 package nova | 3 package nova |
4 | 4 |
5 import ( | 5 import ( |
6 "encoding/base64" | 6 "encoding/base64" |
7 "fmt" | 7 "fmt" |
8 "launchpad.net/goose/client" | 8 "launchpad.net/goose/client" |
9 goosehttp "launchpad.net/goose/http" | 9 goosehttp "launchpad.net/goose/http" |
10 "net/http" | 10 "net/http" |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 // ListFlavours lists IDs, names, and links for available flavors. | 96 // ListFlavours lists IDs, names, and links for available flavors. |
97 func (c *Client) ListFlavors() ([]Entity, error) { | 97 func (c *Client) ListFlavors() ([]Entity, error) { |
98 var resp struct { | 98 var resp struct { |
99 Flavors []Entity | 99 Flavors []Entity |
100 } | 100 } |
101 requestData := goosehttp.RequestData{RespValue: &resp} | 101 requestData := goosehttp.RequestData{RespValue: &resp} |
102 err := c.client.SendRequest(client.GET, "compute", apiFlavors, &requestD
ata, "failed to get list of flavors") | 102 err := c.client.SendRequest(client.GET, "compute", apiFlavors, &requestD
ata, "failed to get list of flavors") |
103 return resp.Flavors, err | 103 return resp.Flavors, err |
104 } | 104 } |
105 | 105 |
| 106 // FlavorDetail describes detailed information about a flavor. |
106 type FlavorDetail struct { | 107 type FlavorDetail struct { |
107 Name string | 108 Name string |
108 » RAM int | 109 » RAM int // Available RAM, in MB |
109 » VCPUs int | 110 » VCPUs int // Number of virtual CPU (cores) |
110 » Disk int | 111 » Disk int // Available root partition space, in GB |
111 Id string | 112 Id string |
112 » Swap interface{} // Can be an empty string (?!) | 113 » Links []Link |
113 } | 114 } |
114 | 115 |
115 // ListFlavorsDetail lists all details for available flavors. | 116 // ListFlavorsDetail lists all details for available flavors. |
116 func (c *Client) ListFlavorsDetail() ([]FlavorDetail, error) { | 117 func (c *Client) ListFlavorsDetail() ([]FlavorDetail, error) { |
117 var resp struct { | 118 var resp struct { |
118 Flavors []FlavorDetail | 119 Flavors []FlavorDetail |
119 } | 120 } |
120 requestData := goosehttp.RequestData{RespValue: &resp} | 121 requestData := goosehttp.RequestData{RespValue: &resp} |
121 err := c.client.SendRequest(client.GET, "compute", apiFlavorsDetail, &re
questData, | 122 err := c.client.SendRequest(client.GET, "compute", apiFlavorsDetail, &re
questData, |
122 "failed to get list of flavors details") | 123 "failed to get list of flavors details") |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 } | 225 } |
225 requestData := goosehttp.RequestData{ReqValue: req, RespValue: &resp, Ex
pectedStatus: []int{http.StatusAccepted}} | 226 requestData := goosehttp.RequestData{ReqValue: req, RespValue: &resp, Ex
pectedStatus: []int{http.StatusAccepted}} |
226 err := c.client.SendRequest(client.POST, "compute", apiServers, &request
Data, | 227 err := c.client.SendRequest(client.POST, "compute", apiServers, &request
Data, |
227 "failed to run a server with %#v", opts) | 228 "failed to run a server with %#v", opts) |
228 if err != nil { | 229 if err != nil { |
229 return nil, err | 230 return nil, err |
230 } | 231 } |
231 return &resp.Server, nil | 232 return &resp.Server, nil |
232 } | 233 } |
233 | 234 |
| 235 // SecurityGroupRef refers to an existing named security group |
| 236 type SecurityGroupRef struct { |
| 237 TenantId string `json:"tenant_id"` |
| 238 Name string `json:"name"` |
| 239 } |
| 240 |
234 type SecurityGroupRule struct { | 241 type SecurityGroupRule struct { |
235 FromPort *int `json:"from_port"` // Can be nil | 242 FromPort *int `json:"from_port"` // Can be nil |
236 IPProtocol *string `json:"ip_protocol"` // Can be nil | 243 IPProtocol *string `json:"ip_protocol"` // Can be nil |
237 ToPort *int `json:"to_port"` // Can be nil | 244 ToPort *int `json:"to_port"` // Can be nil |
238 ParentGroupId int `json:"parent_group_id"` | 245 ParentGroupId int `json:"parent_group_id"` |
239 IPRange map[string]string `json:"ip_range"` // Can be empty | 246 IPRange map[string]string `json:"ip_range"` // Can be empty |
240 Id int | 247 Id int |
241 » Group map[string]string // Can be empty | 248 » Group *SecurityGroupRef // Can be nil |
242 } | 249 } |
243 | 250 |
244 type SecurityGroup struct { | 251 type SecurityGroup struct { |
245 Rules []SecurityGroupRule | 252 Rules []SecurityGroupRule |
246 TenantId string `json:"tenant_id"` | 253 TenantId string `json:"tenant_id"` |
247 Id int | 254 Id int |
248 Name string | 255 Name string |
249 Description string | 256 Description string |
250 } | 257 } |
251 | 258 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
304 | 311 |
305 // DeleteSecurityGroup deletes the specified security group. | 312 // DeleteSecurityGroup deletes the specified security group. |
306 func (c *Client) DeleteSecurityGroup(groupId int) error { | 313 func (c *Client) DeleteSecurityGroup(groupId int) error { |
307 url := fmt.Sprintf("%s/%d", apiSecurityGroups, groupId) | 314 url := fmt.Sprintf("%s/%d", apiSecurityGroups, groupId) |
308 requestData := goosehttp.RequestData{ExpectedStatus: []int{http.StatusAc
cepted}} | 315 requestData := goosehttp.RequestData{ExpectedStatus: []int{http.StatusAc
cepted}} |
309 err := c.client.SendRequest(client.DELETE, "compute", url, &requestData, | 316 err := c.client.SendRequest(client.DELETE, "compute", url, &requestData, |
310 "failed to delete a security group with id=%d", groupId) | 317 "failed to delete a security group with id=%d", groupId) |
311 return err | 318 return err |
312 } | 319 } |
313 | 320 |
| 321 // RuleInfo allows the callers of CreateSecurityGroupRule() to |
| 322 // create 2 types of security group rules: ingress rules and group |
| 323 // rules. The difference stems from how the "source" is defined. |
| 324 // It can be either: |
| 325 // 1. Ingress rules - specified directly with any valid subnet mask |
| 326 // in CIDR format (e.g. "192.168.0.0/16"); |
| 327 // 2. Group rules - specified indirectly by giving a source group, |
| 328 // which can be any user's group (different tenant ID). |
| 329 // |
| 330 // Every rule works as an iptables ACCEPT rule, thus a group/ with no |
| 331 // rules does not allow ingress at all. Rules can be added and removed |
| 332 // while the server(s) are running. The set of security groups that |
| 333 // apply to a server is changed only when the server is |
| 334 // started. Adding or removing a security group on a running server |
| 335 // will not take effect until that server is restarted. However, |
| 336 // changing rules of existing groups will take effect immediately. |
| 337 // |
| 338 // For more information: |
| 339 // http://docs.openstack.org/developer/nova/nova.concepts.html#concept-security-
groups |
| 340 // Nova source: https://github.com/openstack/nova.git |
314 type RuleInfo struct { | 341 type RuleInfo struct { |
315 » IPProtocol string `json:"ip_protocol"` // Required, if GroupId is
nil | 342 » /// IPProtocol is optional, and if specified must be "tcp", "udp" or |
316 » FromPort int `json:"from_port"` // Required, if GroupId is
nil | 343 » // "icmp" (in this case, both FromPort and ToPort can be -1). |
317 » ToPort int `json:"to_port"` // Required, if GroupId is
nil | 344 » IPProtocol string `json:"ip_protocol"` |
318 » Cidr string `json:"cidr"` // Required, if GroupId is
nil | 345 |
319 » GroupId *int `json:"group_id"` // If nil, FromPort/ToPort
/IPProtocol must be set | 346 » // FromPort and ToPort are both optional, and if specifed must be |
320 » ParentGroupId int `json:"parent_group_id"` // Required always | 347 » // integers between 1 and 65535 (valid TCP port numbers). -1 is a |
| 348 » // special value, meaning "use default" (e.g. for ICMP). |
| 349 » FromPort int `json:"from_port"` |
| 350 » ToPort int `json:"to_port"` |
| 351 |
| 352 » // Cidr cannot be specified with GroupId. Ingress rules need a valid |
| 353 » // subnet mast in CIDR format here, while if GroupID is specifed, it |
| 354 » // means you're adding a group rule, specifying source group ID, which |
| 355 » // must exists already and can be equal to ParentGroupId). |
| 356 » // need Cidr, while |
| 357 » Cidr string `json:"cidr"` |
| 358 » GroupId *int `json:"group_id"` |
| 359 |
| 360 » // ParentGroupId is always required and specifies the group to which |
| 361 » // the rule is added. |
| 362 » ParentGroupId int `json:"parent_group_id"` |
321 } | 363 } |
322 | 364 |
323 // CreateSecurityGroupRule creates a security group rule. | 365 // CreateSecurityGroupRule creates a security group rule. |
| 366 // It can either be an ingress rule or group rule (see the |
| 367 // description of RuleInfo). |
324 func (c *Client) CreateSecurityGroupRule(ruleInfo RuleInfo) (*SecurityGroupRule,
error) { | 368 func (c *Client) CreateSecurityGroupRule(ruleInfo RuleInfo) (*SecurityGroupRule,
error) { |
325 var req struct { | 369 var req struct { |
326 SecurityGroupRule RuleInfo `json:"security_group_rule"` | 370 SecurityGroupRule RuleInfo `json:"security_group_rule"` |
327 } | 371 } |
328 req.SecurityGroupRule = ruleInfo | 372 req.SecurityGroupRule = ruleInfo |
329 | 373 |
330 var resp struct { | 374 var resp struct { |
331 SecurityGroupRule SecurityGroupRule `json:"security_group_rule"` | 375 SecurityGroupRule SecurityGroupRule `json:"security_group_rule"` |
332 } | 376 } |
333 | 377 |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 } `json:"removeFloatingIp"` | 512 } `json:"removeFloatingIp"` |
469 } | 513 } |
470 req.RemoveFloatingIP.Address = address | 514 req.RemoveFloatingIP.Address = address |
471 | 515 |
472 url := fmt.Sprintf("%s/%s/action", apiServers, serverId) | 516 url := fmt.Sprintf("%s/%s/action", apiServers, serverId) |
473 requestData := goosehttp.RequestData{ReqValue: req, ExpectedStatus: []in
t{http.StatusAccepted}} | 517 requestData := goosehttp.RequestData{ReqValue: req, ExpectedStatus: []in
t{http.StatusAccepted}} |
474 err := c.client.SendRequest(client.POST, "compute", url, &requestData, | 518 err := c.client.SendRequest(client.POST, "compute", url, &requestData, |
475 "failed to remove floating ip %s to server %s", address, serverI
d) | 519 "failed to remove floating ip %s to server %s", address, serverI
d) |
476 return err | 520 return err |
477 } | 521 } |
OLD | NEW |