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