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  }