1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
33 type ResourceService struct {
34 client *Client
35 }
36
37
38
39
40 type Resource struct {
41 Name string `json:"name,omitempty"`
42 NodeName string `json:"node_name,omitempty"`
43
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
49 Uuid string `json:"uuid,omitempty"`
50
51 CreateTimestamp *TimeStampMs `json:"create_timestamp,omitempty"`
52 }
53
54 type ResourceWithVolumes struct {
55 Resource
56
57 CreateTimestamp *TimeStampMs `json:"create_timestamp,omitempty"`
58 Volumes []Volume `json:"volumes,omitempty"`
59
60
61 SharedName string `json:"shared_name,omitempty"`
62 }
63
64 type ResourceDefinitionModify struct {
65
66 DrbdPort int32 `json:"drbd_port,omitempty"`
67
68 DrbdPeerSlots int32 `json:"drbd_peer_slots,omitempty"`
69 LayerStack []devicelayerkind.DeviceLayerKind `json:"layer_stack,omitempty"`
70
71 ResourceGroup string `json:"resource_group,omitempty"`
72 GenericPropsModify
73 }
74
75
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
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
103 DevicePath string `json:"device_path,omitempty"`
104
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
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
119 DevicePath string `json:"device_path,omitempty"`
120
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
125 DiskState string `json:"disk_state,omitempty"`
126 }
127
128
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
143 type DrbdConnection struct {
144 Connected bool `json:"connected,omitempty"`
145
146 Message string `json:"message,omitempty"`
147 }
148
149
150 type DrbdVolume struct {
151 DrbdVolumeDefinition DrbdVolumeDefinition `json:"drbd_volume_definition,omitempty"`
152
153 DevicePath string `json:"device_path,omitempty"`
154
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
160 DiskState string `json:"disk_state,omitempty"`
161
162 ExtMetaStorPool string `json:"ext_meta_stor_pool,omitempty"`
163 }
164
165
166 type LuksResource struct {
167 StorageVolumes []LuksVolume `json:"storage_volumes,omitempty"`
168 }
169
170
171 type LuksVolume struct {
172 VolumeNumber int32 `json:"volume_number,omitempty"`
173
174 DevicePath string `json:"device_path,omitempty"`
175
176 BackingDevice string `json:"backing_device,omitempty"`
177 AllocatedSizeKib int64 `json:"allocated_size_kib,omitempty"`
178 UsableSizeKib int64 `json:"usable_size_kib,omitempty"`
179
180 DiskState string `json:"disk_state,omitempty"`
181 Opened bool `json:"opened,omitempty"`
182 }
183
184
185 type StorageResource struct {
186 StorageVolumes []StorageVolume `json:"storage_volumes,omitempty"`
187 }
188
189
190 type StorageVolume struct {
191 VolumeNumber int32 `json:"volume_number,omitempty"`
192
193 DevicePath string `json:"device_path,omitempty"`
194 AllocatedSizeKib int64 `json:"allocated_size_kib,omitempty"`
195 UsableSizeKib int64 `json:"usable_size_kib,omitempty"`
196
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
207 DevicePath string `json:"device_path,omitempty"`
208
209 BackingDevice string `json:"backing_device,omitempty"`
210 AllocatedSizeKib int64 `json:"allocated_size_kib,omitempty"`
211 UsableSizeKib int64 `json:"usable_size_kib,omitempty"`
212
213 DiskState string `json:"disk_state,omitempty"`
214 }
215
216
217 type ResourceState struct {
218 InUse *bool `json:"in_use,omitempty"`
219 }
220
221
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
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
235 Uuid string `json:"uuid,omitempty"`
236 Reports []ApiCallRc `json:"reports,omitempty"`
237 }
238
239
240 type VolumeLayer struct {
241 Type devicelayerkind.DeviceLayerKind `json:"type,omitempty"`
242 Data OneOfDrbdVolumeLuksVolumeStorageVolumeNvmeVolumeWritecacheVolumeCacheVolumeBCacheVolume `json:"data,omitempty"`
243 }
244
245
246 type VolumeState struct {
247 DiskState string `json:"disk_state,omitempty"`
248 }
249
250
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
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
277 type ResourceConnection struct {
278
279 NodeA string `json:"node_a,omitempty"`
280
281 NodeB string `json:"node_b,omitempty"`
282
283 Props map[string]string `json:"props,omitempty"`
284 Flags []string `json:"flags,omitempty"`
285 Port int32 `json:"port,omitempty"`
286 }
287
288
289 type Snapshot struct {
290 Name string `json:"name,omitempty"`
291 ResourceName string `json:"resource_name,omitempty"`
292 Nodes []string `json:"nodes,omitempty"`
293
294 Props map[string]string `json:"props,omitempty"`
295 Flags []string `json:"flags,omitempty"`
296 VolumeDefinitions []SnapshotVolumeDefinition `json:"volume_definitions,omitempty"`
297
298 Uuid string `json:"uuid,omitempty"`
299 Snapshots []SnapshotNode `json:"snapshots,omitempty"`
300 }
301
302
303 type SnapshotNode struct {
304
305 SnapshotName string `json:"snapshot_name,omitempty"`
306
307 NodeName string `json:"node_name,omitempty"`
308
309 CreateTimestamp *TimeStampMs `json:"create_timestamp,omitempty"`
310 Flags []string `json:"flags,omitempty"`
311
312 Uuid string `json:"uuid,omitempty"`
313
314 SnapshotVolumes []SnapshotVolumeNode `json:"snapshot_volumes,omitempty"`
315 }
316
317 type SnapshotVolumeNode struct {
318
319 Uuid string `json:"uuid,omitempty"`
320
321 VlmNr int32 `json:"vlm_nr,omitempty"`
322
323 Props map[string]string `json:"props,omitempty"`
324
325 State string `json:"state,omitempty"`
326 }
327
328
329 type SnapshotShipping struct {
330
331 FromNode string `json:"from_node"`
332
333 FromNic string `json:"from_nic,omitempty"`
334
335 ToNode string `json:"to_node"`
336
337 ToNic string `json:"to_nic,omitempty"`
338 }
339
340
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
349 type SnapshotVolumeDefinition struct {
350 VolumeNumber int32 `json:"volume_number,omitempty"`
351
352 SizeKib uint64 `json:"size_kib,omitempty"`
353 }
354
355
356 type SnapshotRestore struct {
357
358 ToResource string `json:"to_resource"`
359
360 Nodes []string `json:"nodes,omitempty"`
361 }
362
363 type DrbdProxyModify struct {
364
365 CompressionType string `json:"compression_type,omitempty"`
366
367 CompressionProps map[string]string `json:"compression_props,omitempty"`
368 GenericPropsModify
369 }
370
371
372 type Candidate struct {
373 StoragePool string `json:"storage_pool,omitempty"`
374
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
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
389 Diskful bool `json:"diskful,omitempty"`
390 }
391
392 type ToggleDiskDiskfulProps struct {
393 LayerList []devicelayerkind.DeviceLayerKind `json:"layer_list,omitempty"`
394 }
395
396
397
398
399
400
401 type ResourceProvider interface {
402
403 GetResourceView(ctx context.Context, opts ...*ListOpts) ([]ResourceWithVolumes, error)
404
405 GetAll(ctx context.Context, resName string, opts ...*ListOpts) ([]Resource, error)
406
407 Get(ctx context.Context, resName, nodeName string, opts ...*ListOpts) (Resource, error)
408
409 Create(ctx context.Context, res ResourceCreate) error
410
411 Modify(ctx context.Context, resName, nodeName string, props GenericPropsModify) error
412
413 Delete(ctx context.Context, resName, nodeName string) error
414
415 GetVolumes(ctx context.Context, resName, nodeName string, opts ...*ListOpts) ([]Volume, error)
416
417 GetVolume(ctx context.Context, resName, nodeName string, volNr int, opts ...*ListOpts) (Volume, error)
418
419 ModifyVolume(ctx context.Context, resName, nodeName string, volNr int, props GenericPropsModify) error
420
421 Diskless(ctx context.Context, resName, nodeName, disklessPoolName string) error
422
423 Diskful(ctx context.Context, resName, nodeName, storagePoolName string, props *ToggleDiskDiskfulProps) error
424
425 Migrate(ctx context.Context, resName, fromNodeName, toNodeName, storagePoolName string) error
426
427 Autoplace(ctx context.Context, resName string, apr AutoPlaceRequest) error
428
429 GetConnections(ctx context.Context, resName, nodeAName, nodeBName string, opts ...*ListOpts) ([]ResourceConnection, error)
430
431 ModifyConnection(ctx context.Context, resName, nodeAName, nodeBName string, props GenericPropsModify) error
432
433 GetSnapshots(ctx context.Context, resName string, opts ...*ListOpts) ([]Snapshot, error)
434
435 GetSnapshotView(ctx context.Context, opts ...*ListOpts) ([]Snapshot, error)
436
437 GetSnapshot(ctx context.Context, resName, snapName string, opts ...*ListOpts) (Snapshot, error)
438
439 CreateSnapshot(ctx context.Context, snapshot Snapshot) error
440
441 DeleteSnapshot(ctx context.Context, resName, snapName string, nodes ...string) error
442
443 RestoreSnapshot(ctx context.Context, origResName, snapName string, snapRestoreConf SnapshotRestore) error
444
445 RestoreVolumeDefinitionSnapshot(ctx context.Context, origResName, snapName string, snapRestoreConf SnapshotRestore) error
446
447 RollbackSnapshot(ctx context.Context, resName, snapName string) error
448
449 EnableSnapshotShipping(ctx context.Context, resName string, ship SnapshotShipping) error
450
451 ModifyDRBDProxy(ctx context.Context, resName string, props DrbdProxyModify) error
452
453 EnableDRBDProxy(ctx context.Context, resName, nodeAName, nodeBName string) error
454
455 DisableDRBDProxy(ctx context.Context, resName, nodeAName, nodeBName string) error
456
457 QueryMaxVolumeSize(ctx context.Context, filter AutoSelectFilter) (MaxVolumeSizes, error)
458
459 GetSnapshotShippings(ctx context.Context, opts ...*ListOpts) ([]SnapshotShippingStatus, error)
460
461
462 GetPropsInfos(ctx context.Context, resName string, opts ...*ListOpts) ([]PropsInfo, error)
463
464
465 GetVolumeDefinitionPropsInfos(ctx context.Context, resName string, opts ...*ListOpts) ([]PropsInfo, error)
466
467
468 GetVolumePropsInfos(ctx context.Context, resName, nodeName string, opts ...*ListOpts) ([]PropsInfo, error)
469
470
471 GetConnectionPropsInfos(ctx context.Context, resName string, opts ...*ListOpts) ([]PropsInfo, error)
472
473 Activate(ctx context.Context, resName string, nodeName string) error
474
475 Deactivate(ctx context.Context, resName string, nodeName string) error
476
477
478
479
480
481
482
483 MakeAvailable(ctx context.Context, resName, nodeName string, makeAvailable ResourceMakeAvailable) error
484 }
485
486 var _ ResourceProvider = &ResourceService{}
487
488
489 type volumeLayerIn struct {
490 Type devicelayerkind.DeviceLayerKind `json:"type,omitempty"`
491 Data json.RawMessage `json:"data,omitempty"`
492 }
493
494
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
553 type OneOfDrbdVolumeLuksVolumeStorageVolumeNvmeVolumeWritecacheVolumeCacheVolumeBCacheVolume interface {
554 isOneOfDrbdVolumeLuksVolumeStorageVolumeNvmeVolumeWritecacheVolumeCacheVolumeBCacheVolume()
555 }
556
557
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
804
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
812
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
820
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
828
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
836
837
838
839
840
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