github.com/vnpaycloud-console/gophercloud/v2@v2.0.5/openstack/baremetal/v1/nodes/requests.go (about) 1 package nodes 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/vnpaycloud-console/gophercloud/v2" 8 "github.com/vnpaycloud-console/gophercloud/v2/pagination" 9 ) 10 11 // ListOptsBuilder allows extensions to add additional parameters to the 12 // List request. 13 type ListOptsBuilder interface { 14 ToNodeListQuery() (string, error) 15 ToNodeListDetailQuery() (string, error) 16 } 17 18 // Provision state reports the current provision state of the node, these are only used in filtering 19 type ProvisionState string 20 21 const ( 22 Enroll ProvisionState = "enroll" 23 Verifying ProvisionState = "verifying" 24 Manageable ProvisionState = "manageable" 25 Available ProvisionState = "available" 26 Active ProvisionState = "active" 27 DeployWait ProvisionState = "wait call-back" 28 Deploying ProvisionState = "deploying" 29 DeployFail ProvisionState = "deploy failed" 30 DeployDone ProvisionState = "deploy complete" 31 DeployHold ProvisionState = "deploy hold" 32 Deleting ProvisionState = "deleting" 33 Deleted ProvisionState = "deleted" 34 Cleaning ProvisionState = "cleaning" 35 CleanWait ProvisionState = "clean wait" 36 CleanFail ProvisionState = "clean failed" 37 CleanHold ProvisionState = "clean hold" 38 Error ProvisionState = "error" 39 Rebuild ProvisionState = "rebuild" 40 Inspecting ProvisionState = "inspecting" 41 InspectFail ProvisionState = "inspect failed" 42 InspectWait ProvisionState = "inspect wait" 43 Adopting ProvisionState = "adopting" 44 AdoptFail ProvisionState = "adopt failed" 45 Rescue ProvisionState = "rescue" 46 RescueFail ProvisionState = "rescue failed" 47 Rescuing ProvisionState = "rescuing" 48 UnrescueFail ProvisionState = "unrescue failed" 49 RescueWait ProvisionState = "rescue wait" 50 Unrescuing ProvisionState = "unrescuing" 51 Servicing ProvisionState = "servicing" 52 ServiceWait ProvisionState = "service wait" 53 ServiceFail ProvisionState = "service failed" 54 ServiceHold ProvisionState = "service hold" 55 ) 56 57 // TargetProvisionState is used when setting the provision state for a node. 58 type TargetProvisionState string 59 60 const ( 61 TargetActive TargetProvisionState = "active" 62 TargetDeleted TargetProvisionState = "deleted" 63 TargetManage TargetProvisionState = "manage" 64 TargetProvide TargetProvisionState = "provide" 65 TargetInspect TargetProvisionState = "inspect" 66 TargetAbort TargetProvisionState = "abort" 67 TargetClean TargetProvisionState = "clean" 68 TargetAdopt TargetProvisionState = "adopt" 69 TargetRescue TargetProvisionState = "rescue" 70 TargetUnrescue TargetProvisionState = "unrescue" 71 TargetRebuild TargetProvisionState = "rebuild" 72 TargetService TargetProvisionState = "service" 73 TargetUnhold TargetProvisionState = "unhold" 74 ) 75 76 const ( 77 StepHold string = "hold" 78 StepWait string = "wait" 79 StepPowerOn string = "power_on" 80 StepPowerOff string = "power_off" 81 StepReboot string = "reboot" 82 ) 83 84 // ListOpts allows the filtering and sorting of paginated collections through 85 // the API. Filtering is achieved by passing in struct field values that map to 86 // the node attributes you want to see returned. Marker and Limit are used 87 // for pagination. 88 type ListOpts struct { 89 // Filter the list by specific instance UUID 90 InstanceUUID string `q:"instance_uuid"` 91 92 // Filter the list by chassis UUID 93 ChassisUUID string `q:"chassis_uuid"` 94 95 // Filter the list by maintenance set to True or False 96 Maintenance bool `q:"maintenance"` 97 98 // Nodes which are, or are not, associated with an instance_uuid. 99 Associated bool `q:"associated"` 100 101 // Only return those with the specified provision_state. 102 ProvisionState ProvisionState `q:"provision_state"` 103 104 // Filter the list with the specified driver. 105 Driver string `q:"driver"` 106 107 // Filter the list with the specified resource class. 108 ResourceClass string `q:"resource_class"` 109 110 // Filter the list with the specified conductor_group. 111 ConductorGroup string `q:"conductor_group"` 112 113 // Filter the list with the specified fault. 114 Fault string `q:"fault"` 115 116 // One or more fields to be returned in the response. 117 Fields []string `q:"fields" format:"comma-separated"` 118 119 // Requests a page size of items. 120 Limit int `q:"limit"` 121 122 // The ID of the last-seen item. 123 Marker string `q:"marker"` 124 125 // Sorts the response by the requested sort direction. 126 SortDir string `q:"sort_dir"` 127 128 // Sorts the response by the this attribute value. 129 SortKey string `q:"sort_key"` 130 131 // A string or UUID of the tenant who owns the baremetal node. 132 Owner string `q:"owner"` 133 } 134 135 // ToNodeListQuery formats a ListOpts into a query string. 136 func (opts ListOpts) ToNodeListQuery() (string, error) { 137 q, err := gophercloud.BuildQueryString(opts) 138 return q.String(), err 139 } 140 141 // List makes a request against the API to list nodes accessible to you. 142 func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { 143 url := listURL(client) 144 if opts != nil { 145 query, err := opts.ToNodeListQuery() 146 if err != nil { 147 return pagination.Pager{Err: err} 148 } 149 url += query 150 } 151 return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page { 152 return NodePage{pagination.LinkedPageBase{PageResult: r}} 153 }) 154 } 155 156 // ToNodeListDetailQuery formats a ListOpts into a query string for the list details API. 157 func (opts ListOpts) ToNodeListDetailQuery() (string, error) { 158 // Detail endpoint can't filter by Fields 159 if len(opts.Fields) > 0 { 160 return "", fmt.Errorf("fields is not a valid option when getting a detailed listing of nodes") 161 } 162 163 q, err := gophercloud.BuildQueryString(opts) 164 return q.String(), err 165 } 166 167 // Return a list of bare metal Nodes with complete details. Some filtering is possible by passing in flags in ListOpts, 168 // but you cannot limit by the fields returned. 169 func ListDetail(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { 170 // This URL is deprecated. In the future, we should compare the microversion and if >= 1.43, hit the listURL 171 // with ListOpts{Detail: true,} 172 url := listDetailURL(client) 173 if opts != nil { 174 query, err := opts.ToNodeListDetailQuery() 175 if err != nil { 176 return pagination.Pager{Err: err} 177 } 178 url += query 179 } 180 return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page { 181 return NodePage{pagination.LinkedPageBase{PageResult: r}} 182 }) 183 } 184 185 // Get requests details on a single node, by ID. 186 func Get(ctx context.Context, client *gophercloud.ServiceClient, id string) (r GetResult) { 187 resp, err := client.Get(ctx, getURL(client, id), &r.Body, &gophercloud.RequestOpts{ 188 OkCodes: []int{200}, 189 }) 190 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 191 return 192 } 193 194 // CreateOptsBuilder allows extensions to add additional parameters to the 195 // Create request. 196 type CreateOptsBuilder interface { 197 ToNodeCreateMap() (map[string]any, error) 198 } 199 200 // CreateOpts specifies node creation parameters. 201 type CreateOpts struct { 202 // The interface to configure automated cleaning for a Node. 203 // Requires microversion 1.47 or later. 204 AutomatedClean *bool `json:"automated_clean,omitempty"` 205 206 // The BIOS interface for a Node, e.g. “redfish”. 207 BIOSInterface string `json:"bios_interface,omitempty"` 208 209 // The boot interface for a Node, e.g. “pxe”. 210 BootInterface string `json:"boot_interface,omitempty"` 211 212 // The conductor group for a node. Case-insensitive string up to 255 characters, containing a-z, 0-9, _, -, and .. 213 ConductorGroup string `json:"conductor_group,omitempty"` 214 215 // The console interface for a node, e.g. “no-console”. 216 ConsoleInterface string `json:"console_interface,omitempty"` 217 218 // The deploy interface for a node, e.g. “iscsi”. 219 DeployInterface string `json:"deploy_interface,omitempty"` 220 221 // All the metadata required by the driver to manage this Node. List of fields varies between drivers, and can 222 // be retrieved from the /v1/drivers/<DRIVER_NAME>/properties resource. 223 DriverInfo map[string]any `json:"driver_info,omitempty"` 224 225 // name of the driver used to manage this Node. 226 Driver string `json:"driver,omitempty"` 227 228 // A set of one or more arbitrary metadata key and value pairs. 229 Extra map[string]any `json:"extra,omitempty"` 230 231 // The firmware interface for a node, e.g. "redfish" 232 FirmwareInterface string `json:"firmware_interface,omitempty"` 233 234 // The interface used for node inspection, e.g. “no-inspect”. 235 InspectInterface string `json:"inspect_interface,omitempty"` 236 237 // Interface for out-of-band node management, e.g. “ipmitool”. 238 ManagementInterface string `json:"management_interface,omitempty"` 239 240 // Human-readable identifier for the Node resource. May be undefined. Certain words are reserved. 241 Name string `json:"name,omitempty"` 242 243 // Which Network Interface provider to use when plumbing the network connections for this Node. 244 NetworkInterface string `json:"network_interface,omitempty"` 245 246 // Interface used for performing power actions on the node, e.g. “ipmitool”. 247 PowerInterface string `json:"power_interface,omitempty"` 248 249 // Physical characteristics of this Node. Populated during inspection, if performed. Can be edited via the REST 250 // API at any time. 251 Properties map[string]any `json:"properties,omitempty"` 252 253 // Interface used for configuring RAID on this node, e.g. “no-raid”. 254 RAIDInterface string `json:"raid_interface,omitempty"` 255 256 // The interface used for node rescue, e.g. “no-rescue”. 257 RescueInterface string `json:"rescue_interface,omitempty"` 258 259 // A string which can be used by external schedulers to identify this Node as a unit of a specific type 260 // of resource. 261 ResourceClass string `json:"resource_class,omitempty"` 262 263 // Interface used for attaching and detaching volumes on this node, e.g. “cinder”. 264 StorageInterface string `json:"storage_interface,omitempty"` 265 266 // The UUID for the resource. 267 UUID string `json:"uuid,omitempty"` 268 269 // Interface for vendor-specific functionality on this node, e.g. “no-vendor”. 270 VendorInterface string `json:"vendor_interface,omitempty"` 271 272 // A string or UUID of the tenant who owns the baremetal node. 273 Owner string `json:"owner,omitempty"` 274 275 // Static network configuration to use during deployment and cleaning. 276 NetworkData map[string]any `json:"network_data,omitempty"` 277 278 // Whether disable_power_off is enabled or disabled on this node. 279 // Requires microversion 1.95 or later. 280 DisablePowerOff *bool `json:"disable_power_off,omitempty"` 281 } 282 283 // ToNodeCreateMap assembles a request body based on the contents of a CreateOpts. 284 func (opts CreateOpts) ToNodeCreateMap() (map[string]any, error) { 285 body, err := gophercloud.BuildRequestBody(opts, "") 286 if err != nil { 287 return nil, err 288 } 289 290 return body, nil 291 } 292 293 // Create requests a node to be created 294 func Create(ctx context.Context, client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) { 295 reqBody, err := opts.ToNodeCreateMap() 296 if err != nil { 297 r.Err = err 298 return 299 } 300 301 resp, err := client.Post(ctx, createURL(client), reqBody, &r.Body, nil) 302 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 303 return 304 } 305 306 type Patch interface { 307 ToNodeUpdateMap() (map[string]any, error) 308 } 309 310 // UpdateOpts is a slice of Patches used to update a node 311 type UpdateOpts []Patch 312 313 type UpdateOp string 314 315 const ( 316 ReplaceOp UpdateOp = "replace" 317 AddOp UpdateOp = "add" 318 RemoveOp UpdateOp = "remove" 319 ) 320 321 type UpdateOperation struct { 322 Op UpdateOp `json:"op" required:"true"` 323 Path string `json:"path" required:"true"` 324 Value any `json:"value,omitempty"` 325 } 326 327 func (opts UpdateOperation) ToNodeUpdateMap() (map[string]any, error) { 328 return gophercloud.BuildRequestBody(opts, "") 329 } 330 331 // Update requests that a node be updated 332 func Update(ctx context.Context, client *gophercloud.ServiceClient, id string, opts UpdateOpts) (r UpdateResult) { 333 body := make([]map[string]any, len(opts)) 334 for i, patch := range opts { 335 result, err := patch.ToNodeUpdateMap() 336 if err != nil { 337 r.Err = err 338 return 339 } 340 341 body[i] = result 342 } 343 resp, err := client.Patch(ctx, updateURL(client, id), body, &r.Body, &gophercloud.RequestOpts{ 344 OkCodes: []int{200}, 345 }) 346 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 347 return 348 } 349 350 // Delete requests that a node be removed 351 func Delete(ctx context.Context, client *gophercloud.ServiceClient, id string) (r DeleteResult) { 352 resp, err := client.Delete(ctx, deleteURL(client, id), nil) 353 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 354 return 355 } 356 357 // Request that Ironic validate whether the Node’s driver has enough information to manage the Node. This polls each 358 // interface on the driver, and returns the status of that interface. 359 func Validate(ctx context.Context, client *gophercloud.ServiceClient, id string) (r ValidateResult) { 360 resp, err := client.Get(ctx, validateURL(client, id), &r.Body, &gophercloud.RequestOpts{ 361 OkCodes: []int{200}, 362 }) 363 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 364 return 365 } 366 367 // Inject NMI (Non-Masking Interrupts) for the given Node. This feature can be used for hardware diagnostics, and 368 // actual support depends on a driver. 369 func InjectNMI(ctx context.Context, client *gophercloud.ServiceClient, id string) (r InjectNMIResult) { 370 resp, err := client.Put(ctx, injectNMIURL(client, id), map[string]string{}, nil, &gophercloud.RequestOpts{ 371 OkCodes: []int{204}, 372 }) 373 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 374 return 375 } 376 377 type BootDeviceOpts struct { 378 BootDevice string `json:"boot_device"` // e.g., 'pxe', 'disk', etc. 379 Persistent bool `json:"persistent"` // Whether this is one-time or not 380 } 381 382 // BootDeviceOptsBuilder allows extensions to add additional parameters to the 383 // SetBootDevice request. 384 type BootDeviceOptsBuilder interface { 385 ToBootDeviceMap() (map[string]any, error) 386 } 387 388 // ToBootDeviceSetMap assembles a request body based on the contents of a BootDeviceOpts. 389 func (opts BootDeviceOpts) ToBootDeviceMap() (map[string]any, error) { 390 body, err := gophercloud.BuildRequestBody(opts, "") 391 if err != nil { 392 return nil, err 393 } 394 395 return body, nil 396 } 397 398 // Set the boot device for the given Node, and set it persistently or for one-time boot. The exact behaviour 399 // of this depends on the hardware driver. 400 func SetBootDevice(ctx context.Context, client *gophercloud.ServiceClient, id string, bootDevice BootDeviceOptsBuilder) (r SetBootDeviceResult) { 401 reqBody, err := bootDevice.ToBootDeviceMap() 402 if err != nil { 403 r.Err = err 404 return 405 } 406 407 resp, err := client.Put(ctx, bootDeviceURL(client, id), reqBody, nil, &gophercloud.RequestOpts{ 408 OkCodes: []int{204}, 409 }) 410 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 411 return 412 } 413 414 // Get the current boot device for the given Node. 415 func GetBootDevice(ctx context.Context, client *gophercloud.ServiceClient, id string) (r BootDeviceResult) { 416 resp, err := client.Get(ctx, bootDeviceURL(client, id), &r.Body, &gophercloud.RequestOpts{ 417 OkCodes: []int{200}, 418 }) 419 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 420 return 421 } 422 423 // Retrieve the acceptable set of supported boot devices for a specific Node. 424 func GetSupportedBootDevices(ctx context.Context, client *gophercloud.ServiceClient, id string) (r SupportedBootDeviceResult) { 425 resp, err := client.Get(ctx, supportedBootDeviceURL(client, id), &r.Body, &gophercloud.RequestOpts{ 426 OkCodes: []int{200}, 427 }) 428 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 429 return 430 } 431 432 // An interface type for a deploy (or clean) step. 433 type StepInterface string 434 435 const ( 436 InterfaceBIOS StepInterface = "bios" 437 InterfaceDeploy StepInterface = "deploy" 438 InterfaceFirmware StepInterface = "firmware" 439 InterfaceManagement StepInterface = "management" 440 InterfacePower StepInterface = "power" 441 InterfaceRAID StepInterface = "raid" 442 ) 443 444 // A cleaning step has required keys ‘interface’ and ‘step’, and optional key ‘args’. If specified, 445 // the value for ‘args’ is a keyword variable argument dictionary that is passed to the cleaning step 446 // method. 447 type CleanStep struct { 448 Interface StepInterface `json:"interface" required:"true"` 449 Step string `json:"step" required:"true"` 450 Args map[string]any `json:"args,omitempty"` 451 } 452 453 // A service step looks the same as a cleaning step. 454 type ServiceStep = CleanStep 455 456 // A deploy step has required keys ‘interface’, ‘step’, ’args’ and ’priority’. 457 // The value for ‘args’ is a keyword variable argument dictionary that is passed to the deploy step 458 // method. Priority is a numeric priority at which the step is running. 459 type DeployStep struct { 460 Interface StepInterface `json:"interface" required:"true"` 461 Step string `json:"step" required:"true"` 462 Args map[string]any `json:"args" required:"true"` 463 Priority int `json:"priority" required:"true"` 464 } 465 466 // ProvisionStateOptsBuilder allows extensions to add additional parameters to the 467 // ChangeProvisionState request. 468 type ProvisionStateOptsBuilder interface { 469 ToProvisionStateMap() (map[string]any, error) 470 } 471 472 // Starting with Ironic API version 1.56, a configdrive may be a JSON object with structured data. 473 // Prior to this version, it must be a base64-encoded, gzipped ISO9660 image. 474 type ConfigDrive struct { 475 MetaData map[string]any `json:"meta_data,omitempty"` 476 NetworkData map[string]any `json:"network_data,omitempty"` 477 UserData any `json:"user_data,omitempty"` 478 } 479 480 // ProvisionStateOpts for a request to change a node's provision state. A config drive should be base64-encoded 481 // gzipped ISO9660 image. Deploy steps are supported starting with API 1.69. 482 type ProvisionStateOpts struct { 483 Target TargetProvisionState `json:"target" required:"true"` 484 ConfigDrive any `json:"configdrive,omitempty"` 485 CleanSteps []CleanStep `json:"clean_steps,omitempty"` 486 DeploySteps []DeployStep `json:"deploy_steps,omitempty"` 487 ServiceSteps []ServiceStep `json:"service_steps,omitempty"` 488 RescuePassword string `json:"rescue_password,omitempty"` 489 } 490 491 // ToProvisionStateMap assembles a request body based on the contents of a CreateOpts. 492 func (opts ProvisionStateOpts) ToProvisionStateMap() (map[string]any, error) { 493 body, err := gophercloud.BuildRequestBody(opts, "") 494 if err != nil { 495 return nil, err 496 } 497 498 return body, nil 499 } 500 501 // Request a change to the Node’s provision state. Acceptable target states depend on the Node’s current provision 502 // state. More detailed documentation of the Ironic State Machine is available in the developer docs. 503 func ChangeProvisionState(ctx context.Context, client *gophercloud.ServiceClient, id string, opts ProvisionStateOptsBuilder) (r ChangeStateResult) { 504 reqBody, err := opts.ToProvisionStateMap() 505 if err != nil { 506 r.Err = err 507 return 508 } 509 510 resp, err := client.Put(ctx, provisionStateURL(client, id), reqBody, nil, &gophercloud.RequestOpts{ 511 OkCodes: []int{202}, 512 }) 513 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 514 return 515 } 516 517 type TargetPowerState string 518 519 // TargetPowerState is used when changing the power state of a node. 520 const ( 521 PowerOn TargetPowerState = "power on" 522 PowerOff TargetPowerState = "power off" 523 Rebooting TargetPowerState = "rebooting" 524 SoftPowerOff TargetPowerState = "soft power off" 525 SoftRebooting TargetPowerState = "soft rebooting" 526 ) 527 528 // PowerStateOptsBuilder allows extensions to add additional parameters to the ChangePowerState request. 529 type PowerStateOptsBuilder interface { 530 ToPowerStateMap() (map[string]any, error) 531 } 532 533 // PowerStateOpts for a request to change a node's power state. 534 type PowerStateOpts struct { 535 Target TargetPowerState `json:"target" required:"true"` 536 Timeout int `json:"timeout,omitempty"` 537 } 538 539 // ToPowerStateMap assembles a request body based on the contents of a PowerStateOpts. 540 func (opts PowerStateOpts) ToPowerStateMap() (map[string]any, error) { 541 body, err := gophercloud.BuildRequestBody(opts, "") 542 if err != nil { 543 return nil, err 544 } 545 546 return body, nil 547 } 548 549 // Request to change a Node's power state. 550 func ChangePowerState(ctx context.Context, client *gophercloud.ServiceClient, id string, opts PowerStateOptsBuilder) (r ChangePowerStateResult) { 551 reqBody, err := opts.ToPowerStateMap() 552 if err != nil { 553 r.Err = err 554 return 555 } 556 557 resp, err := client.Put(ctx, powerStateURL(client, id), reqBody, nil, &gophercloud.RequestOpts{ 558 OkCodes: []int{202}, 559 }) 560 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 561 return 562 } 563 564 // This is the desired RAID configuration on the bare metal node. 565 type RAIDConfigOpts struct { 566 LogicalDisks []LogicalDisk `json:"logical_disks"` 567 } 568 569 // RAIDConfigOptsBuilder allows extensions to modify a set RAID config request. 570 type RAIDConfigOptsBuilder interface { 571 ToRAIDConfigMap() (map[string]any, error) 572 } 573 574 // RAIDLevel type is used to specify the RAID level for a logical disk. 575 type RAIDLevel string 576 577 const ( 578 RAID0 RAIDLevel = "0" 579 RAID1 RAIDLevel = "1" 580 RAID2 RAIDLevel = "2" 581 RAID5 RAIDLevel = "5" 582 RAID6 RAIDLevel = "6" 583 RAID10 RAIDLevel = "1+0" 584 RAID50 RAIDLevel = "5+0" 585 RAID60 RAIDLevel = "6+0" 586 JBOD RAIDLevel = "JBOD" 587 ) 588 589 // DiskType is used to specify the disk type for a logical disk, e.g. hdd or ssd. 590 type DiskType string 591 592 const ( 593 HDD DiskType = "hdd" 594 SSD DiskType = "ssd" 595 ) 596 597 // InterfaceType is used to specify the interface for a logical disk. 598 type InterfaceType string 599 600 const ( 601 SATA InterfaceType = "sata" 602 SCSI InterfaceType = "scsi" 603 SAS InterfaceType = "sas" 604 ) 605 606 type LogicalDisk struct { 607 // Size (Integer) of the logical disk to be created in GiB. If unspecified, "MAX" will be used. 608 SizeGB *int `json:"size_gb"` 609 610 // RAID level for the logical disk. 611 RAIDLevel RAIDLevel `json:"raid_level" required:"true"` 612 613 // Name of the volume. Should be unique within the Node. If not specified, volume name will be auto-generated. 614 VolumeName string `json:"volume_name,omitempty"` 615 616 // Set to true if this is the root volume. At most one logical disk can have this set to true. 617 IsRootVolume *bool `json:"is_root_volume,omitempty"` 618 619 // Set to true if this logical disk can share physical disks with other logical disks. 620 SharePhysicalDisks *bool `json:"share_physical_disks,omitempty"` 621 622 // If this is not specified, disk type will not be a criterion to find backing physical disks 623 DiskType DiskType `json:"disk_type,omitempty"` 624 625 // If this is not specified, interface type will not be a criterion to find backing physical disks. 626 InterfaceType InterfaceType `json:"interface_type,omitempty"` 627 628 // Integer, number of disks to use for the logical disk. Defaults to minimum number of disks required 629 // for the particular RAID level. 630 NumberOfPhysicalDisks int `json:"number_of_physical_disks,omitempty"` 631 632 // The name of the controller as read by the RAID interface. 633 Controller string `json:"controller,omitempty"` 634 635 // A list of physical disks to use as read by the RAID interface. 636 PhysicalDisks []any `json:"physical_disks,omitempty"` 637 } 638 639 func (opts RAIDConfigOpts) ToRAIDConfigMap() (map[string]any, error) { 640 body, err := gophercloud.BuildRequestBody(opts, "") 641 if err != nil { 642 return nil, err 643 } 644 645 if body["logical_disks"] != nil { 646 for _, v := range body["logical_disks"].([]any) { 647 if logicalDisk, ok := v.(map[string]any); ok { 648 if logicalDisk["size_gb"] == nil { 649 logicalDisk["size_gb"] = "MAX" 650 } 651 } 652 } 653 } 654 655 return body, nil 656 } 657 658 // Request to change a Node's RAID config. 659 func SetRAIDConfig(ctx context.Context, client *gophercloud.ServiceClient, id string, raidConfigOptsBuilder RAIDConfigOptsBuilder) (r ChangeStateResult) { 660 reqBody, err := raidConfigOptsBuilder.ToRAIDConfigMap() 661 if err != nil { 662 r.Err = err 663 return 664 } 665 666 resp, err := client.Put(ctx, raidConfigURL(client, id), reqBody, nil, &gophercloud.RequestOpts{ 667 OkCodes: []int{204}, 668 }) 669 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 670 return 671 } 672 673 // ListBIOSSettingsOptsBuilder allows extensions to add additional parameters to the 674 // ListBIOSSettings request. 675 type ListBIOSSettingsOptsBuilder interface { 676 ToListBIOSSettingsOptsQuery() (string, error) 677 } 678 679 // ListBIOSSettingsOpts defines query options that can be passed to ListBIOSettings 680 type ListBIOSSettingsOpts struct { 681 // Provide additional information for the BIOS Settings 682 Detail bool `q:"detail"` 683 684 // One or more fields to be returned in the response. 685 Fields []string `q:"fields" format:"comma-separated"` 686 } 687 688 // ToListBIOSSettingsOptsQuery formats a ListBIOSSettingsOpts into a query string 689 func (opts ListBIOSSettingsOpts) ToListBIOSSettingsOptsQuery() (string, error) { 690 if opts.Detail && len(opts.Fields) > 0 { 691 return "", fmt.Errorf("cannot have both fields and detail options for BIOS settings") 692 } 693 694 q, err := gophercloud.BuildQueryString(opts) 695 return q.String(), err 696 } 697 698 // Get the current BIOS Settings for the given Node. 699 // To use the opts requires microversion 1.74. 700 func ListBIOSSettings(ctx context.Context, client *gophercloud.ServiceClient, id string, opts ListBIOSSettingsOptsBuilder) (r ListBIOSSettingsResult) { 701 url := biosListSettingsURL(client, id) 702 if opts != nil { 703 704 query, err := opts.ToListBIOSSettingsOptsQuery() 705 if err != nil { 706 r.Err = err 707 return 708 } 709 url += query 710 } 711 712 resp, err := client.Get(ctx, url, &r.Body, &gophercloud.RequestOpts{ 713 OkCodes: []int{200}, 714 }) 715 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 716 return 717 } 718 719 // Get one BIOS Setting for the given Node. 720 func GetBIOSSetting(ctx context.Context, client *gophercloud.ServiceClient, id string, setting string) (r GetBIOSSettingResult) { 721 resp, err := client.Get(ctx, biosGetSettingURL(client, id, setting), &r.Body, &gophercloud.RequestOpts{ 722 OkCodes: []int{200}, 723 }) 724 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 725 return 726 } 727 728 // CallVendorPassthruOpts defines query options that can be passed to any VendorPassthruCall 729 type CallVendorPassthruOpts struct { 730 Method string `q:"method"` 731 } 732 733 // ToGetSubscriptionMap assembles a query based on the contents of a CallVendorPassthruOpts 734 func ToGetAllSubscriptionMap(opts CallVendorPassthruOpts) (string, error) { 735 q, err := gophercloud.BuildQueryString(opts) 736 return q.String(), err 737 } 738 739 // Get all vendor_passthru methods available for the given Node. 740 func GetVendorPassthruMethods(ctx context.Context, client *gophercloud.ServiceClient, id string) (r VendorPassthruMethodsResult) { 741 resp, err := client.Get(ctx, vendorPassthruMethodsURL(client, id), &r.Body, &gophercloud.RequestOpts{ 742 OkCodes: []int{200}, 743 }) 744 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 745 return 746 } 747 748 // Get all subscriptions available for the given Node. 749 func GetAllSubscriptions(ctx context.Context, client *gophercloud.ServiceClient, id string, method CallVendorPassthruOpts) (r GetAllSubscriptionsVendorPassthruResult) { 750 query, err := ToGetAllSubscriptionMap(method) 751 if err != nil { 752 r.Err = err 753 return 754 } 755 url := vendorPassthruCallURL(client, id) + query 756 resp, err := client.Get(ctx, url, &r.Body, &gophercloud.RequestOpts{ 757 OkCodes: []int{200}, 758 }) 759 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 760 return 761 } 762 763 // The desired subscription id on the baremetal node. 764 type GetSubscriptionOpts struct { 765 Id string `json:"id"` 766 } 767 768 // ToGetSubscriptionMap assembles a query based on the contents of CallVendorPassthruOpts and a request body based on the contents of a GetSubscriptionOpts 769 func ToGetSubscriptionMap(method CallVendorPassthruOpts, opts GetSubscriptionOpts) (string, map[string]any, error) { 770 q, err := gophercloud.BuildQueryString(method) 771 if err != nil { 772 return q.String(), nil, err 773 } 774 body, err := gophercloud.BuildRequestBody(opts, "") 775 if err != nil { 776 return q.String(), nil, err 777 } 778 779 return q.String(), body, nil 780 } 781 782 // Get a subscription on the given Node. 783 func GetSubscription(ctx context.Context, client *gophercloud.ServiceClient, id string, method CallVendorPassthruOpts, subscriptionOpts GetSubscriptionOpts) (r SubscriptionVendorPassthruResult) { 784 query, reqBody, err := ToGetSubscriptionMap(method, subscriptionOpts) 785 if err != nil { 786 r.Err = err 787 return 788 } 789 url := vendorPassthruCallURL(client, id) + query 790 resp, err := client.Get(ctx, url, &r.Body, &gophercloud.RequestOpts{ 791 JSONBody: reqBody, 792 OkCodes: []int{200}, 793 }) 794 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 795 return 796 } 797 798 // The desired subscription to be deleted from the baremetal node. 799 type DeleteSubscriptionOpts struct { 800 Id string `json:"id"` 801 } 802 803 // ToDeleteSubscriptionMap assembles a query based on the contents of CallVendorPassthruOpts and a request body based on the contents of a DeleteSubscriptionOpts 804 func ToDeleteSubscriptionMap(method CallVendorPassthruOpts, opts DeleteSubscriptionOpts) (string, map[string]any, error) { 805 q, err := gophercloud.BuildQueryString(method) 806 if err != nil { 807 return q.String(), nil, err 808 } 809 body, err := gophercloud.BuildRequestBody(opts, "") 810 if err != nil { 811 return q.String(), nil, err 812 } 813 return q.String(), body, nil 814 } 815 816 // Delete a subscription on the given node. 817 func DeleteSubscription(ctx context.Context, client *gophercloud.ServiceClient, id string, method CallVendorPassthruOpts, subscriptionOpts DeleteSubscriptionOpts) (r DeleteSubscriptionVendorPassthruResult) { 818 query, reqBody, err := ToDeleteSubscriptionMap(method, subscriptionOpts) 819 if err != nil { 820 r.Err = err 821 return 822 } 823 url := vendorPassthruCallURL(client, id) + query 824 resp, err := client.Delete(ctx, url, &gophercloud.RequestOpts{ 825 JSONBody: reqBody, 826 OkCodes: []int{200, 202, 204}, 827 }) 828 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 829 return r 830 } 831 832 // The desired subscription to be created from the baremetal node. 833 type CreateSubscriptionOpts struct { 834 Destination string `json:"Destination"` 835 EventTypes []string `json:"EventTypes,omitempty"` 836 HttpHeaders []map[string]string `json:"HttpHeaders,omitempty"` 837 Context string `json:"Context,omitempty"` 838 Protocol string `json:"Protocol,omitempty"` 839 } 840 841 // ToCreateSubscriptionMap assembles a query based on the contents of CallVendorPassthruOpts and a request body based on the contents of a CreateSubscriptionOpts 842 func ToCreateSubscriptionMap(method CallVendorPassthruOpts, opts CreateSubscriptionOpts) (string, map[string]any, error) { 843 q, err := gophercloud.BuildQueryString(method) 844 if err != nil { 845 return q.String(), nil, err 846 } 847 body, err := gophercloud.BuildRequestBody(opts, "") 848 if err != nil { 849 return q.String(), nil, err 850 } 851 return q.String(), body, nil 852 } 853 854 // Creates a subscription on the given node. 855 func CreateSubscription(ctx context.Context, client *gophercloud.ServiceClient, id string, method CallVendorPassthruOpts, subscriptionOpts CreateSubscriptionOpts) (r SubscriptionVendorPassthruResult) { 856 query, reqBody, err := ToCreateSubscriptionMap(method, subscriptionOpts) 857 if err != nil { 858 r.Err = err 859 return 860 } 861 url := vendorPassthruCallURL(client, id) + query 862 resp, err := client.Post(ctx, url, reqBody, &r.Body, &gophercloud.RequestOpts{ 863 OkCodes: []int{200}, 864 }) 865 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 866 return r 867 } 868 869 // MaintenanceOpts for a request to set the node's maintenance mode. 870 type MaintenanceOpts struct { 871 Reason string `json:"reason,omitempty"` 872 } 873 874 // MaintenanceOptsBuilder allows extensions to add additional parameters to the SetMaintenance request. 875 type MaintenanceOptsBuilder interface { 876 ToMaintenanceMap() (map[string]any, error) 877 } 878 879 // ToMaintenanceMap assembles a request body based on the contents of a MaintenanceOpts. 880 func (opts MaintenanceOpts) ToMaintenanceMap() (map[string]any, error) { 881 body, err := gophercloud.BuildRequestBody(opts, "") 882 if err != nil { 883 return nil, err 884 } 885 886 return body, nil 887 } 888 889 // Request to set the Node's maintenance mode. 890 func SetMaintenance(ctx context.Context, client *gophercloud.ServiceClient, id string, opts MaintenanceOptsBuilder) (r SetMaintenanceResult) { 891 reqBody, err := opts.ToMaintenanceMap() 892 if err != nil { 893 r.Err = err 894 return 895 } 896 897 resp, err := client.Put(ctx, maintenanceURL(client, id), reqBody, nil, &gophercloud.RequestOpts{ 898 OkCodes: []int{202}, 899 }) 900 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 901 return 902 } 903 904 // Request to unset the Node's maintenance mode. 905 func UnsetMaintenance(ctx context.Context, client *gophercloud.ServiceClient, id string) (r SetMaintenanceResult) { 906 resp, err := client.Delete(ctx, maintenanceURL(client, id), &gophercloud.RequestOpts{ 907 OkCodes: []int{202}, 908 }) 909 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 910 return 911 } 912 913 // GetInventory return stored data from successful inspection. 914 func GetInventory(ctx context.Context, client *gophercloud.ServiceClient, id string) (r InventoryResult) { 915 resp, err := client.Get(ctx, inventoryURL(client, id), &r.Body, &gophercloud.RequestOpts{ 916 OkCodes: []int{200}, 917 }) 918 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 919 return 920 } 921 922 // ListFirmware return the list of Firmware components for the given Node. 923 func ListFirmware(ctx context.Context, client *gophercloud.ServiceClient, id string) (r ListFirmwareResult) { 924 resp, err := client.Get(ctx, firmwareListURL(client, id), &r.Body, &gophercloud.RequestOpts{ 925 OkCodes: []int{200}, 926 }) 927 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 928 return 929 } 930 931 type VirtualMediaDeviceType string 932 933 const ( 934 VirtualMediaDisk VirtualMediaDeviceType = "disk" 935 VirtualMediaCD VirtualMediaDeviceType = "cdrom" 936 VirtualMediaFloppy VirtualMediaDeviceType = "floppy" 937 ) 938 939 type ImageDownloadSource string 940 941 const ( 942 ImageDownloadSourceHTTP ImageDownloadSource = "http" 943 ImageDownloadSourceLocal ImageDownloadSource = "local" 944 ImageDownloadSourceSwift ImageDownloadSource = "swift" 945 ) 946 947 // The desired virtual media attachment on the baremetal node. 948 type AttachVirtualMediaOpts struct { 949 DeviceType VirtualMediaDeviceType `json:"device_type"` 950 ImageURL string `json:"image_url"` 951 ImageDownloadSource ImageDownloadSource `json:"image_download_source,omitempty"` 952 } 953 954 type AttachVirtualMediaOptsBuilder interface { 955 ToAttachVirtualMediaMap() (map[string]any, error) 956 } 957 958 func (opts AttachVirtualMediaOpts) ToAttachVirtualMediaMap() (map[string]any, error) { 959 return gophercloud.BuildRequestBody(opts, "") 960 } 961 962 // Request to attach a virtual media device to the Node. 963 func AttachVirtualMedia(ctx context.Context, client *gophercloud.ServiceClient, id string, opts AttachVirtualMediaOptsBuilder) (r VirtualMediaAttachResult) { 964 reqBody, err := opts.ToAttachVirtualMediaMap() 965 if err != nil { 966 r.Err = err 967 return 968 } 969 970 resp, err := client.Post(ctx, virtualMediaURL(client, id), reqBody, nil, &gophercloud.RequestOpts{ 971 OkCodes: []int{204}, 972 }) 973 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 974 return 975 } 976 977 // The desired virtual media detachment on the baremetal node. 978 type DetachVirtualMediaOpts struct { 979 DeviceTypes []VirtualMediaDeviceType `q:"device_types" format:"comma-separated"` 980 } 981 982 type DetachVirtualMediaOptsBuilder interface { 983 ToDetachVirtualMediaOptsQuery() (string, error) 984 } 985 986 func (opts DetachVirtualMediaOpts) ToDetachVirtualMediaOptsQuery() (string, error) { 987 q, err := gophercloud.BuildQueryString(opts) 988 return q.String(), err 989 } 990 991 // Request to detach a virtual media device from the Node. 992 func DetachVirtualMedia(ctx context.Context, client *gophercloud.ServiceClient, id string, opts DetachVirtualMediaOptsBuilder) (r VirtualMediaDetachResult) { 993 query, err := opts.ToDetachVirtualMediaOptsQuery() 994 if err != nil { 995 r.Err = err 996 return 997 } 998 999 resp, err := client.Delete(ctx, virtualMediaURL(client, id)+query, &gophercloud.RequestOpts{ 1000 OkCodes: []int{204}, 1001 }) 1002 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 1003 return 1004 }