github.com/vnpaycloud-console/gophercloud/v2@v2.0.5/openstack/blockstorage/v3/volumes/requests.go (about) 1 package volumes 2 3 import ( 4 "context" 5 "maps" 6 "regexp" 7 8 "github.com/vnpaycloud-console/gophercloud/v2" 9 "github.com/vnpaycloud-console/gophercloud/v2/pagination" 10 ) 11 12 // SchedulerHintOptsBuilder builds the scheduler hints into a serializable format. 13 type SchedulerHintOptsBuilder interface { 14 ToSchedulerHintsMap() (map[string]any, error) 15 } 16 17 // SchedulerHintOpts contains options for providing scheduler hints 18 // when creating a Volume. This object is passed to the volumes.Create function. 19 // For more information about these parameters, see the Volume object. 20 type SchedulerHintOpts struct { 21 // DifferentHost will place the volume on a different back-end that does not 22 // host the given volumes. 23 DifferentHost []string 24 25 // SameHost will place the volume on a back-end that hosts the given volumes. 26 SameHost []string 27 28 // LocalToInstance will place volume on same host on a given instance 29 LocalToInstance string 30 31 // Query is a conditional statement that results in back-ends able to 32 // host the volume. 33 Query string 34 35 // AdditionalProperies are arbitrary key/values that are not validated by nova. 36 AdditionalProperties map[string]any 37 } 38 39 // ToSchedulerHintsMap assembles a request body for scheduler hints 40 func (opts SchedulerHintOpts) ToSchedulerHintsMap() (map[string]any, error) { 41 sh := make(map[string]any) 42 43 uuidRegex, _ := regexp.Compile("^[a-z0-9]{8}-[a-z0-9]{4}-[1-5][a-z0-9]{3}-[a-z0-9]{4}-[a-z0-9]{12}$") 44 45 if len(opts.DifferentHost) > 0 { 46 for _, diffHost := range opts.DifferentHost { 47 if !uuidRegex.MatchString(diffHost) { 48 err := gophercloud.ErrInvalidInput{} 49 err.Argument = "volumes.SchedulerHintOpts.DifferentHost" 50 err.Value = opts.DifferentHost 51 err.Info = "The hosts must be in UUID format." 52 return nil, err 53 } 54 } 55 sh["different_host"] = opts.DifferentHost 56 } 57 58 if len(opts.SameHost) > 0 { 59 for _, sameHost := range opts.SameHost { 60 if !uuidRegex.MatchString(sameHost) { 61 err := gophercloud.ErrInvalidInput{} 62 err.Argument = "volumes.SchedulerHintOpts.SameHost" 63 err.Value = opts.SameHost 64 err.Info = "The hosts must be in UUID format." 65 return nil, err 66 } 67 } 68 sh["same_host"] = opts.SameHost 69 } 70 71 if opts.LocalToInstance != "" { 72 if !uuidRegex.MatchString(opts.LocalToInstance) { 73 err := gophercloud.ErrInvalidInput{} 74 err.Argument = "volumes.SchedulerHintOpts.LocalToInstance" 75 err.Value = opts.LocalToInstance 76 err.Info = "The instance must be in UUID format." 77 return nil, err 78 } 79 sh["local_to_instance"] = opts.LocalToInstance 80 } 81 82 if opts.Query != "" { 83 sh["query"] = opts.Query 84 } 85 86 if opts.AdditionalProperties != nil { 87 for k, v := range opts.AdditionalProperties { 88 sh[k] = v 89 } 90 } 91 92 if len(sh) == 0 { 93 return sh, nil 94 } 95 96 return map[string]any{"OS-SCH-HNT:scheduler_hints": sh}, nil 97 } 98 99 // CreateOptsBuilder allows extensions to add additional parameters to the 100 // Create request. 101 type CreateOptsBuilder interface { 102 ToVolumeCreateMap() (map[string]any, error) 103 } 104 105 // CreateOpts contains options for creating a Volume. This object is passed to 106 // the volumes.Create function. For more information about these parameters, 107 // see the Volume object. 108 type CreateOpts struct { 109 // The size of the volume, in GB 110 Size int `json:"size,omitempty"` 111 // The availability zone 112 AvailabilityZone string `json:"availability_zone,omitempty"` 113 // ConsistencyGroupID is the ID of a consistency group 114 ConsistencyGroupID string `json:"consistencygroup_id,omitempty"` 115 // The volume description 116 Description string `json:"description,omitempty"` 117 // One or more metadata key and value pairs to associate with the volume 118 Metadata map[string]string `json:"metadata,omitempty"` 119 // The volume name 120 Name string `json:"name,omitempty"` 121 // the ID of the existing volume snapshot 122 SnapshotID string `json:"snapshot_id,omitempty"` 123 // SourceReplica is a UUID of an existing volume to replicate with 124 SourceReplica string `json:"source_replica,omitempty"` 125 // the ID of the existing volume 126 SourceVolID string `json:"source_volid,omitempty"` 127 // The ID of the image from which you want to create the volume. 128 // Required to create a bootable volume. 129 ImageID string `json:"imageRef,omitempty"` 130 // Specifies the backup ID, from which you want to create the volume. 131 // Create a volume from a backup is supported since 3.47 microversion 132 BackupID string `json:"backup_id,omitempty"` 133 // The associated volume type 134 VolumeType string `json:"volume_type,omitempty"` 135 } 136 137 // ToVolumeCreateMap assembles a request body based on the contents of a 138 // CreateOpts. 139 func (opts CreateOpts) ToVolumeCreateMap() (map[string]any, error) { 140 return gophercloud.BuildRequestBody(opts, "volume") 141 } 142 143 // Create will create a new Volume based on the values in CreateOpts. To extract 144 // the Volume object from the response, call the Extract method on the 145 // CreateResult. 146 func Create(ctx context.Context, client *gophercloud.ServiceClient, opts CreateOptsBuilder, hintOpts SchedulerHintOptsBuilder) (r CreateResult) { 147 b, err := opts.ToVolumeCreateMap() 148 if err != nil { 149 r.Err = err 150 return 151 } 152 153 if hintOpts != nil { 154 sh, err := hintOpts.ToSchedulerHintsMap() 155 if err != nil { 156 r.Err = err 157 return 158 } 159 maps.Copy(b, sh) 160 } 161 162 resp, err := client.Post(ctx, createURL(client), b, &r.Body, &gophercloud.RequestOpts{ 163 OkCodes: []int{202}, 164 }) 165 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 166 return 167 } 168 169 // DeleteOptsBuilder allows extensions to add additional parameters to the 170 // Delete request. 171 type DeleteOptsBuilder interface { 172 ToVolumeDeleteQuery() (string, error) 173 } 174 175 // DeleteOpts contains options for deleting a Volume. This object is passed to 176 // the volumes.Delete function. 177 type DeleteOpts struct { 178 // Delete all snapshots of this volume as well. 179 Cascade bool `q:"cascade"` 180 } 181 182 // ToLoadBalancerDeleteQuery formats a DeleteOpts into a query string. 183 func (opts DeleteOpts) ToVolumeDeleteQuery() (string, error) { 184 q, err := gophercloud.BuildQueryString(opts) 185 return q.String(), err 186 } 187 188 // Delete will delete the existing Volume with the provided ID. 189 func Delete(ctx context.Context, client *gophercloud.ServiceClient, id string, opts DeleteOptsBuilder) (r DeleteResult) { 190 url := deleteURL(client, id) 191 if opts != nil { 192 query, err := opts.ToVolumeDeleteQuery() 193 if err != nil { 194 r.Err = err 195 return 196 } 197 url += query 198 } 199 resp, err := client.Delete(ctx, url, nil) 200 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 201 return 202 } 203 204 // Get retrieves the Volume with the provided ID. To extract the Volume object 205 // from the response, call the Extract method on the GetResult. 206 func Get(ctx context.Context, client *gophercloud.ServiceClient, id string) (r GetResult) { 207 resp, err := client.Get(ctx, getURL(client, id), &r.Body, nil) 208 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 209 return 210 } 211 212 // ListOptsBuilder allows extensions to add additional parameters to the List 213 // request. 214 type ListOptsBuilder interface { 215 ToVolumeListQuery() (string, error) 216 } 217 218 // ListOpts holds options for listing Volumes. It is passed to the volumes.List 219 // function. 220 type ListOpts struct { 221 // AllTenants will retrieve volumes of all tenants/projects. 222 AllTenants bool `q:"all_tenants"` 223 224 // Metadata will filter results based on specified metadata. 225 Metadata map[string]string `q:"metadata"` 226 227 // Name will filter by the specified volume name. 228 Name string `q:"name"` 229 230 // Status will filter by the specified status. 231 Status string `q:"status"` 232 233 // TenantID will filter by a specific tenant/project ID. 234 // Setting AllTenants is required for this. 235 TenantID string `q:"project_id"` 236 237 // Comma-separated list of sort keys and optional sort directions in the 238 // form of <key>[:<direction>]. 239 Sort string `q:"sort"` 240 241 // Requests a page size of items. 242 Limit int `q:"limit"` 243 244 // Used in conjunction with limit to return a slice of items. 245 Offset int `q:"offset"` 246 247 // The ID of the last-seen item. 248 Marker string `q:"marker"` 249 250 // Bootable will filter results based on whether they are bootable volumes 251 Bootable *bool `q:"bootable,omitempty"` 252 } 253 254 // ToVolumeListQuery formats a ListOpts into a query string. 255 func (opts ListOpts) ToVolumeListQuery() (string, error) { 256 q, err := gophercloud.BuildQueryString(opts) 257 return q.String(), err 258 } 259 260 // List returns Volumes optionally limited by the conditions provided in ListOpts. 261 func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { 262 url := listURL(client) 263 if opts != nil { 264 query, err := opts.ToVolumeListQuery() 265 if err != nil { 266 return pagination.Pager{Err: err} 267 } 268 url += query 269 } 270 271 return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page { 272 return VolumePage{pagination.LinkedPageBase{PageResult: r}} 273 }) 274 } 275 276 // UpdateOptsBuilder allows extensions to add additional parameters to the 277 // Update request. 278 type UpdateOptsBuilder interface { 279 ToVolumeUpdateMap() (map[string]any, error) 280 } 281 282 // UpdateOpts contain options for updating an existing Volume. This object is passed 283 // to the volumes.Update function. For more information about the parameters, see 284 // the Volume object. 285 type UpdateOpts struct { 286 Name *string `json:"name,omitempty"` 287 Description *string `json:"description,omitempty"` 288 Metadata map[string]string `json:"metadata,omitempty"` 289 } 290 291 // ToVolumeUpdateMap assembles a request body based on the contents of an 292 // UpdateOpts. 293 func (opts UpdateOpts) ToVolumeUpdateMap() (map[string]any, error) { 294 return gophercloud.BuildRequestBody(opts, "volume") 295 } 296 297 // Update will update the Volume with provided information. To extract the updated 298 // Volume from the response, call the Extract method on the UpdateResult. 299 func Update(ctx context.Context, client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) { 300 b, err := opts.ToVolumeUpdateMap() 301 if err != nil { 302 r.Err = err 303 return 304 } 305 resp, err := client.Put(ctx, updateURL(client, id), b, &r.Body, &gophercloud.RequestOpts{ 306 OkCodes: []int{200}, 307 }) 308 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 309 return 310 } 311 312 // AttachOptsBuilder allows extensions to add additional parameters to the 313 // Attach request. 314 type AttachOptsBuilder interface { 315 ToVolumeAttachMap() (map[string]any, error) 316 } 317 318 // AttachMode describes the attachment mode for volumes. 319 type AttachMode string 320 321 // These constants determine how a volume is attached. 322 const ( 323 ReadOnly AttachMode = "ro" 324 ReadWrite AttachMode = "rw" 325 ) 326 327 // AttachOpts contains options for attaching a Volume. 328 type AttachOpts struct { 329 // The mountpoint of this volume. 330 MountPoint string `json:"mountpoint,omitempty"` 331 332 // The nova instance ID, can't set simultaneously with HostName. 333 InstanceUUID string `json:"instance_uuid,omitempty"` 334 335 // The hostname of baremetal host, can't set simultaneously with InstanceUUID. 336 HostName string `json:"host_name,omitempty"` 337 338 // Mount mode of this volume. 339 Mode AttachMode `json:"mode,omitempty"` 340 } 341 342 // ToVolumeAttachMap assembles a request body based on the contents of a 343 // AttachOpts. 344 func (opts AttachOpts) ToVolumeAttachMap() (map[string]any, error) { 345 return gophercloud.BuildRequestBody(opts, "os-attach") 346 } 347 348 // Attach will attach a volume based on the values in AttachOpts. 349 func Attach(ctx context.Context, client *gophercloud.ServiceClient, id string, opts AttachOptsBuilder) (r AttachResult) { 350 b, err := opts.ToVolumeAttachMap() 351 if err != nil { 352 r.Err = err 353 return 354 } 355 resp, err := client.Post(ctx, actionURL(client, id), b, nil, &gophercloud.RequestOpts{ 356 OkCodes: []int{202}, 357 }) 358 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 359 return 360 } 361 362 // BeginDetaching will mark the volume as detaching. 363 func BeginDetaching(ctx context.Context, client *gophercloud.ServiceClient, id string) (r BeginDetachingResult) { 364 b := map[string]any{"os-begin_detaching": make(map[string]any)} 365 resp, err := client.Post(ctx, actionURL(client, id), b, nil, &gophercloud.RequestOpts{ 366 OkCodes: []int{202}, 367 }) 368 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 369 return 370 } 371 372 // DetachOptsBuilder allows extensions to add additional parameters to the 373 // Detach request. 374 type DetachOptsBuilder interface { 375 ToVolumeDetachMap() (map[string]any, error) 376 } 377 378 // DetachOpts contains options for detaching a Volume. 379 type DetachOpts struct { 380 // AttachmentID is the ID of the attachment between a volume and instance. 381 AttachmentID string `json:"attachment_id,omitempty"` 382 } 383 384 // ToVolumeDetachMap assembles a request body based on the contents of a 385 // DetachOpts. 386 func (opts DetachOpts) ToVolumeDetachMap() (map[string]any, error) { 387 return gophercloud.BuildRequestBody(opts, "os-detach") 388 } 389 390 // Detach will detach a volume based on volume ID. 391 func Detach(ctx context.Context, client *gophercloud.ServiceClient, id string, opts DetachOptsBuilder) (r DetachResult) { 392 b, err := opts.ToVolumeDetachMap() 393 if err != nil { 394 r.Err = err 395 return 396 } 397 resp, err := client.Post(ctx, actionURL(client, id), b, nil, &gophercloud.RequestOpts{ 398 OkCodes: []int{202}, 399 }) 400 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 401 return 402 } 403 404 // Reserve will reserve a volume based on volume ID. 405 func Reserve(ctx context.Context, client *gophercloud.ServiceClient, id string) (r ReserveResult) { 406 b := map[string]any{"os-reserve": make(map[string]any)} 407 resp, err := client.Post(ctx, actionURL(client, id), b, nil, &gophercloud.RequestOpts{ 408 OkCodes: []int{200, 201, 202}, 409 }) 410 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 411 return 412 } 413 414 // Unreserve will unreserve a volume based on volume ID. 415 func Unreserve(ctx context.Context, client *gophercloud.ServiceClient, id string) (r UnreserveResult) { 416 b := map[string]any{"os-unreserve": make(map[string]any)} 417 resp, err := client.Post(ctx, actionURL(client, id), b, nil, &gophercloud.RequestOpts{ 418 OkCodes: []int{200, 201, 202}, 419 }) 420 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 421 return 422 } 423 424 // InitializeConnectionOptsBuilder allows extensions to add additional parameters to the 425 // InitializeConnection request. 426 type InitializeConnectionOptsBuilder interface { 427 ToVolumeInitializeConnectionMap() (map[string]any, error) 428 } 429 430 // InitializeConnectionOpts hosts options for InitializeConnection. 431 // The fields are specific to the storage driver in use and the destination 432 // attachment. 433 type InitializeConnectionOpts struct { 434 IP string `json:"ip,omitempty"` 435 Host string `json:"host,omitempty"` 436 Initiator string `json:"initiator,omitempty"` 437 Wwpns []string `json:"wwpns,omitempty"` 438 Wwnns string `json:"wwnns,omitempty"` 439 Multipath *bool `json:"multipath,omitempty"` 440 Platform string `json:"platform,omitempty"` 441 OSType string `json:"os_type,omitempty"` 442 } 443 444 // ToVolumeInitializeConnectionMap assembles a request body based on the contents of a 445 // InitializeConnectionOpts. 446 func (opts InitializeConnectionOpts) ToVolumeInitializeConnectionMap() (map[string]any, error) { 447 b, err := gophercloud.BuildRequestBody(opts, "connector") 448 return map[string]any{"os-initialize_connection": b}, err 449 } 450 451 // InitializeConnection initializes an iSCSI connection by volume ID. 452 func InitializeConnection(ctx context.Context, client *gophercloud.ServiceClient, id string, opts InitializeConnectionOptsBuilder) (r InitializeConnectionResult) { 453 b, err := opts.ToVolumeInitializeConnectionMap() 454 if err != nil { 455 r.Err = err 456 return 457 } 458 resp, err := client.Post(ctx, actionURL(client, id), b, &r.Body, &gophercloud.RequestOpts{ 459 OkCodes: []int{200, 201, 202}, 460 }) 461 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 462 return 463 } 464 465 // TerminateConnectionOptsBuilder allows extensions to add additional parameters to the 466 // TerminateConnection request. 467 type TerminateConnectionOptsBuilder interface { 468 ToVolumeTerminateConnectionMap() (map[string]any, error) 469 } 470 471 // TerminateConnectionOpts hosts options for TerminateConnection. 472 type TerminateConnectionOpts struct { 473 IP string `json:"ip,omitempty"` 474 Host string `json:"host,omitempty"` 475 Initiator string `json:"initiator,omitempty"` 476 Wwpns []string `json:"wwpns,omitempty"` 477 Wwnns string `json:"wwnns,omitempty"` 478 Multipath *bool `json:"multipath,omitempty"` 479 Platform string `json:"platform,omitempty"` 480 OSType string `json:"os_type,omitempty"` 481 } 482 483 // ToVolumeTerminateConnectionMap assembles a request body based on the contents of a 484 // TerminateConnectionOpts. 485 func (opts TerminateConnectionOpts) ToVolumeTerminateConnectionMap() (map[string]any, error) { 486 b, err := gophercloud.BuildRequestBody(opts, "connector") 487 return map[string]any{"os-terminate_connection": b}, err 488 } 489 490 // TerminateConnection terminates an iSCSI connection by volume ID. 491 func TerminateConnection(ctx context.Context, client *gophercloud.ServiceClient, id string, opts TerminateConnectionOptsBuilder) (r TerminateConnectionResult) { 492 b, err := opts.ToVolumeTerminateConnectionMap() 493 if err != nil { 494 r.Err = err 495 return 496 } 497 resp, err := client.Post(ctx, actionURL(client, id), b, nil, &gophercloud.RequestOpts{ 498 OkCodes: []int{202}, 499 }) 500 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 501 return 502 } 503 504 // ExtendSizeOptsBuilder allows extensions to add additional parameters to the 505 // ExtendSize request. 506 type ExtendSizeOptsBuilder interface { 507 ToVolumeExtendSizeMap() (map[string]any, error) 508 } 509 510 // ExtendSizeOpts contains options for extending the size of an existing Volume. 511 // This object is passed to the volumes.ExtendSize function. 512 type ExtendSizeOpts struct { 513 // NewSize is the new size of the volume, in GB. 514 NewSize int `json:"new_size" required:"true"` 515 } 516 517 // ToVolumeExtendSizeMap assembles a request body based on the contents of an 518 // ExtendSizeOpts. 519 func (opts ExtendSizeOpts) ToVolumeExtendSizeMap() (map[string]any, error) { 520 return gophercloud.BuildRequestBody(opts, "os-extend") 521 } 522 523 // ExtendSize will extend the size of the volume based on the provided information. 524 // This operation does not return a response body. 525 func ExtendSize(ctx context.Context, client *gophercloud.ServiceClient, id string, opts ExtendSizeOptsBuilder) (r ExtendSizeResult) { 526 b, err := opts.ToVolumeExtendSizeMap() 527 if err != nil { 528 r.Err = err 529 return 530 } 531 resp, err := client.Post(ctx, actionURL(client, id), b, nil, &gophercloud.RequestOpts{ 532 OkCodes: []int{202}, 533 }) 534 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 535 return 536 } 537 538 // UploadImageOptsBuilder allows extensions to add additional parameters to the 539 // UploadImage request. 540 type UploadImageOptsBuilder interface { 541 ToVolumeUploadImageMap() (map[string]any, error) 542 } 543 544 // UploadImageOpts contains options for uploading a Volume to image storage. 545 type UploadImageOpts struct { 546 // Container format, may be bare, ofv, ova, etc. 547 ContainerFormat string `json:"container_format,omitempty"` 548 549 // Disk format, may be raw, qcow2, vhd, vdi, vmdk, etc. 550 DiskFormat string `json:"disk_format,omitempty"` 551 552 // The name of image that will be stored in glance. 553 ImageName string `json:"image_name,omitempty"` 554 555 // Force image creation, usable if volume attached to instance. 556 Force bool `json:"force,omitempty"` 557 558 // Visibility defines who can see/use the image. 559 // supported since 3.1 microversion 560 Visibility string `json:"visibility,omitempty"` 561 562 // whether the image is not deletable. 563 // supported since 3.1 microversion 564 Protected bool `json:"protected,omitempty"` 565 } 566 567 // ToVolumeUploadImageMap assembles a request body based on the contents of a 568 // UploadImageOpts. 569 func (opts UploadImageOpts) ToVolumeUploadImageMap() (map[string]any, error) { 570 return gophercloud.BuildRequestBody(opts, "os-volume_upload_image") 571 } 572 573 // UploadImage will upload an image based on the values in UploadImageOptsBuilder. 574 func UploadImage(ctx context.Context, client *gophercloud.ServiceClient, id string, opts UploadImageOptsBuilder) (r UploadImageResult) { 575 b, err := opts.ToVolumeUploadImageMap() 576 if err != nil { 577 r.Err = err 578 return 579 } 580 resp, err := client.Post(ctx, actionURL(client, id), b, &r.Body, &gophercloud.RequestOpts{ 581 OkCodes: []int{202}, 582 }) 583 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 584 return 585 } 586 587 // ForceDelete will delete the volume regardless of state. 588 func ForceDelete(ctx context.Context, client *gophercloud.ServiceClient, id string) (r ForceDeleteResult) { 589 resp, err := client.Post(ctx, actionURL(client, id), map[string]any{"os-force_delete": ""}, nil, nil) 590 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 591 return 592 } 593 594 // ImageMetadataOptsBuilder allows extensions to add additional parameters to the 595 // ImageMetadataRequest request. 596 type ImageMetadataOptsBuilder interface { 597 ToImageMetadataMap() (map[string]any, error) 598 } 599 600 // ImageMetadataOpts contains options for setting image metadata to a volume. 601 type ImageMetadataOpts struct { 602 // The image metadata to add to the volume as a set of metadata key and value pairs. 603 Metadata map[string]string `json:"metadata"` 604 } 605 606 // ToImageMetadataMap assembles a request body based on the contents of a 607 // ImageMetadataOpts. 608 func (opts ImageMetadataOpts) ToImageMetadataMap() (map[string]any, error) { 609 return gophercloud.BuildRequestBody(opts, "os-set_image_metadata") 610 } 611 612 // SetImageMetadata will set image metadata on a volume based on the values in ImageMetadataOptsBuilder. 613 func SetImageMetadata(ctx context.Context, client *gophercloud.ServiceClient, id string, opts ImageMetadataOptsBuilder) (r SetImageMetadataResult) { 614 b, err := opts.ToImageMetadataMap() 615 if err != nil { 616 r.Err = err 617 return 618 } 619 resp, err := client.Post(ctx, actionURL(client, id), b, &r.Body, &gophercloud.RequestOpts{ 620 OkCodes: []int{200}, 621 }) 622 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 623 return 624 } 625 626 // BootableOpts contains options for setting bootable status to a volume. 627 type BootableOpts struct { 628 // Enables or disables the bootable attribute. You can boot an instance from a bootable volume. 629 Bootable bool `json:"bootable"` 630 } 631 632 // ToBootableMap assembles a request body based on the contents of a 633 // BootableOpts. 634 func (opts BootableOpts) ToBootableMap() (map[string]any, error) { 635 return gophercloud.BuildRequestBody(opts, "os-set_bootable") 636 } 637 638 // SetBootable will set bootable status on a volume based on the values in BootableOpts 639 func SetBootable(ctx context.Context, client *gophercloud.ServiceClient, id string, opts BootableOpts) (r SetBootableResult) { 640 b, err := opts.ToBootableMap() 641 if err != nil { 642 r.Err = err 643 return 644 } 645 resp, err := client.Post(ctx, actionURL(client, id), b, nil, &gophercloud.RequestOpts{ 646 OkCodes: []int{200}, 647 }) 648 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 649 return 650 } 651 652 // MigrationPolicy type represents a migration_policy when changing types. 653 type MigrationPolicy string 654 655 // Supported attributes for MigrationPolicy attribute for changeType operations. 656 const ( 657 MigrationPolicyNever MigrationPolicy = "never" 658 MigrationPolicyOnDemand MigrationPolicy = "on-demand" 659 ) 660 661 // ChangeTypeOptsBuilder allows extensions to add additional parameters to the 662 // ChangeType request. 663 type ChangeTypeOptsBuilder interface { 664 ToVolumeChangeTypeMap() (map[string]any, error) 665 } 666 667 // ChangeTypeOpts contains options for changing the type of an existing Volume. 668 // This object is passed to the volumes.ChangeType function. 669 type ChangeTypeOpts struct { 670 // NewType is the name of the new volume type of the volume. 671 NewType string `json:"new_type" required:"true"` 672 673 // MigrationPolicy specifies if the volume should be migrated when it is 674 // re-typed. Possible values are "on-demand" or "never". If not specified, 675 // the default is "never". 676 MigrationPolicy MigrationPolicy `json:"migration_policy,omitempty"` 677 } 678 679 // ToVolumeChangeTypeMap assembles a request body based on the contents of an 680 // ChangeTypeOpts. 681 func (opts ChangeTypeOpts) ToVolumeChangeTypeMap() (map[string]any, error) { 682 return gophercloud.BuildRequestBody(opts, "os-retype") 683 } 684 685 // ChangeType will change the volume type of the volume based on the provided information. 686 // This operation does not return a response body. 687 func ChangeType(ctx context.Context, client *gophercloud.ServiceClient, id string, opts ChangeTypeOptsBuilder) (r ChangeTypeResult) { 688 b, err := opts.ToVolumeChangeTypeMap() 689 if err != nil { 690 r.Err = err 691 return 692 } 693 resp, err := client.Post(ctx, actionURL(client, id), b, nil, &gophercloud.RequestOpts{ 694 OkCodes: []int{202}, 695 }) 696 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 697 return 698 } 699 700 // ReImageOpts contains options for Re-image a volume. 701 type ReImageOpts struct { 702 // New image id 703 ImageID string `json:"image_id"` 704 // set true to re-image volumes in reserved state 705 ReImageReserved bool `json:"reimage_reserved"` 706 } 707 708 // ToReImageMap assembles a request body based on the contents of a ReImageOpts. 709 func (opts ReImageOpts) ToReImageMap() (map[string]any, error) { 710 return gophercloud.BuildRequestBody(opts, "os-reimage") 711 } 712 713 // ReImage will re-image a volume based on the values in ReImageOpts 714 func ReImage(ctx context.Context, client *gophercloud.ServiceClient, id string, opts ReImageOpts) (r ReImageResult) { 715 b, err := opts.ToReImageMap() 716 if err != nil { 717 r.Err = err 718 return 719 } 720 resp, err := client.Post(ctx, actionURL(client, id), b, nil, &gophercloud.RequestOpts{ 721 OkCodes: []int{202}, 722 }) 723 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 724 return 725 } 726 727 // ResetStatusOptsBuilder allows extensions to add additional parameters to the 728 // ResetStatus request. 729 type ResetStatusOptsBuilder interface { 730 ToResetStatusMap() (map[string]any, error) 731 } 732 733 // ResetStatusOpts contains options for resetting a Volume status. 734 // For more information about these parameters, please, refer to the Block Storage API V3, 735 // Volume Actions, ResetStatus volume documentation. 736 type ResetStatusOpts struct { 737 // Status is a volume status to reset to. 738 Status string `json:"status"` 739 // MigrationStatus is a volume migration status to reset to. 740 MigrationStatus string `json:"migration_status,omitempty"` 741 // AttachStatus is a volume attach status to reset to. 742 AttachStatus string `json:"attach_status,omitempty"` 743 } 744 745 // ToResetStatusMap assembles a request body based on the contents of a 746 // ResetStatusOpts. 747 func (opts ResetStatusOpts) ToResetStatusMap() (map[string]any, error) { 748 return gophercloud.BuildRequestBody(opts, "os-reset_status") 749 } 750 751 // ResetStatus will reset the existing volume status. ResetStatusResult contains only the error. 752 // To extract it, call the ExtractErr method on the ResetStatusResult. 753 func ResetStatus(ctx context.Context, client *gophercloud.ServiceClient, id string, opts ResetStatusOptsBuilder) (r ResetStatusResult) { 754 b, err := opts.ToResetStatusMap() 755 if err != nil { 756 r.Err = err 757 return 758 } 759 760 resp, err := client.Post(ctx, actionURL(client, id), b, nil, &gophercloud.RequestOpts{ 761 OkCodes: []int{202}, 762 }) 763 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 764 return 765 }