|
59 | 59 | ErrDatasetNotFound = errors.New("dataset not found for share") |
60 | 60 | ) |
61 | 61 |
|
| 62 | +// capacityErrorSubstrings are error message patterns that indicate insufficient pool capacity. |
| 63 | +// TrueNAS returns these when a pool or dataset doesn't have enough free space. |
| 64 | +var capacityErrorSubstrings = []string{ |
| 65 | + "insufficient space", |
| 66 | + "out of space", |
| 67 | + "not enough space", |
| 68 | + "no space left", |
| 69 | + "ENOSPC", |
| 70 | + "quota exceeded", |
| 71 | +} |
| 72 | + |
| 73 | +// isCapacityError checks if an error indicates a storage capacity issue. |
| 74 | +// Returns codes.ResourceExhausted status if it is, nil otherwise. |
| 75 | +func isCapacityError(err error) bool { |
| 76 | + if err == nil { |
| 77 | + return false |
| 78 | + } |
| 79 | + errStr := strings.ToLower(err.Error()) |
| 80 | + for _, substr := range capacityErrorSubstrings { |
| 81 | + if strings.Contains(errStr, substr) { |
| 82 | + return true |
| 83 | + } |
| 84 | + } |
| 85 | + return false |
| 86 | +} |
| 87 | + |
| 88 | +// createVolumeError returns an appropriate gRPC status error for volume creation failures. |
| 89 | +// Maps capacity-related errors to ResourceExhausted per CSI spec. |
| 90 | +func createVolumeError(msg string, err error) error { |
| 91 | + if isCapacityError(err) { |
| 92 | + return status.Errorf(codes.ResourceExhausted, "%s: %v", msg, err) |
| 93 | + } |
| 94 | + return status.Errorf(codes.Internal, "%s: %v", msg, err) |
| 95 | +} |
| 96 | + |
62 | 97 | // mountpointToDatasetID converts a ZFS mountpoint to a dataset ID. |
63 | 98 | // ZFS datasets are mounted at /mnt/<dataset_name>, so we strip the /mnt/ prefix. |
64 | 99 | // Example: /mnt/tank/csi/pvc-xxx -> tank/csi/pvc-xxx. |
@@ -1509,6 +1544,20 @@ func (s *ControllerService) ControllerGetCapabilities(_ context.Context, _ *csi. |
1509 | 1544 | }, |
1510 | 1545 | }, |
1511 | 1546 | }, |
| 1547 | + { |
| 1548 | + Type: &csi.ControllerServiceCapability_Rpc{ |
| 1549 | + Rpc: &csi.ControllerServiceCapability_RPC{ |
| 1550 | + Type: csi.ControllerServiceCapability_RPC_VOLUME_CONDITION, |
| 1551 | + }, |
| 1552 | + }, |
| 1553 | + }, |
| 1554 | + { |
| 1555 | + Type: &csi.ControllerServiceCapability_Rpc{ |
| 1556 | + Rpc: &csi.ControllerServiceCapability_RPC{ |
| 1557 | + Type: csi.ControllerServiceCapability_RPC_SINGLE_NODE_MULTI_WRITER, |
| 1558 | + }, |
| 1559 | + }, |
| 1560 | + }, |
1512 | 1561 | }, |
1513 | 1562 | }, nil |
1514 | 1563 | } |
|
0 commit comments