github.com/huaweicloud/golangsdk@v0.0.0-20210831081626-d823fe11ceba/openstack/compute/v2/servers/requests.go (about) 1 package servers 2 3 import ( 4 "encoding/base64" 5 "encoding/json" 6 7 "github.com/huaweicloud/golangsdk" 8 "github.com/huaweicloud/golangsdk/openstack/compute/v2/flavors" 9 "github.com/huaweicloud/golangsdk/openstack/compute/v2/images" 10 "github.com/huaweicloud/golangsdk/pagination" 11 ) 12 13 // ListOptsBuilder allows extensions to add additional parameters to the 14 // List request. 15 type ListOptsBuilder interface { 16 ToServerListQuery() (string, error) 17 } 18 19 // ListOpts allows the filtering and sorting of paginated collections through 20 // the API. Filtering is achieved by passing in struct field values that map to 21 // the server attributes you want to see returned. Marker and Limit are used 22 // for pagination. 23 type ListOpts struct { 24 // ChangesSince is a time/date stamp for when the server last changed status. 25 ChangesSince string `q:"changes-since"` 26 27 // Image is the name of the image in URL format. 28 Image string `q:"image"` 29 30 // Flavor is the name of the flavor in URL format. 31 Flavor string `q:"flavor"` 32 33 // Name of the server as a string; can be queried with regular expressions. 34 // Realize that ?name=bob returns both bob and bobb. If you need to match bob 35 // only, you can use a regular expression matching the syntax of the 36 // underlying database server implemented for Compute. 37 Name string `q:"name"` 38 39 // Status is the value of the status of the server so that you can filter on 40 // "ACTIVE" for example. 41 Status string `q:"status"` 42 43 // Host is the name of the host as a string. 44 Host string `q:"host"` 45 46 // Marker is a UUID of the server at which you want to set a marker. 47 Marker string `q:"marker"` 48 49 // Limit is an integer value for the limit of values to return. 50 Limit int `q:"limit"` 51 52 // AllTenants is a bool to show all tenants. 53 AllTenants bool `q:"all_tenants"` 54 55 // TenantID lists servers for a particular tenant. 56 // Setting "AllTenants = true" is required. 57 TenantID string `q:"tenant_id"` 58 } 59 60 // ToServerListQuery formats a ListOpts into a query string. 61 func (opts ListOpts) ToServerListQuery() (string, error) { 62 q, err := golangsdk.BuildQueryString(opts) 63 return q.String(), err 64 } 65 66 // List makes a request against the API to list servers accessible to you. 67 func List(client *golangsdk.ServiceClient, opts ListOptsBuilder) pagination.Pager { 68 url := listDetailURL(client) 69 if opts != nil { 70 query, err := opts.ToServerListQuery() 71 if err != nil { 72 return pagination.Pager{Err: err} 73 } 74 url += query 75 } 76 return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page { 77 return ServerPage{pagination.LinkedPageBase{PageResult: r}} 78 }) 79 } 80 81 // CreateOptsBuilder allows extensions to add additional parameters to the 82 // Create request. 83 type CreateOptsBuilder interface { 84 ToServerCreateMap() (map[string]interface{}, error) 85 } 86 87 // Network is used within CreateOpts to control a new server's network 88 // attachments. 89 type Network struct { 90 // UUID of a network to attach to the newly provisioned server. 91 // Required unless Port is provided. 92 UUID string 93 94 // Port of a neutron network to attach to the newly provisioned server. 95 // Required unless UUID is provided. 96 Port string 97 98 // FixedIP specifies a fixed IPv4 address to be used on this network. 99 FixedIP string 100 } 101 102 // Personality is an array of files that are injected into the server at launch. 103 type Personality []*File 104 105 // File is used within CreateOpts and RebuildOpts to inject a file into the 106 // server at launch. 107 // File implements the json.Marshaler interface, so when a Create or Rebuild 108 // operation is requested, json.Marshal will call File's MarshalJSON method. 109 type File struct { 110 // Path of the file. 111 Path string 112 113 // Contents of the file. Maximum content size is 255 bytes. 114 Contents []byte 115 } 116 117 // MarshalJSON marshals the escaped file, base64 encoding the contents. 118 func (f *File) MarshalJSON() ([]byte, error) { 119 file := struct { 120 Path string `json:"path"` 121 Contents string `json:"contents"` 122 }{ 123 Path: f.Path, 124 Contents: base64.StdEncoding.EncodeToString(f.Contents), 125 } 126 return json.Marshal(file) 127 } 128 129 // CreateOpts specifies server creation parameters. 130 type CreateOpts struct { 131 // Name is the name to assign to the newly launched server. 132 Name string `json:"name" required:"true"` 133 134 // ImageRef [optional; required if ImageName is not provided] is the ID or 135 // full URL to the image that contains the server's OS and initial state. 136 // Also optional if using the boot-from-volume extension. 137 ImageRef string `json:"imageRef"` 138 139 // ImageName [optional; required if ImageRef is not provided] is the name of 140 // the image that contains the server's OS and initial state. 141 // Also optional if using the boot-from-volume extension. 142 ImageName string `json:"-"` 143 144 // FlavorRef [optional; required if FlavorName is not provided] is the ID or 145 // full URL to the flavor that describes the server's specs. 146 FlavorRef string `json:"flavorRef"` 147 148 // FlavorName [optional; required if FlavorRef is not provided] is the name of 149 // the flavor that describes the server's specs. 150 FlavorName string `json:"-"` 151 152 // SecurityGroups lists the names of the security groups to which this server 153 // should belong. 154 SecurityGroups []string `json:"-"` 155 156 // UserData contains configuration information or scripts to use upon launch. 157 // Create will base64-encode it for you, if it isn't already. 158 UserData []byte `json:"-"` 159 160 // AvailabilityZone in which to launch the server. 161 AvailabilityZone string `json:"availability_zone,omitempty"` 162 163 // Networks dictates how this server will be attached to available networks. 164 // By default, the server will be attached to all isolated networks for the 165 // tenant. 166 Networks []Network `json:"-"` 167 168 // Metadata contains key-value pairs (up to 255 bytes each) to attach to the 169 // server. 170 Metadata map[string]string `json:"metadata,omitempty"` 171 172 // Personality includes files to inject into the server at launch. 173 // Create will base64-encode file contents for you. 174 Personality Personality `json:"personality,omitempty"` 175 176 // ConfigDrive enables metadata injection through a configuration drive. 177 ConfigDrive *bool `json:"config_drive,omitempty"` 178 179 // AdminPass sets the root user password. If not set, a randomly-generated 180 // password will be created and returned in the response. 181 AdminPass string `json:"adminPass,omitempty"` 182 183 // AccessIPv4 specifies an IPv4 address for the instance. 184 AccessIPv4 string `json:"accessIPv4,omitempty"` 185 186 // AccessIPv6 pecifies an IPv6 address for the instance. 187 AccessIPv6 string `json:"accessIPv6,omitempty"` 188 189 // ServiceClient will allow calls to be made to retrieve an image or 190 // flavor ID by name. 191 ServiceClient *golangsdk.ServiceClient `json:"-"` 192 } 193 194 // ToServerCreateMap assembles a request body based on the contents of a 195 // CreateOpts. 196 func (opts CreateOpts) ToServerCreateMap() (map[string]interface{}, error) { 197 sc := opts.ServiceClient 198 opts.ServiceClient = nil 199 b, err := golangsdk.BuildRequestBody(opts, "") 200 if err != nil { 201 return nil, err 202 } 203 204 if opts.UserData != nil { 205 var userData string 206 if _, err := base64.StdEncoding.DecodeString(string(opts.UserData)); err != nil { 207 userData = base64.StdEncoding.EncodeToString(opts.UserData) 208 } else { 209 userData = string(opts.UserData) 210 } 211 b["user_data"] = &userData 212 } 213 214 if len(opts.SecurityGroups) > 0 { 215 securityGroups := make([]map[string]interface{}, len(opts.SecurityGroups)) 216 for i, groupName := range opts.SecurityGroups { 217 securityGroups[i] = map[string]interface{}{"name": groupName} 218 } 219 b["security_groups"] = securityGroups 220 } 221 222 if len(opts.Networks) > 0 { 223 networks := make([]map[string]interface{}, len(opts.Networks)) 224 for i, net := range opts.Networks { 225 networks[i] = make(map[string]interface{}) 226 if net.UUID != "" { 227 networks[i]["uuid"] = net.UUID 228 } 229 if net.Port != "" { 230 networks[i]["port"] = net.Port 231 } 232 if net.FixedIP != "" { 233 networks[i]["fixed_ip"] = net.FixedIP 234 } 235 } 236 b["networks"] = networks 237 } 238 239 // If ImageRef isn't provided, check if ImageName was provided to ascertain 240 // the image ID. 241 if opts.ImageRef == "" { 242 if opts.ImageName != "" { 243 if sc == nil { 244 err := ErrNoClientProvidedForIDByName{} 245 err.Argument = "ServiceClient" 246 return nil, err 247 } 248 imageID, err := images.IDFromName(sc, opts.ImageName) 249 if err != nil { 250 return nil, err 251 } 252 b["imageRef"] = imageID 253 } 254 } 255 256 // If FlavorRef isn't provided, use FlavorName to ascertain the flavor ID. 257 if opts.FlavorRef == "" { 258 if opts.FlavorName == "" { 259 err := ErrNeitherFlavorIDNorFlavorNameProvided{} 260 err.Argument = "FlavorRef/FlavorName" 261 return nil, err 262 } 263 if sc == nil { 264 err := ErrNoClientProvidedForIDByName{} 265 err.Argument = "ServiceClient" 266 return nil, err 267 } 268 flavorID, err := flavors.IDFromName(sc, opts.FlavorName) 269 if err != nil { 270 return nil, err 271 } 272 b["flavorRef"] = flavorID 273 } 274 275 return map[string]interface{}{"server": b}, nil 276 } 277 278 // Create requests a server to be provisioned to the user in the current tenant. 279 func Create(client *golangsdk.ServiceClient, opts CreateOptsBuilder) (r CreateResult) { 280 reqBody, err := opts.ToServerCreateMap() 281 if err != nil { 282 r.Err = err 283 return 284 } 285 _, r.Err = client.Post(listURL(client), reqBody, &r.Body, nil) 286 return 287 } 288 289 // Delete requests that a server previously provisioned be removed from your 290 // account. 291 func Delete(client *golangsdk.ServiceClient, id string) (r DeleteResult) { 292 _, r.Err = client.Delete(deleteURL(client, id), nil) 293 return 294 } 295 296 // ForceDelete forces the deletion of a server. 297 func ForceDelete(client *golangsdk.ServiceClient, id string) (r ActionResult) { 298 _, r.Err = client.Post(actionURL(client, id), map[string]interface{}{"forceDelete": ""}, nil, nil) 299 return 300 } 301 302 // Get requests details on a single server, by ID. 303 func Get(client *golangsdk.ServiceClient, id string) (r GetResult) { 304 _, r.Err = client.Get(getURL(client, id), &r.Body, &golangsdk.RequestOpts{ 305 OkCodes: []int{200, 203}, 306 }) 307 return 308 } 309 310 // UpdateOptsBuilder allows extensions to add additional attributes to the 311 // Update request. 312 type UpdateOptsBuilder interface { 313 ToServerUpdateMap() (map[string]interface{}, error) 314 } 315 316 // UpdateOpts specifies the base attributes that may be updated on an existing 317 // server. 318 type UpdateOpts struct { 319 // Name changes the displayed name of the server. 320 // The server host name will *not* change. 321 // Server names are not constrained to be unique, even within the same tenant. 322 Name string `json:"name,omitempty"` 323 324 // AccessIPv4 provides a new IPv4 address for the instance. 325 AccessIPv4 string `json:"accessIPv4,omitempty"` 326 327 // AccessIPv6 provides a new IPv6 address for the instance. 328 AccessIPv6 string `json:"accessIPv6,omitempty"` 329 } 330 331 // ToServerUpdateMap formats an UpdateOpts structure into a request body. 332 func (opts UpdateOpts) ToServerUpdateMap() (map[string]interface{}, error) { 333 return golangsdk.BuildRequestBody(opts, "server") 334 } 335 336 // Update requests that various attributes of the indicated server be changed. 337 func Update(client *golangsdk.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) { 338 b, err := opts.ToServerUpdateMap() 339 if err != nil { 340 r.Err = err 341 return 342 } 343 _, r.Err = client.Put(updateURL(client, id), b, &r.Body, &golangsdk.RequestOpts{ 344 OkCodes: []int{200}, 345 }) 346 return 347 } 348 349 // ChangeAdminPassword alters the administrator or root password for a specified 350 // server. 351 func ChangeAdminPassword(client *golangsdk.ServiceClient, id, newPassword string) (r ActionResult) { 352 b := map[string]interface{}{ 353 "changePassword": map[string]string{ 354 "adminPass": newPassword, 355 }, 356 } 357 _, r.Err = client.Post(actionURL(client, id), b, nil, nil) 358 return 359 } 360 361 // RebootMethod describes the mechanisms by which a server reboot can be requested. 362 type RebootMethod string 363 364 // These constants determine how a server should be rebooted. 365 // See the Reboot() function for further details. 366 const ( 367 SoftReboot RebootMethod = "SOFT" 368 HardReboot RebootMethod = "HARD" 369 OSReboot = SoftReboot 370 PowerCycle = HardReboot 371 ) 372 373 // RebootOptsBuilder allows extensions to add additional parameters to the 374 // reboot request. 375 type RebootOptsBuilder interface { 376 ToServerRebootMap() (map[string]interface{}, error) 377 } 378 379 // RebootOpts provides options to the reboot request. 380 type RebootOpts struct { 381 // Type is the type of reboot to perform on the server. 382 Type RebootMethod `json:"type" required:"true"` 383 } 384 385 // ToServerRebootMap builds a body for the reboot request. 386 func (opts RebootOpts) ToServerRebootMap() (map[string]interface{}, error) { 387 return golangsdk.BuildRequestBody(opts, "reboot") 388 } 389 390 /* 391 Reboot requests that a given server reboot. 392 393 Two methods exist for rebooting a server: 394 395 HardReboot (aka PowerCycle) starts the server instance by physically cutting 396 power to the machine, or if a VM, terminating it at the hypervisor level. 397 It's done. Caput. Full stop. 398 Then, after a brief while, power is rtored or the VM instance restarted. 399 400 SoftReboot (aka OSReboot) simply tells the OS to restart under its own 401 procedure. 402 E.g., in Linux, asking it to enter runlevel 6, or executing 403 "sudo shutdown -r now", or by asking Windows to rtart the machine. 404 */ 405 func Reboot(client *golangsdk.ServiceClient, id string, opts RebootOptsBuilder) (r ActionResult) { 406 b, err := opts.ToServerRebootMap() 407 if err != nil { 408 r.Err = err 409 return 410 } 411 _, r.Err = client.Post(actionURL(client, id), b, nil, nil) 412 return 413 } 414 415 // RebuildOptsBuilder allows extensions to provide additional parameters to the 416 // rebuild request. 417 type RebuildOptsBuilder interface { 418 ToServerRebuildMap() (map[string]interface{}, error) 419 } 420 421 // RebuildOpts represents the configuration options used in a server rebuild 422 // operation. 423 type RebuildOpts struct { 424 // AdminPass is the server's admin password 425 AdminPass string `json:"adminPass,omitempty"` 426 427 // ImageID is the ID of the image you want your server to be provisioned on. 428 ImageID string `json:"imageRef"` 429 430 // ImageName is readable name of an image. 431 ImageName string `json:"-"` 432 433 // Name to set the server to 434 Name string `json:"name,omitempty"` 435 436 // AccessIPv4 [optional] provides a new IPv4 address for the instance. 437 AccessIPv4 string `json:"accessIPv4,omitempty"` 438 439 // AccessIPv6 [optional] provides a new IPv6 address for the instance. 440 AccessIPv6 string `json:"accessIPv6,omitempty"` 441 442 // Metadata [optional] contains key-value pairs (up to 255 bytes each) 443 // to attach to the server. 444 Metadata map[string]string `json:"metadata,omitempty"` 445 446 // Personality [optional] includes files to inject into the server at launch. 447 // Rebuild will base64-encode file contents for you. 448 Personality Personality `json:"personality,omitempty"` 449 450 // ServiceClient will allow calls to be made to retrieve an image or 451 // flavor ID by name. 452 ServiceClient *golangsdk.ServiceClient `json:"-"` 453 } 454 455 // ToServerRebuildMap formats a RebuildOpts struct into a map for use in JSON 456 func (opts RebuildOpts) ToServerRebuildMap() (map[string]interface{}, error) { 457 b, err := golangsdk.BuildRequestBody(opts, "") 458 if err != nil { 459 return nil, err 460 } 461 462 // If ImageRef isn't provided, check if ImageName was provided to ascertain 463 // the image ID. 464 if opts.ImageID == "" { 465 if opts.ImageName != "" { 466 if opts.ServiceClient == nil { 467 err := ErrNoClientProvidedForIDByName{} 468 err.Argument = "ServiceClient" 469 return nil, err 470 } 471 imageID, err := images.IDFromName(opts.ServiceClient, opts.ImageName) 472 if err != nil { 473 return nil, err 474 } 475 b["imageRef"] = imageID 476 } 477 } 478 479 return map[string]interface{}{"rebuild": b}, nil 480 } 481 482 // Rebuild will reprovision the server according to the configuration options 483 // provided in the RebuildOpts struct. 484 func Rebuild(client *golangsdk.ServiceClient, id string, opts RebuildOptsBuilder) (r RebuildResult) { 485 b, err := opts.ToServerRebuildMap() 486 if err != nil { 487 r.Err = err 488 return 489 } 490 _, r.Err = client.Post(actionURL(client, id), b, &r.Body, nil) 491 return 492 } 493 494 // ResizeOptsBuilder allows extensions to add additional parameters to the 495 // resize request. 496 type ResizeOptsBuilder interface { 497 ToServerResizeMap() (map[string]interface{}, error) 498 } 499 500 // ResizeOpts represents the configuration options used to control a Resize 501 // operation. 502 type ResizeOpts struct { 503 // FlavorRef is the ID of the flavor you wish your server to become. 504 FlavorRef string `json:"flavorRef" required:"true"` 505 } 506 507 // ToServerResizeMap formats a ResizeOpts as a map that can be used as a JSON 508 // request body for the Resize request. 509 func (opts ResizeOpts) ToServerResizeMap() (map[string]interface{}, error) { 510 return golangsdk.BuildRequestBody(opts, "resize") 511 } 512 513 // Resize instructs the provider to change the flavor of the server. 514 // 515 // Note that this implies rebuilding it. 516 // 517 // Unfortunately, one cannot pass rebuild parameters to the resize function. 518 // When the resize completes, the server will be in VERIFY_RESIZE state. 519 // While in this state, you can explore the use of the new server's 520 // configuration. If you like it, call ConfirmResize() to commit the resize 521 // permanently. Otherwise, call RevertResize() to restore the old configuration. 522 func Resize(client *golangsdk.ServiceClient, id string, opts ResizeOptsBuilder) (r ActionResult) { 523 b, err := opts.ToServerResizeMap() 524 if err != nil { 525 r.Err = err 526 return 527 } 528 _, r.Err = client.Post(actionURL(client, id), b, nil, nil) 529 return 530 } 531 532 // ConfirmResize confirms a previous resize operation on a server. 533 // See Resize() for more details. 534 func ConfirmResize(client *golangsdk.ServiceClient, id string) (r ActionResult) { 535 _, r.Err = client.Post(actionURL(client, id), map[string]interface{}{"confirmResize": nil}, nil, &golangsdk.RequestOpts{ 536 OkCodes: []int{201, 202, 204}, 537 }) 538 return 539 } 540 541 // RevertResize cancels a previous resize operation on a server. 542 // See Resize() for more details. 543 func RevertResize(client *golangsdk.ServiceClient, id string) (r ActionResult) { 544 _, r.Err = client.Post(actionURL(client, id), map[string]interface{}{"revertResize": nil}, nil, nil) 545 return 546 } 547 548 // ResetMetadataOptsBuilder allows extensions to add additional parameters to 549 // the Reset request. 550 type ResetMetadataOptsBuilder interface { 551 ToMetadataResetMap() (map[string]interface{}, error) 552 } 553 554 // MetadataOpts is a map that contains key-value pairs. 555 type MetadataOpts map[string]string 556 557 // ToMetadataResetMap assembles a body for a Reset request based on the contents 558 // of a MetadataOpts. 559 func (opts MetadataOpts) ToMetadataResetMap() (map[string]interface{}, error) { 560 return map[string]interface{}{"metadata": opts}, nil 561 } 562 563 // ToMetadataUpdateMap assembles a body for an Update request based on the 564 // contents of a MetadataOpts. 565 func (opts MetadataOpts) ToMetadataUpdateMap() (map[string]interface{}, error) { 566 return map[string]interface{}{"metadata": opts}, nil 567 } 568 569 // ResetMetadata will create multiple new key-value pairs for the given server 570 // ID. 571 // Note: Using this operation will erase any already-existing metadata and 572 // create the new metadata provided. To keep any already-existing metadata, 573 // use the UpdateMetadatas or UpdateMetadata function. 574 func ResetMetadata(client *golangsdk.ServiceClient, id string, opts ResetMetadataOptsBuilder) (r ResetMetadataResult) { 575 b, err := opts.ToMetadataResetMap() 576 if err != nil { 577 r.Err = err 578 return 579 } 580 _, r.Err = client.Put(metadataURL(client, id), b, &r.Body, &golangsdk.RequestOpts{ 581 OkCodes: []int{200}, 582 }) 583 return 584 } 585 586 // Metadata requests all the metadata for the given server ID. 587 func Metadata(client *golangsdk.ServiceClient, id string) (r GetMetadataResult) { 588 _, r.Err = client.Get(metadataURL(client, id), &r.Body, nil) 589 return 590 } 591 592 // UpdateMetadataOptsBuilder allows extensions to add additional parameters to 593 // the Create request. 594 type UpdateMetadataOptsBuilder interface { 595 ToMetadataUpdateMap() (map[string]interface{}, error) 596 } 597 598 // UpdateMetadata updates (or creates) all the metadata specified by opts for 599 // the given server ID. This operation does not affect already-existing metadata 600 // that is not specified by opts. 601 func UpdateMetadata(client *golangsdk.ServiceClient, id string, opts UpdateMetadataOptsBuilder) (r UpdateMetadataResult) { 602 b, err := opts.ToMetadataUpdateMap() 603 if err != nil { 604 r.Err = err 605 return 606 } 607 _, r.Err = client.Post(metadataURL(client, id), b, &r.Body, &golangsdk.RequestOpts{ 608 OkCodes: []int{200}, 609 }) 610 return 611 } 612 613 // MetadatumOptsBuilder allows extensions to add additional parameters to the 614 // Create request. 615 type MetadatumOptsBuilder interface { 616 ToMetadatumCreateMap() (map[string]interface{}, string, error) 617 } 618 619 // MetadatumOpts is a map of length one that contains a key-value pair. 620 type MetadatumOpts map[string]string 621 622 // ToMetadatumCreateMap assembles a body for a Create request based on the 623 // contents of a MetadataumOpts. 624 func (opts MetadatumOpts) ToMetadatumCreateMap() (map[string]interface{}, string, error) { 625 if len(opts) != 1 { 626 err := golangsdk.ErrInvalidInput{} 627 err.Argument = "servers.MetadatumOpts" 628 err.Info = "Must have 1 and only 1 key-value pair" 629 return nil, "", err 630 } 631 metadatum := map[string]interface{}{"meta": opts} 632 var key string 633 for k := range metadatum["meta"].(MetadatumOpts) { 634 key = k 635 } 636 return metadatum, key, nil 637 } 638 639 // CreateMetadatum will create or update the key-value pair with the given key 640 // for the given server ID. 641 func CreateMetadatum(client *golangsdk.ServiceClient, id string, opts MetadatumOptsBuilder) (r CreateMetadatumResult) { 642 b, key, err := opts.ToMetadatumCreateMap() 643 if err != nil { 644 r.Err = err 645 return 646 } 647 _, r.Err = client.Put(metadatumURL(client, id, key), b, &r.Body, &golangsdk.RequestOpts{ 648 OkCodes: []int{200}, 649 }) 650 return 651 } 652 653 // Metadatum requests the key-value pair with the given key for the given 654 // server ID. 655 func Metadatum(client *golangsdk.ServiceClient, id, key string) (r GetMetadatumResult) { 656 _, r.Err = client.Get(metadatumURL(client, id, key), &r.Body, nil) 657 return 658 } 659 660 // DeleteMetadatum will delete the key-value pair with the given key for the 661 // given server ID. 662 func DeleteMetadatum(client *golangsdk.ServiceClient, id, key string) (r DeleteMetadatumResult) { 663 _, r.Err = client.Delete(metadatumURL(client, id, key), nil) 664 return 665 } 666 667 // ListAddresses makes a request against the API to list the servers IP 668 // addresses. 669 func ListAddresses(client *golangsdk.ServiceClient, id string) pagination.Pager { 670 return pagination.NewPager(client, listAddressesURL(client, id), func(r pagination.PageResult) pagination.Page { 671 return AddressPage{pagination.SinglePageBase(r)} 672 }) 673 } 674 675 // ListAddressesByNetwork makes a request against the API to list the servers IP 676 // addresses for the given network. 677 func ListAddressesByNetwork(client *golangsdk.ServiceClient, id, network string) pagination.Pager { 678 return pagination.NewPager(client, listAddressesByNetworkURL(client, id, network), func(r pagination.PageResult) pagination.Page { 679 return NetworkAddressPage{pagination.SinglePageBase(r)} 680 }) 681 } 682 683 // CreateImageOptsBuilder allows extensions to add additional parameters to the 684 // CreateImage request. 685 type CreateImageOptsBuilder interface { 686 ToServerCreateImageMap() (map[string]interface{}, error) 687 } 688 689 // CreateImageOpts provides options to pass to the CreateImage request. 690 type CreateImageOpts struct { 691 // Name of the image/snapshot. 692 Name string `json:"name" required:"true"` 693 694 // Metadata contains key-value pairs (up to 255 bytes each) to attach to 695 // the created image. 696 Metadata map[string]string `json:"metadata,omitempty"` 697 } 698 699 // ToServerCreateImageMap formats a CreateImageOpts structure into a request 700 // body. 701 func (opts CreateImageOpts) ToServerCreateImageMap() (map[string]interface{}, error) { 702 return golangsdk.BuildRequestBody(opts, "createImage") 703 } 704 705 // CreateImage makes a request against the nova API to schedule an image to be 706 // created of the server 707 func CreateImage(client *golangsdk.ServiceClient, id string, opts CreateImageOptsBuilder) (r CreateImageResult) { 708 b, err := opts.ToServerCreateImageMap() 709 if err != nil { 710 r.Err = err 711 return 712 } 713 resp, err := client.Post(actionURL(client, id), b, nil, &golangsdk.RequestOpts{ 714 OkCodes: []int{202}, 715 }) 716 r.Err = err 717 r.Header = resp.Header 718 return 719 } 720 721 // IDFromName is a convienience function that returns a server's ID given its 722 // name. 723 func IDFromName(client *golangsdk.ServiceClient, name string) (string, error) { 724 count := 0 725 id := "" 726 727 listOpts := ListOpts{ 728 Name: name, 729 } 730 731 allPages, err := List(client, listOpts).AllPages() 732 if err != nil { 733 return "", err 734 } 735 736 all, err := ExtractServers(allPages) 737 if err != nil { 738 return "", err 739 } 740 741 for _, f := range all { 742 if f.Name == name { 743 count++ 744 id = f.ID 745 } 746 } 747 748 switch count { 749 case 0: 750 return "", golangsdk.ErrResourceNotFound{Name: name, ResourceType: "server"} 751 case 1: 752 return id, nil 753 default: 754 return "", golangsdk.ErrMultipleResourcesFound{Name: name, Count: count, ResourceType: "server"} 755 } 756 } 757 758 // GetPassword makes a request against the nova API to get the encrypted 759 // administrative password. 760 func GetPassword(client *golangsdk.ServiceClient, serverId string) (r GetPasswordResult) { 761 _, r.Err = client.Get(passwordURL(client, serverId), &r.Body, nil) 762 return 763 } 764 765 // ShowConsoleOutputOptsBuilder is the interface types must satisfy in order to be 766 // used as ShowConsoleOutput options 767 type ShowConsoleOutputOptsBuilder interface { 768 ToServerShowConsoleOutputMap() (map[string]interface{}, error) 769 } 770 771 // ShowConsoleOutputOpts satisfies the ShowConsoleOutputOptsBuilder 772 type ShowConsoleOutputOpts struct { 773 // The number of lines to fetch from the end of console log. 774 // All lines will be returned if this is not specified. 775 Length int `json:"length,omitempty"` 776 } 777 778 // ToServerShowConsoleOutputMap formats a ShowConsoleOutputOpts structure into a request body. 779 func (opts ShowConsoleOutputOpts) ToServerShowConsoleOutputMap() (map[string]interface{}, error) { 780 return golangsdk.BuildRequestBody(opts, "os-getConsoleOutput") 781 } 782 783 // ShowConsoleOutput makes a request against the nova API to get console log from the server 784 func ShowConsoleOutput(client *golangsdk.ServiceClient, id string, opts ShowConsoleOutputOptsBuilder) (r ShowConsoleOutputResult) { 785 b, err := opts.ToServerShowConsoleOutputMap() 786 if err != nil { 787 r.Err = err 788 return 789 } 790 _, r.Err = client.Post(actionURL(client, id), b, &r.Body, &golangsdk.RequestOpts{ 791 OkCodes: []int{200}, 792 }) 793 return 794 }