...

Source file src/github.com/LINBIT/golinstor/client/resource.go

Documentation: github.com/LINBIT/golinstor/client

     1  // A REST client to interact with LINSTOR's REST API
     2  // Copyright (C) LINBIT HA-Solutions GmbH
     3  // All Rights Reserved.
     4  // Author: Roland Kammerer <roland.kammerer@linbit.com>
     5  //
     6  // Licensed under the Apache License, Version 2.0 (the "License"); you may
     7  // not use this file except in compliance with the License. You may obtain
     8  // a copy of the License at
     9  //
    10  // http://www.apache.org/licenses/LICENSE-2.0
    11  //
    12  // Unless required by applicable law or agreed to in writing, software
    13  // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    14  // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    15  // License for the specific language governing permissions and limitations
    16  // under the License.
    17  
    18  package client
    19  
    20  import (
    21  	"context"
    22  	"encoding/json"
    23  	"fmt"
    24  	"strconv"
    25  
    26  	"github.com/google/go-querystring/query"
    27  
    28  	"github.com/LINBIT/golinstor/devicelayerkind"
    29  	"github.com/LINBIT/golinstor/snapshotshipstatus"
    30  )
    31  
    32  // ResourceService is a struct which contains the pointer of the client
    33  type ResourceService struct {
    34  	client *Client
    35  }
    36  
    37  // copy & paste from generated code
    38  
    39  // Resource is a struct which holds the information of a resource
    40  type Resource struct {
    41  	Name     string `json:"name,omitempty"`
    42  	NodeName string `json:"node_name,omitempty"`
    43  	// A string to string property map.
    44  	Props       map[string]string `json:"props,omitempty"`
    45  	Flags       []string          `json:"flags,omitempty"`
    46  	LayerObject *ResourceLayer    `json:"layer_object,omitempty"`
    47  	State       *ResourceState    `json:"state,omitempty"`
    48  	// unique object id
    49  	Uuid string `json:"uuid,omitempty"`
    50  	// milliseconds since unix epoch in UTC
    51  	CreateTimestamp *TimeStampMs `json:"create_timestamp,omitempty"`
    52  }
    53  
    54  type ResourceWithVolumes struct {
    55  	Resource
    56  	// milliseconds since unix epoch in UTC
    57  	CreateTimestamp *TimeStampMs `json:"create_timestamp,omitempty"`
    58  	Volumes         []Volume     `json:"volumes,omitempty"`
    59  	// shared space name of the data storage pool of the first volume of
    60  	// the resource or empty if data storage pool is not shared
    61  	SharedName string `json:"shared_name,omitempty"`
    62  }
    63  
    64  type ResourceDefinitionModify struct {
    65  	// drbd port for resources
    66  	DrbdPort int32 `json:"drbd_port,omitempty"`
    67  	// drbd peer slot number
    68  	DrbdPeerSlots int32                             `json:"drbd_peer_slots,omitempty"`
    69  	LayerStack    []devicelayerkind.DeviceLayerKind `json:"layer_stack,omitempty"`
    70  	// change resource group to the given group name
    71  	ResourceGroup string `json:"resource_group,omitempty"`
    72  	GenericPropsModify
    73  }
    74  
    75  // ResourceCreate is a struct where the properties of a resource are stored to create it
    76  type ResourceCreate struct {
    77  	Resource   Resource                          `json:"resource,omitempty"`
    78  	LayerList  []devicelayerkind.DeviceLayerKind `json:"layer_list,omitempty"`
    79  	DrbdNodeId int32                             `json:"drbd_node_id,omitempty"`
    80  }
    81  
    82  // ResourceLayer is a struct to store layer-information abour a resource
    83  type ResourceLayer struct {
    84  	Children           []ResourceLayer                 `json:"children,omitempty"`
    85  	ResourceNameSuffix string                          `json:"resource_name_suffix,omitempty"`
    86  	Type               devicelayerkind.DeviceLayerKind `json:"type,omitempty"`
    87  	Drbd               *DrbdResource                   `json:"drbd,omitempty"`
    88  	Luks               *LuksResource                   `json:"luks,omitempty"`
    89  	Storage            *StorageResource                `json:"storage,omitempty"`
    90  	Nvme               *NvmeResource                   `json:"nvme,omitempty"`
    91  	Writecache         *WritecacheResource             `json:"writecache,omitempty"`
    92  	Cache              *CacheResource                  `json:"cache,omitempty"`
    93  	BCache             *BCacheResource                 `json:"bcache,omitempty"`
    94  }
    95  
    96  type WritecacheResource struct {
    97  	WritecacheVolumes []WritecacheVolume `json:"writecache_volumes,omitempty"`
    98  }
    99  
   100  type WritecacheVolume struct {
   101  	VolumeNumber int32 `json:"volume_number,omitempty"`
   102  	// block device path
   103  	DevicePath string `json:"device_path,omitempty"`
   104  	// block device path used as cache device
   105  	DevicePathCache  string `json:"device_path_cache,omitempty"`
   106  	AllocatedSizeKib int64  `json:"allocated_size_kib,omitempty"`
   107  	UsableSizeKib    int64  `json:"usable_size_kib,omitempty"`
   108  	// String describing current volume state
   109  	DiskState string `json:"disk_state,omitempty"`
   110  }
   111  
   112  type BCacheResource struct {
   113  	BCacheVolumes []BCacheVolume `json:"bcache_volumes,omitempty"`
   114  }
   115  
   116  type BCacheVolume struct {
   117  	VolumeNumber int32 `json:"volume_number,omitempty"`
   118  	// block device path
   119  	DevicePath string `json:"device_path,omitempty"`
   120  	// block device path used as cache device
   121  	DevicePathCache  string `json:"device_path_cache,omitempty"`
   122  	AllocatedSizeKib int64  `json:"allocated_size_kib,omitempty"`
   123  	UsableSizeKib    int64  `json:"usable_size_kib,omitempty"`
   124  	// String describing current volume state
   125  	DiskState string `json:"disk_state,omitempty"`
   126  }
   127  
   128  // DrbdResource is a struct used to give linstor drbd properties for a resource
   129  type DrbdResource struct {
   130  	DrbdResourceDefinition DrbdResourceDefinitionLayer `json:"drbd_resource_definition,omitempty"`
   131  	NodeId                 int32                       `json:"node_id,omitempty"`
   132  	PeerSlots              int32                       `json:"peer_slots,omitempty"`
   133  	AlStripes              int32                       `json:"al_stripes,omitempty"`
   134  	AlSize                 int64                       `json:"al_size,omitempty"`
   135  	Flags                  []string                    `json:"flags,omitempty"`
   136  	DrbdVolumes            []DrbdVolume                `json:"drbd_volumes,omitempty"`
   137  	Connections            map[string]DrbdConnection   `json:"connections,omitempty"`
   138  	PromotionScore         int32                       `json:"promotion_score,omitempty"`
   139  	MayPromote             bool                        `json:"may_promote,omitempty"`
   140  }
   141  
   142  // DrbdConnection is a struct representing the DRBD connection status
   143  type DrbdConnection struct {
   144  	Connected bool `json:"connected,omitempty"`
   145  	// DRBD connection status
   146  	Message string `json:"message,omitempty"`
   147  }
   148  
   149  // DrbdVolume is a struct for linstor to get inormation about a drbd-volume
   150  type DrbdVolume struct {
   151  	DrbdVolumeDefinition DrbdVolumeDefinition `json:"drbd_volume_definition,omitempty"`
   152  	// drbd device path e.g. '/dev/drbd1000'
   153  	DevicePath string `json:"device_path,omitempty"`
   154  	// block device used by drbd
   155  	BackingDevice    string `json:"backing_device,omitempty"`
   156  	MetaDisk         string `json:"meta_disk,omitempty"`
   157  	AllocatedSizeKib int64  `json:"allocated_size_kib,omitempty"`
   158  	UsableSizeKib    int64  `json:"usable_size_kib,omitempty"`
   159  	// String describing current volume state
   160  	DiskState string `json:"disk_state,omitempty"`
   161  	// Storage pool name used for external meta data; null for internal
   162  	ExtMetaStorPool string `json:"ext_meta_stor_pool,omitempty"`
   163  }
   164  
   165  // LuksResource is a struct to store storage-volumes for a luks-resource
   166  type LuksResource struct {
   167  	StorageVolumes []LuksVolume `json:"storage_volumes,omitempty"`
   168  }
   169  
   170  // LuksVolume is a struct used for information about a luks-volume
   171  type LuksVolume struct {
   172  	VolumeNumber int32 `json:"volume_number,omitempty"`
   173  	// block device path
   174  	DevicePath string `json:"device_path,omitempty"`
   175  	// block device used by luks
   176  	BackingDevice    string `json:"backing_device,omitempty"`
   177  	AllocatedSizeKib int64  `json:"allocated_size_kib,omitempty"`
   178  	UsableSizeKib    int64  `json:"usable_size_kib,omitempty"`
   179  	// String describing current volume state
   180  	DiskState string `json:"disk_state,omitempty"`
   181  	Opened    bool   `json:"opened,omitempty"`
   182  }
   183  
   184  // StorageResource is a struct which contains the storage-volumes for a storage-resource
   185  type StorageResource struct {
   186  	StorageVolumes []StorageVolume `json:"storage_volumes,omitempty"`
   187  }
   188  
   189  // StorageVolume is a struct to store standard poperties of a Volume
   190  type StorageVolume struct {
   191  	VolumeNumber int32 `json:"volume_number,omitempty"`
   192  	// block device path
   193  	DevicePath       string `json:"device_path,omitempty"`
   194  	AllocatedSizeKib int64  `json:"allocated_size_kib,omitempty"`
   195  	UsableSizeKib    int64  `json:"usable_size_kib,omitempty"`
   196  	// String describing current volume state
   197  	DiskState string `json:"disk_state,omitempty"`
   198  }
   199  
   200  type NvmeResource struct {
   201  	NvmeVolumes []NvmeVolume `json:"nvme_volumes,omitempty"`
   202  }
   203  
   204  type NvmeVolume struct {
   205  	VolumeNumber int32 `json:"volume_number,omitempty"`
   206  	// block device path
   207  	DevicePath string `json:"device_path,omitempty"`
   208  	// block device used by nvme
   209  	BackingDevice    string `json:"backing_device,omitempty"`
   210  	AllocatedSizeKib int64  `json:"allocated_size_kib,omitempty"`
   211  	UsableSizeKib    int64  `json:"usable_size_kib,omitempty"`
   212  	// String describing current volume state
   213  	DiskState string `json:"disk_state,omitempty"`
   214  }
   215  
   216  // ResourceState is a struct for getting the status of a resource
   217  type ResourceState struct {
   218  	InUse *bool `json:"in_use,omitempty"`
   219  }
   220  
   221  // Volume is a struct which holds the information about a linstor-volume
   222  type Volume struct {
   223  	VolumeNumber     int32        `json:"volume_number,omitempty"`
   224  	StoragePoolName  string       `json:"storage_pool_name,omitempty"`
   225  	ProviderKind     ProviderKind `json:"provider_kind,omitempty"`
   226  	DevicePath       string       `json:"device_path,omitempty"`
   227  	AllocatedSizeKib int64        `json:"allocated_size_kib,omitempty"`
   228  	UsableSizeKib    int64        `json:"usable_size_kib,omitempty"`
   229  	// A string to string property map.
   230  	Props         map[string]string `json:"props,omitempty"`
   231  	Flags         []string          `json:"flags,omitempty"`
   232  	State         VolumeState       `json:"state,omitempty"`
   233  	LayerDataList []VolumeLayer     `json:"layer_data_list,omitempty"`
   234  	// unique object id
   235  	Uuid    string      `json:"uuid,omitempty"`
   236  	Reports []ApiCallRc `json:"reports,omitempty"`
   237  }
   238  
   239  // VolumeLayer is a struct for storing the layer-properties of a linstor-volume
   240  type VolumeLayer struct {
   241  	Type devicelayerkind.DeviceLayerKind                                                         `json:"type,omitempty"`
   242  	Data OneOfDrbdVolumeLuksVolumeStorageVolumeNvmeVolumeWritecacheVolumeCacheVolumeBCacheVolume `json:"data,omitempty"`
   243  }
   244  
   245  // VolumeState is a struct which contains the disk-state for volume
   246  type VolumeState struct {
   247  	DiskState string `json:"disk_state,omitempty"`
   248  }
   249  
   250  // AutoPlaceRequest is a struct to store the paramters for the linstor auto-place command
   251  type AutoPlaceRequest struct {
   252  	DisklessOnRemaining bool                              `json:"diskless_on_remaining,omitempty"`
   253  	SelectFilter        AutoSelectFilter                  `json:"select_filter,omitempty"`
   254  	LayerList           []devicelayerkind.DeviceLayerKind `json:"layer_list,omitempty"`
   255  }
   256  
   257  // AutoSelectFilter is a struct used to have information about the auto-select function
   258  type AutoSelectFilter struct {
   259  	PlaceCount              int32    `json:"place_count,omitempty"`
   260  	AdditionalPlaceCount    int32    `json:"additional_place_count,omitempty"`
   261  	NodeNameList            []string `json:"node_name_list,omitempty"`
   262  	StoragePool             string   `json:"storage_pool,omitempty"`
   263  	StoragePoolList         []string `json:"storage_pool_list,omitempty"`
   264  	StoragePoolDisklessList []string `json:"storage_pool_diskless_list,omitempty"`
   265  	NotPlaceWithRsc         []string `json:"not_place_with_rsc,omitempty"`
   266  	NotPlaceWithRscRegex    string   `json:"not_place_with_rsc_regex,omitempty"`
   267  	ReplicasOnSame          []string `json:"replicas_on_same,omitempty"`
   268  	ReplicasOnDifferent     []string `json:"replicas_on_different,omitempty"`
   269  	LayerStack              []string `json:"layer_stack,omitempty"`
   270  	ProviderList            []string `json:"provider_list,omitempty"`
   271  	DisklessOnRemaining     bool     `json:"diskless_on_remaining,omitempty"`
   272  	DisklessType            string   `json:"diskless_type,omitempty"`
   273  	Overprovision           *float64 `json:"overprovision,omitempty"`
   274  }
   275  
   276  // ResourceConnection is a struct which holds information about a connection between to nodes
   277  type ResourceConnection struct {
   278  	// source node of the connection
   279  	NodeA string `json:"node_a,omitempty"`
   280  	// target node of the connection
   281  	NodeB string `json:"node_b,omitempty"`
   282  	// A string to string property map.
   283  	Props map[string]string `json:"props,omitempty"`
   284  	Flags []string          `json:"flags,omitempty"`
   285  	Port  int32             `json:"port,omitempty"`
   286  }
   287  
   288  // Snapshot is a struct for information about a snapshot
   289  type Snapshot struct {
   290  	Name         string   `json:"name,omitempty"`
   291  	ResourceName string   `json:"resource_name,omitempty"`
   292  	Nodes        []string `json:"nodes,omitempty"`
   293  	// A string to string property map.
   294  	Props             map[string]string          `json:"props,omitempty"`
   295  	Flags             []string                   `json:"flags,omitempty"`
   296  	VolumeDefinitions []SnapshotVolumeDefinition `json:"volume_definitions,omitempty"`
   297  	// unique object id
   298  	Uuid      string         `json:"uuid,omitempty"`
   299  	Snapshots []SnapshotNode `json:"snapshots,omitempty"`
   300  }
   301  
   302  // SnapshotNode Actual snapshot data from a node
   303  type SnapshotNode struct {
   304  	// Snapshot name this snapshots belongs to
   305  	SnapshotName string `json:"snapshot_name,omitempty"`
   306  	// Node name where this snapshot was taken
   307  	NodeName string `json:"node_name,omitempty"`
   308  	// milliseconds since unix epoch in UTC
   309  	CreateTimestamp *TimeStampMs `json:"create_timestamp,omitempty"`
   310  	Flags           []string     `json:"flags,omitempty"`
   311  	// unique object id
   312  	Uuid string `json:"uuid,omitempty"`
   313  	// SnapshotVolumes holds per-volume information about snapshots on this node.
   314  	SnapshotVolumes []SnapshotVolumeNode `json:"snapshot_volumes,omitempty"`
   315  }
   316  
   317  type SnapshotVolumeNode struct {
   318  	// unique object id
   319  	Uuid string `json:"uuid,omitempty"`
   320  	// Volume number of the snapshot
   321  	VlmNr int32 `json:"vlm_nr,omitempty"`
   322  	// A string to string property map.
   323  	Props map[string]string `json:"props,omitempty"`
   324  	// Optional state for the given snapshot
   325  	State string `json:"state,omitempty"`
   326  }
   327  
   328  // SnapshotShipping struct for SnapshotShipping
   329  type SnapshotShipping struct {
   330  	// Node where to ship the snapshot from
   331  	FromNode string `json:"from_node"`
   332  	// NetInterface of the source node
   333  	FromNic string `json:"from_nic,omitempty"`
   334  	// Node where to ship the snapshot
   335  	ToNode string `json:"to_node"`
   336  	// NetInterface of the destination node
   337  	ToNic string `json:"to_nic,omitempty"`
   338  }
   339  
   340  // SnapshotShippingStatus struct for SnapshotShippingStatus
   341  type SnapshotShippingStatus struct {
   342  	Snapshot     Snapshot                              `json:"snapshot,omitempty"`
   343  	FromNodeName string                                `json:"from_node_name,omitempty"`
   344  	ToNodeName   string                                `json:"to_node_name,omitempty"`
   345  	Status       snapshotshipstatus.SnapshotShipStatus `json:"status,omitempty"`
   346  }
   347  
   348  // SnapshotVolumeDefinition is a struct to store the properties of a volume from a snapshot
   349  type SnapshotVolumeDefinition struct {
   350  	VolumeNumber int32 `json:"volume_number,omitempty"`
   351  	// Volume size in KiB
   352  	SizeKib uint64 `json:"size_kib,omitempty"`
   353  }
   354  
   355  // SnapshotRestore is a struct used to hold the information about where a Snapshot has to be restored
   356  type SnapshotRestore struct {
   357  	// Resource where to restore the snapshot
   358  	ToResource string `json:"to_resource"`
   359  	// List of nodes where to place the restored snapshot
   360  	Nodes []string `json:"nodes,omitempty"`
   361  }
   362  
   363  type DrbdProxyModify struct {
   364  	// Compression type used by the proxy.
   365  	CompressionType string `json:"compression_type,omitempty"`
   366  	// A string to string property map.
   367  	CompressionProps map[string]string `json:"compression_props,omitempty"`
   368  	GenericPropsModify
   369  }
   370  
   371  // Candidate struct for Candidate
   372  type Candidate struct {
   373  	StoragePool string `json:"storage_pool,omitempty"`
   374  	// maximum size in KiB
   375  	MaxVolumeSizeKib int64    `json:"max_volume_size_kib,omitempty"`
   376  	NodeNames        []string `json:"node_names,omitempty"`
   377  	AllThin          bool     `json:"all_thin,omitempty"`
   378  }
   379  
   380  // MaxVolumeSizes struct for MaxVolumeSizes
   381  type MaxVolumeSizes struct {
   382  	Candidates                      []Candidate `json:"candidates,omitempty"`
   383  	DefaultMaxOversubscriptionRatio float64     `json:"default_max_oversubscription_ratio,omitempty"`
   384  }
   385  
   386  type ResourceMakeAvailable struct {
   387  	LayerList []devicelayerkind.DeviceLayerKind `json:"layer_list,omitempty"`
   388  	// if true resource will be created as diskful even if diskless would be possible
   389  	Diskful bool `json:"diskful,omitempty"`
   390  }
   391  
   392  type ToggleDiskDiskfulProps struct {
   393  	LayerList []devicelayerkind.DeviceLayerKind `json:"layer_list,omitempty"`
   394  }
   395  
   396  // custom code
   397  
   398  // ResourceProvider acts as an abstraction for an ResourceService. It can be
   399  // swapped out for another ResourceService implementation, for example for
   400  // testing.
   401  type ResourceProvider interface {
   402  	// GetResourceView returns all resources in the cluster. Filters can be set via ListOpts.
   403  	GetResourceView(ctx context.Context, opts ...*ListOpts) ([]ResourceWithVolumes, error)
   404  	// GetAll returns all resources for a resource-definition
   405  	GetAll(ctx context.Context, resName string, opts ...*ListOpts) ([]Resource, error)
   406  	// Get returns information about a resource on a specific node
   407  	Get(ctx context.Context, resName, nodeName string, opts ...*ListOpts) (Resource, error)
   408  	// Create is used to create a resource on a node
   409  	Create(ctx context.Context, res ResourceCreate) error
   410  	// Modify gives the ability to modify a resource on a node
   411  	Modify(ctx context.Context, resName, nodeName string, props GenericPropsModify) error
   412  	// Delete deletes a resource on a specific node
   413  	Delete(ctx context.Context, resName, nodeName string) error
   414  	// GetVolumes lists als volumes of a resource
   415  	GetVolumes(ctx context.Context, resName, nodeName string, opts ...*ListOpts) ([]Volume, error)
   416  	// GetVolume returns information about a specific volume defined by it resource,node and volume-number
   417  	GetVolume(ctx context.Context, resName, nodeName string, volNr int, opts ...*ListOpts) (Volume, error)
   418  	// ModifyVolume modifies an existing volume with the given props
   419  	ModifyVolume(ctx context.Context, resName, nodeName string, volNr int, props GenericPropsModify) error
   420  	// Diskless toggles a resource on a node to diskless - the parameter disklesspool can be set if its needed
   421  	Diskless(ctx context.Context, resName, nodeName, disklessPoolName string) error
   422  	// Diskful toggles a resource to diskful - the parameter storagepool can be set if its needed
   423  	Diskful(ctx context.Context, resName, nodeName, storagePoolName string, props *ToggleDiskDiskfulProps) error
   424  	// Migrate mirgates a resource from one node to another node
   425  	Migrate(ctx context.Context, resName, fromNodeName, toNodeName, storagePoolName string) error
   426  	// Autoplace places a resource on your nodes autmatically
   427  	Autoplace(ctx context.Context, resName string, apr AutoPlaceRequest) error
   428  	// GetConnections lists all resource connections if no node-names are given- if two node-names are given it shows the connection between them
   429  	GetConnections(ctx context.Context, resName, nodeAName, nodeBName string, opts ...*ListOpts) ([]ResourceConnection, error)
   430  	// ModifyConnection allows to modify the connection between two nodes
   431  	ModifyConnection(ctx context.Context, resName, nodeAName, nodeBName string, props GenericPropsModify) error
   432  	// GetSnapshots lists all snapshots of a resource
   433  	GetSnapshots(ctx context.Context, resName string, opts ...*ListOpts) ([]Snapshot, error)
   434  	// GetSnapshotView gets information about all snapshots
   435  	GetSnapshotView(ctx context.Context, opts ...*ListOpts) ([]Snapshot, error)
   436  	// GetSnapshot returns information about a specific Snapshot by its name
   437  	GetSnapshot(ctx context.Context, resName, snapName string, opts ...*ListOpts) (Snapshot, error)
   438  	// CreateSnapshot creates a snapshot of a resource
   439  	CreateSnapshot(ctx context.Context, snapshot Snapshot) error
   440  	// DeleteSnapshot deletes a snapshot by its name. Specify nodes to only delete snapshots on specific nodes.
   441  	DeleteSnapshot(ctx context.Context, resName, snapName string, nodes ...string) error
   442  	// RestoreSnapshot restores a snapshot on a resource
   443  	RestoreSnapshot(ctx context.Context, origResName, snapName string, snapRestoreConf SnapshotRestore) error
   444  	// RestoreVolumeDefinitionSnapshot restores a volume-definition-snapshot on a resource
   445  	RestoreVolumeDefinitionSnapshot(ctx context.Context, origResName, snapName string, snapRestoreConf SnapshotRestore) error
   446  	// RollbackSnapshot rolls back a snapshot from a specific resource
   447  	RollbackSnapshot(ctx context.Context, resName, snapName string) error
   448  	// EnableSnapshotShipping enables snapshot shipping for a resource
   449  	EnableSnapshotShipping(ctx context.Context, resName string, ship SnapshotShipping) error
   450  	// ModifyDRBDProxy is used to modify drbd-proxy properties
   451  	ModifyDRBDProxy(ctx context.Context, resName string, props DrbdProxyModify) error
   452  	// EnableDRBDProxy is used to enable drbd-proxy with the rest-api call from the function enableDisableDRBDProxy
   453  	EnableDRBDProxy(ctx context.Context, resName, nodeAName, nodeBName string) error
   454  	// DisableDRBDProxy is used to disable drbd-proxy with the rest-api call from the function enableDisableDRBDProxy
   455  	DisableDRBDProxy(ctx context.Context, resName, nodeAName, nodeBName string) error
   456  	// QueryMaxVolumeSize finds the maximum size of a volume for a given filter
   457  	QueryMaxVolumeSize(ctx context.Context, filter AutoSelectFilter) (MaxVolumeSizes, error)
   458  	// GetSnapshotShippings gets a view of all snapshot shippings
   459  	GetSnapshotShippings(ctx context.Context, opts ...*ListOpts) ([]SnapshotShippingStatus, error)
   460  	// GetPropsInfos gets meta information about the properties that can be
   461  	// set on a resource.
   462  	GetPropsInfos(ctx context.Context, resName string, opts ...*ListOpts) ([]PropsInfo, error)
   463  	// GetVolumeDefinitionPropsInfos gets meta information about the
   464  	// properties that can be set on a volume definition.
   465  	GetVolumeDefinitionPropsInfos(ctx context.Context, resName string, opts ...*ListOpts) ([]PropsInfo, error)
   466  	// GetVolumePropsInfos gets meta information about the properties that
   467  	// can be set on a volume.
   468  	GetVolumePropsInfos(ctx context.Context, resName, nodeName string, opts ...*ListOpts) ([]PropsInfo, error)
   469  	// GetConnectionPropsInfos gets meta information about the properties
   470  	// that can be set on a connection.
   471  	GetConnectionPropsInfos(ctx context.Context, resName string, opts ...*ListOpts) ([]PropsInfo, error)
   472  	// Activate starts an inactive resource on a given node.
   473  	Activate(ctx context.Context, resName string, nodeName string) error
   474  	// Deactivate stops an active resource on given node.
   475  	Deactivate(ctx context.Context, resName string, nodeName string) error
   476  	// MakeAvailable adds a resource on a node if not already deployed.
   477  	// To use a specific storage pool add the StorPoolName property and use
   478  	// the storage pool name as value. If the StorPoolName property is not
   479  	// set, a storage pool will be chosen automatically using the
   480  	// auto-placer.
   481  	// To create a diskless resource you have to set the "DISKLESS" flag in
   482  	// the flags list.
   483  	MakeAvailable(ctx context.Context, resName, nodeName string, makeAvailable ResourceMakeAvailable) error
   484  }
   485  
   486  var _ ResourceProvider = &ResourceService{}
   487  
   488  // volumeLayerIn is a struct for volume-layers
   489  type volumeLayerIn struct {
   490  	Type devicelayerkind.DeviceLayerKind `json:"type,omitempty"`
   491  	Data json.RawMessage                 `json:"data,omitempty"`
   492  }
   493  
   494  // UnmarshalJSON fulfills the unmarshal interface for the VolumeLayer type
   495  func (v *VolumeLayer) UnmarshalJSON(b []byte) error {
   496  	var vIn volumeLayerIn
   497  	if err := json.Unmarshal(b, &vIn); err != nil {
   498  		return err
   499  	}
   500  
   501  	v.Type = vIn.Type
   502  	switch v.Type {
   503  	case devicelayerkind.Drbd:
   504  		dst := new(DrbdVolume)
   505  		if vIn.Data != nil {
   506  			if err := json.Unmarshal(vIn.Data, &dst); err != nil {
   507  				return err
   508  			}
   509  		}
   510  		v.Data = dst
   511  	case devicelayerkind.Luks:
   512  		dst := new(LuksVolume)
   513  		if vIn.Data != nil {
   514  			if err := json.Unmarshal(vIn.Data, &dst); err != nil {
   515  				return err
   516  			}
   517  		}
   518  		v.Data = dst
   519  	case devicelayerkind.Storage:
   520  		dst := new(StorageVolume)
   521  		if vIn.Data != nil {
   522  			if err := json.Unmarshal(vIn.Data, &dst); err != nil {
   523  				return err
   524  			}
   525  		}
   526  		v.Data = dst
   527  	case devicelayerkind.Nvme:
   528  		dst := new(NvmeVolume)
   529  		if vIn.Data != nil {
   530  			if err := json.Unmarshal(vIn.Data, &dst); err != nil {
   531  				return err
   532  			}
   533  		}
   534  		v.Data = dst
   535  	case devicelayerkind.Writecache:
   536  		dst := new(WritecacheVolume)
   537  		if vIn.Data != nil {
   538  			if err := json.Unmarshal(vIn.Data, &dst); err != nil {
   539  				return err
   540  			}
   541  		}
   542  		v.Data = dst
   543  	case devicelayerkind.Cache:
   544  	case devicelayerkind.Exos:
   545  	default:
   546  		return fmt.Errorf("'%+v' is not a valid type to Unmarshal", v.Type)
   547  	}
   548  
   549  	return nil
   550  }
   551  
   552  // OneOfDrbdVolumeLuksVolumeStorageVolumeNvmeVolumeWritecacheVolumeCacheVolume is used to prevent that other types than drbd- luks- and storage-volume are used for a VolumeLayer
   553  type OneOfDrbdVolumeLuksVolumeStorageVolumeNvmeVolumeWritecacheVolumeCacheVolumeBCacheVolume interface {
   554  	isOneOfDrbdVolumeLuksVolumeStorageVolumeNvmeVolumeWritecacheVolumeCacheVolumeBCacheVolume()
   555  }
   556  
   557  // Functions which are used if type is a correct VolumeLayer
   558  func (d *DrbdVolume) isOneOfDrbdVolumeLuksVolumeStorageVolumeNvmeVolumeWritecacheVolumeCacheVolumeBCacheVolume() {
   559  }
   560  func (d *LuksVolume) isOneOfDrbdVolumeLuksVolumeStorageVolumeNvmeVolumeWritecacheVolumeCacheVolumeBCacheVolume() {
   561  }
   562  func (d *StorageVolume) isOneOfDrbdVolumeLuksVolumeStorageVolumeNvmeVolumeWritecacheVolumeCacheVolumeBCacheVolume() {
   563  }
   564  func (d *NvmeVolume) isOneOfDrbdVolumeLuksVolumeStorageVolumeNvmeVolumeWritecacheVolumeCacheVolumeBCacheVolume() {
   565  }
   566  func (d *WritecacheVolume) isOneOfDrbdVolumeLuksVolumeStorageVolumeNvmeVolumeWritecacheVolumeCacheVolumeBCacheVolume() {
   567  }
   568  func (d *CacheVolume) isOneOfDrbdVolumeLuksVolumeStorageVolumeNvmeVolumeWritecacheVolumeCacheVolumeBCacheVolume() {
   569  }
   570  
   571  // GetResourceView returns all resources in the cluster. Filters can be set via ListOpts.
   572  func (n *ResourceService) GetResourceView(ctx context.Context, opts ...*ListOpts) ([]ResourceWithVolumes, error) {
   573  	var reses []ResourceWithVolumes
   574  	_, err := n.client.doGET(ctx, "/v1/view/resources", &reses, opts...)
   575  	return reses, err
   576  }
   577  
   578  // GetAll returns all resources for a resource-definition
   579  func (n *ResourceService) GetAll(ctx context.Context, resName string, opts ...*ListOpts) ([]Resource, error) {
   580  	var reses []Resource
   581  	_, err := n.client.doGET(ctx, "/v1/resource-definitions/"+resName+"/resources", &reses, opts...)
   582  	return reses, err
   583  }
   584  
   585  // Get returns information about a resource on a specific node
   586  func (n *ResourceService) Get(ctx context.Context, resName, nodeName string, opts ...*ListOpts) (Resource, error) {
   587  	var res Resource
   588  	_, err := n.client.doGET(ctx, "/v1/resource-definitions/"+resName+"/resources/"+nodeName, &res, opts...)
   589  	return res, err
   590  }
   591  
   592  // Create is used to create a resource on a node
   593  func (n *ResourceService) Create(ctx context.Context, res ResourceCreate) error {
   594  	_, err := n.client.doPOST(ctx, "/v1/resource-definitions/"+res.Resource.Name+"/resources/"+res.Resource.NodeName, res)
   595  	return err
   596  }
   597  
   598  // Modify gives the ability to modify a resource on a node
   599  func (n *ResourceService) Modify(ctx context.Context, resName, nodeName string, props GenericPropsModify) error {
   600  	_, err := n.client.doPUT(ctx, "/v1/resource-definitions/"+resName+"/resources/"+nodeName, props)
   601  	return err
   602  }
   603  
   604  // Delete deletes a resource on a specific node
   605  func (n *ResourceService) Delete(ctx context.Context, resName, nodeName string) error {
   606  	_, err := n.client.doDELETE(ctx, "/v1/resource-definitions/"+resName+"/resources/"+nodeName, nil)
   607  	return err
   608  }
   609  
   610  func (n *ResourceService) Activate(ctx context.Context, resName, nodeName string) error {
   611  	_, err := n.client.doPOST(ctx, "/v1/resource-definitions/"+resName+"/resources/"+nodeName+"/activate", nil)
   612  	return err
   613  }
   614  
   615  func (n *ResourceService) Deactivate(ctx context.Context, resName, nodeName string) error {
   616  	_, err := n.client.doPOST(ctx, "/v1/resource-definitions/"+resName+"/resources/"+nodeName+"/deactivate", nil)
   617  	return err
   618  }
   619  
   620  // GetVolumes lists als volumes of a resource
   621  func (n *ResourceService) GetVolumes(ctx context.Context, resName, nodeName string, opts ...*ListOpts) ([]Volume, error) {
   622  	var vols []Volume
   623  
   624  	_, err := n.client.doGET(ctx, "/v1/resource-definitions/"+resName+"/resources/"+nodeName+"/volumes", &vols, opts...)
   625  	return vols, err
   626  }
   627  
   628  // GetVolume returns information about a specific volume defined by it resource,node and volume-number
   629  func (n *ResourceService) GetVolume(ctx context.Context, resName, nodeName string, volNr int, opts ...*ListOpts) (Volume, error) {
   630  	var vol Volume
   631  
   632  	_, err := n.client.doGET(ctx, "/v1/resource-definitions/"+resName+"/resources/"+nodeName+"/volumes/"+strconv.Itoa(volNr), &vol, opts...)
   633  	return vol, err
   634  }
   635  
   636  // ModifyVolume modifies an existing volume with the given props
   637  func (n *ResourceService) ModifyVolume(ctx context.Context, resName, nodeName string, volNr int, props GenericPropsModify) error {
   638  	u := fmt.Sprintf("/v1/resource-definitions/%s/resources/%s/volumes/%d", resName, nodeName, volNr)
   639  	_, err := n.client.doPUT(ctx, u, props)
   640  	return err
   641  }
   642  
   643  // Diskless toggles a resource on a node to diskless - the parameter disklesspool can be set if its needed
   644  func (n *ResourceService) Diskless(ctx context.Context, resName, nodeName, disklessPoolName string) error {
   645  	u := "/v1/resource-definitions/" + resName + "/resources/" + nodeName + "/toggle-disk/diskless"
   646  	if disklessPoolName != "" {
   647  		u += "/" + disklessPoolName
   648  	}
   649  
   650  	_, err := n.client.doPUT(ctx, u, nil)
   651  	return err
   652  }
   653  
   654  // Diskful toggles a resource to diskful - the parameter storagepool can be set if its needed
   655  func (n *ResourceService) Diskful(ctx context.Context, resName, nodeName, storagePoolName string, props *ToggleDiskDiskfulProps) error {
   656  	u := "/v1/resource-definitions/" + resName + "/resources/" + nodeName + "/toggle-disk/diskful"
   657  	if storagePoolName != "" {
   658  		u += "/" + storagePoolName
   659  	}
   660  	_, err := n.client.doPUT(ctx, u, props)
   661  	return err
   662  }
   663  
   664  // Migrate mirgates a resource from one node to another node
   665  func (n *ResourceService) Migrate(ctx context.Context, resName, fromNodeName, toNodeName, storagePoolName string) error {
   666  	u := "/v1/resource-definitions/" + resName + "/resources/" + toNodeName + "/migrate-disk/" + fromNodeName
   667  	if storagePoolName != "" {
   668  		u += "/" + storagePoolName
   669  	}
   670  	_, err := n.client.doPUT(ctx, u, nil)
   671  	return err
   672  }
   673  
   674  // Autoplace places a resource on your nodes autmatically
   675  func (n *ResourceService) Autoplace(ctx context.Context, resName string, apr AutoPlaceRequest) error {
   676  	_, err := n.client.doPOST(ctx, "/v1/resource-definitions/"+resName+"/autoplace", apr)
   677  	return err
   678  }
   679  
   680  // GetConnections lists all resource connections if no node-names are given- if two node-names are given it shows the connection between them
   681  func (n *ResourceService) GetConnections(ctx context.Context, resName, nodeAName, nodeBName string, opts ...*ListOpts) ([]ResourceConnection, error) {
   682  	var resConns []ResourceConnection
   683  
   684  	u := "/v1/resource-definitions/" + resName + "/resources-connections"
   685  	if nodeAName != "" && nodeBName != "" {
   686  		u += fmt.Sprintf("/%s/%s", nodeAName, nodeBName)
   687  	}
   688  
   689  	_, err := n.client.doGET(ctx, u, &resConns, opts...)
   690  	return resConns, err
   691  }
   692  
   693  // ModifyConnection allows to modify the connection between two nodes
   694  func (n *ResourceService) ModifyConnection(ctx context.Context, resName, nodeAName, nodeBName string, props GenericPropsModify) error {
   695  	u := fmt.Sprintf("/v1/resource-definitions/%s/resource-connections/%s/%s", resName, nodeAName, nodeBName)
   696  	_, err := n.client.doPUT(ctx, u, props)
   697  	return err
   698  }
   699  
   700  // GetSnapshots lists all snapshots of a resource
   701  func (n *ResourceService) GetSnapshots(ctx context.Context, resName string, opts ...*ListOpts) ([]Snapshot, error) {
   702  	var snaps []Snapshot
   703  
   704  	_, err := n.client.doGET(ctx, "/v1/resource-definitions/"+resName+"/snapshots", &snaps, opts...)
   705  	return snaps, err
   706  }
   707  
   708  // GetSnapshotView gets information about all snapshots
   709  func (r *ResourceService) GetSnapshotView(ctx context.Context, opts ...*ListOpts) ([]Snapshot, error) {
   710  	var snaps []Snapshot
   711  	_, err := r.client.doGET(ctx, "/v1/view/snapshots", &snaps, opts...)
   712  	return snaps, err
   713  }
   714  
   715  // GetSnapshot returns information about a specific Snapshot by its name
   716  func (n *ResourceService) GetSnapshot(ctx context.Context, resName, snapName string, opts ...*ListOpts) (Snapshot, error) {
   717  	var snap Snapshot
   718  
   719  	_, err := n.client.doGET(ctx, "/v1/resource-definitions/"+resName+"/snapshots/"+snapName, &snap, opts...)
   720  	return snap, err
   721  }
   722  
   723  // CreateSnapshot creates a snapshot of a resource
   724  func (n *ResourceService) CreateSnapshot(ctx context.Context, snapshot Snapshot) error {
   725  	_, err := n.client.doPOST(ctx, "/v1/resource-definitions/"+snapshot.ResourceName+"/snapshots", snapshot)
   726  	return err
   727  }
   728  
   729  // DeleteSnapshot deletes a snapshot by its name. Specify nodes to only delete snapshots on specific nodes.
   730  func (n *ResourceService) DeleteSnapshot(ctx context.Context, resName, snapName string, nodes ...string) error {
   731  	vals, err := query.Values(struct {
   732  		Nodes []string `url:"nodes"`
   733  	}{Nodes: nodes})
   734  	if err != nil {
   735  		return fmt.Errorf("failed to encode node names: %w", err)
   736  	}
   737  
   738  	_, err = n.client.doDELETE(ctx, "/v1/resource-definitions/"+resName+"/snapshots/"+snapName+"?"+vals.Encode(), nil)
   739  	return err
   740  }
   741  
   742  // RestoreSnapshot restores a snapshot on a resource
   743  func (n *ResourceService) RestoreSnapshot(ctx context.Context, origResName, snapName string, snapRestoreConf SnapshotRestore) error {
   744  	_, err := n.client.doPOST(ctx, "/v1/resource-definitions/"+origResName+"/snapshot-restore-resource/"+snapName, snapRestoreConf)
   745  	return err
   746  }
   747  
   748  // RestoreVolumeDefinitionSnapshot restores a volume-definition-snapshot on a resource
   749  func (n *ResourceService) RestoreVolumeDefinitionSnapshot(ctx context.Context, origResName, snapName string, snapRestoreConf SnapshotRestore) error {
   750  	_, err := n.client.doPOST(ctx, "/v1/resource-definitions/"+origResName+"/snapshot-restore-volume-definition/"+snapName, snapRestoreConf)
   751  	return err
   752  }
   753  
   754  // RollbackSnapshot rolls back a snapshot from a specific resource
   755  func (n *ResourceService) RollbackSnapshot(ctx context.Context, resName, snapName string) error {
   756  	_, err := n.client.doPOST(ctx, "/v1/resource-definitions/"+resName+"/snapshot-rollback/"+snapName, nil)
   757  	return err
   758  }
   759  
   760  // EnableSnapshotShipping enables snapshot shipping for a resource
   761  func (n *ResourceService) EnableSnapshotShipping(ctx context.Context, resName string, ship SnapshotShipping) error {
   762  	_, err := n.client.doPOST(ctx, "/v1/resource-definitions/"+resName+"/snapshot-shipping", ship)
   763  	return err
   764  }
   765  
   766  // ModifyDRBDProxy is used to modify drbd-proxy properties
   767  func (n *ResourceService) ModifyDRBDProxy(ctx context.Context, resName string, props DrbdProxyModify) error {
   768  	_, err := n.client.doPUT(ctx, "/v1/resource-definitions/"+resName+"/drbd-proxy", props)
   769  	return err
   770  }
   771  
   772  // enableDisableDRBDProxy enables or disables drbd-proxy between two nodes
   773  func (n *ResourceService) enableDisableDRBDProxy(ctx context.Context, what, resName, nodeAName, nodeBName string) error {
   774  	u := fmt.Sprintf("/v1/resource-definitions/%s/drbd-proxy/%s/%s/%s", resName, what, nodeAName, nodeBName)
   775  	_, err := n.client.doPOST(ctx, u, nil)
   776  	return err
   777  }
   778  
   779  // EnableDRBDProxy is used to enable drbd-proxy with the rest-api call from the function enableDisableDRBDProxy
   780  func (n *ResourceService) EnableDRBDProxy(ctx context.Context, resName, nodeAName, nodeBName string) error {
   781  	return n.enableDisableDRBDProxy(ctx, "enable", resName, nodeAName, nodeBName)
   782  }
   783  
   784  // DisableDRBDProxy is used to disable drbd-proxy with the rest-api call from the function enableDisableDRBDProxy
   785  func (n *ResourceService) DisableDRBDProxy(ctx context.Context, resName, nodeAName, nodeBName string) error {
   786  	return n.enableDisableDRBDProxy(ctx, "disable", resName, nodeAName, nodeBName)
   787  }
   788  
   789  // QueryMaxVolumeSize finds the maximum size of a volume for a given filter
   790  func (n *ResourceService) QueryMaxVolumeSize(ctx context.Context, filter AutoSelectFilter) (MaxVolumeSizes, error) {
   791  	var sizes MaxVolumeSizes
   792  	_, err := n.client.doOPTIONS(ctx, "/v1/query-max-volume-size", &sizes, filter)
   793  	return sizes, err
   794  }
   795  
   796  // GetSnapshotShippings gets a view of all snapshot shippings
   797  func (n *ResourceService) GetSnapshotShippings(ctx context.Context, opts ...*ListOpts) ([]SnapshotShippingStatus, error) {
   798  	var shippings []SnapshotShippingStatus
   799  	_, err := n.client.doGET(ctx, "/v1/view/snapshot-shippings", &shippings, opts...)
   800  	return shippings, err
   801  }
   802  
   803  // GetPropsInfos gets meta information about the properties that can be set on
   804  // a resource.
   805  func (n *ResourceService) GetPropsInfos(ctx context.Context, resName string, opts ...*ListOpts) ([]PropsInfo, error) {
   806  	var infos []PropsInfo
   807  	_, err := n.client.doGET(ctx, "/v1/resource-definitions/"+resName+"/resources/properties/info", &infos, opts...)
   808  	return infos, err
   809  }
   810  
   811  // GetVolumeDefinitionPropsInfos gets meta information about the properties
   812  // that can be set on a volume definition.
   813  func (n *ResourceService) GetVolumeDefinitionPropsInfos(ctx context.Context, resName string, opts ...*ListOpts) ([]PropsInfo, error) {
   814  	var infos []PropsInfo
   815  	_, err := n.client.doGET(ctx, "/v1/resource-definitions/"+resName+"/volume-definitions/properties/info", &infos, opts...)
   816  	return infos, err
   817  }
   818  
   819  // GetVolumePropsInfos gets meta information about the properties that can be
   820  // set on a volume.
   821  func (n *ResourceService) GetVolumePropsInfos(ctx context.Context, resName, nodeName string, opts ...*ListOpts) ([]PropsInfo, error) {
   822  	var infos []PropsInfo
   823  	_, err := n.client.doGET(ctx, "/v1/resource-definitions/"+resName+"/resources/"+nodeName+"/volumes/properties/info", &infos, opts...)
   824  	return infos, err
   825  }
   826  
   827  // GetConnectionPropsInfos gets meta information about the properties that can
   828  // be set on a connection.
   829  func (n *ResourceService) GetConnectionPropsInfos(ctx context.Context, resName string, opts ...*ListOpts) ([]PropsInfo, error) {
   830  	var infos []PropsInfo
   831  	_, err := n.client.doGET(ctx, "/v1/resource-definitions/"+resName+"/resource-connections/properties/info", &infos, opts...)
   832  	return infos, err
   833  }
   834  
   835  // MakeAvailable adds a resource on a node if not already deployed.
   836  // To use a specific storage pool add the StorPoolName property and use the
   837  // storage pool name as value. If the StorPoolName property is not set, a
   838  // storage pool will be chosen automatically using the auto-placer.
   839  // To create a diskless resource you have to set the "DISKLESS" flag in the
   840  // flags list.
   841  func (n *ResourceService) MakeAvailable(ctx context.Context, resName, nodeName string, makeAvailable ResourceMakeAvailable) error {
   842  	u := fmt.Sprintf("/v1/resource-definitions/%s/resources/%s/make-available",
   843  		resName, nodeName)
   844  	_, err := n.client.doPOST(ctx, u, makeAvailable)
   845  	return err
   846  }
   847  

View as plain text