github.com/openebs/api@v1.12.0/pkg/internalapis/apis/cstor/cstorpool_topology.go (about) 1 /* 2 Copyright 2020 The OpenEBS Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package cstor 18 19 import ( 20 "encoding/json" 21 "strings" 22 23 "github.com/openebs/api/pkg/util" 24 ) 25 26 /* 27 * enum maintaing in cstor data plane side 28 * typedef enum dsl_scan_state { 29 * DSS_NONE, 30 * DSS_SCANNING, 31 * DSS_FINISHED, 32 * DSS_CANCELED, 33 * DSS_NUM_STATES 34 *} dsl_scan_state_t; 35 */ 36 37 //TODO: Improve comments during review process 38 39 //PoolScanState states various pool scan states 40 type PoolScanState uint64 41 42 const ( 43 // PoolScanNone represents pool scanning is not yet started 44 PoolScanNone PoolScanState = iota 45 // PoolScanScanning represents pool is undergoing scanning 46 PoolScanScanning 47 // PoolScanFinished represents pool scanning is finished 48 PoolScanFinished 49 // PoolScanCanceled represents pool scan is aborted 50 PoolScanCanceled 51 // PoolScanNumOfStates holds value 4 52 PoolScanNumOfStates 53 ) 54 55 // PoolScanFunc holds various scanning functions 56 type PoolScanFunc uint64 57 58 const ( 59 // PoolScanFuncNone holds value 0 60 PoolScanFuncNone PoolScanFunc = iota 61 // PoolScanFuncScrub holds value 1 62 PoolScanFuncScrub 63 // PoolScanFuncResilver holds value 2 which states device under went resilvering 64 PoolScanFuncResilver 65 // PoolScanFuncStates holds value 3 66 PoolScanFuncStates 67 ) 68 69 // NOTE: 1. VdevState represent the state of the vdev/disk in pool. 70 // 2. VdevAux represents gives the reason why disk/vdev are in that state. 71 72 // VdevState represent various device/disk states 73 type VdevState uint64 74 75 /* 76 * vdev states are ordered from least to most healthy. 77 * Link: https://github.com/openebs/cstor/blob/f0896898a0be2102e2865cf44b16b88c91f6bb91/include/sys/fs/zfs.h#L723 78 */ 79 const ( 80 // VdevStateUnknown represents uninitialized vdev 81 VdevStateUnknown VdevState = iota 82 // VdevStateClosed represents vdev currently not opened 83 VdevStateClosed 84 // VdevStateOffline represents vdev not allowed to open 85 VdevStateOffline 86 // VdevStateRemoved represents vdev explicitly removed from system 87 VdevStateRemoved 88 // VdevStateCantOpen represents tried to open, but failed 89 VdevStateCantOpen 90 // VdevStateFaulted represents external request to fault device 91 VdevStateFaulted 92 // VdevStateDegraded represents Replicated vdev with unhealthy kids 93 VdevStateDegraded 94 // VdevStateHealthy represents vdev is presumed good 95 VdevStateHealthy 96 ) 97 98 // VdevAux represents reasons why vdev can't open 99 type VdevAux uint64 100 101 /* 102 * vdev aux states. When a vdev is in the CANT_OPEN state, the aux field 103 * of the vdev stats structure uses these constants to distinguish why. 104 */ 105 // NOTE: Added only required enums for more information please have look at 106 // https://github.com/openebs/cstor/blob/f0896898a0be2102e2865cf44b16b88c91f6bb91/include/sys/fs/zfs.h#L740 107 const ( 108 VdevAuxNone VdevAux = iota /* no error */ 109 VdevAuxOpenFailed /* ldi_open_*() or vn_open() failed */ 110 VdevAuxCorruptData /* bad label or disk contents */ 111 VdevAuxNoReplicas /* insufficient number of replicas */ 112 VdevAuxBadGUIDSum /* vdev guid sum doesn't match */ 113 VdevAuxTooSmall /* vdev size is too small */ 114 VdevAuxBadLabel /* the label is OK but invalid */ 115 VdevAuxVersionNewer /* on-disk version is too new */ 116 VdevAuxVersionOlder /* on-disk version is too old */ 117 VdevAuxUnSupFeat /* unsupported features */ 118 VdevAuxSpared /* hot spare used in another pool */ 119 VdevAuxErrExceeded /* too many errors */ 120 VdevAuxIOFailure /* experienced I/O failure */ 121 VdevAuxBadLog /* cannot read log chain(s) */ 122 VdevAuxExternal /* external diagnosis or forced fault */ 123 VdevAuxSplitPool /* vdev was split off into another pool */ 124 VdevAuxBadAShift /* vdev ashift is invalid */ 125 VdevAuxExternalPersist /* persistent forced fault */ 126 VdevAuxActive /* vdev active on a different host */ 127 ) 128 129 const ( 130 // PoolOperator is the name of the tool that makes pool-related operations. 131 PoolOperator = "zpool" 132 // VdevScanProcessedIndex is index of scaned bytes on disk 133 VdevScanProcessedIndex = 25 134 // VdevScanStatsStateIndex represents the index of dataset scan state 135 VdevScanStatsStateIndex = 1 136 // VdevScanStatsScanFuncIndex point to index which inform whether device 137 // under went resilvering or not 138 VdevScanStatsScanFuncIndex = 0 139 // VdevStateIndex represents the device state information 140 VdevStateIndex = 1 141 // VdevAuxIndex represents vdev aux states. When a vdev is 142 // in the CANT_OPEN state, the aux field of the vdev stats 143 // structure uses these constants to distinguish why 144 VdevAuxIndex = 2 145 ) 146 147 // Topology contains the topology strucure of disks used in backend 148 type Topology struct { 149 // Number of top-level children in topology (doesnt include spare/l2cache) 150 ChildrenCount int `json:"vdev_children,omitempty"` 151 152 // Root of vdev topology 153 VdevTree VdevTree `json:"vdev_tree,omitempty"` 154 } 155 156 // VdevTree contains the tree strucure of disks used in backend 157 type VdevTree struct { 158 // root for Root vdev, Raid type in case of non-level 0 vdev, 159 // and file/disk in case of level-0 vdev 160 VdevType string `json:"type,omitempty"` 161 162 // top-level vdev topology 163 Topvdev []Vdev `json:"children,omitempty"` 164 165 // list of read-cache devices 166 Readcache []Vdev `json:"l2cache,omitempty"` 167 168 // list of spare devices 169 Spares []Vdev `json:"spares,omitempty"` 170 171 // vdev indetailed statistics 172 VdevStats []uint64 `json:"vdev_stats,omitempty"` 173 174 // ScanStats states replaced device scan state 175 ScanStats []uint64 `json:"scan_stats,omitempty"` 176 } 177 178 // Vdev relates to a logical or physical disk in backend 179 type Vdev struct { 180 // root for Root vdev, Raid type in case of non-level 0 vdev, 181 // and file/disk in case of level-0 vdev 182 VdevType string `json:"type,omitempty"` 183 184 // Path of the disk or sparse file 185 Path string `json:"path,omitempty"` 186 187 // 0 means not write-cache device, 1 means write-cache device 188 IsLog int `json:"is_log,omitempty"` 189 190 // 0 means not spare device, 1 means spare device 191 IsSpare int `json:"is_spare,omitempty"` 192 193 // 0 means partitioned disk, 1 means whole disk 194 IsWholeDisk int `json:"whole_disk,omitempty"` 195 196 // Capacity represents the size of the disk used in pool 197 Capacity uint64 `json:"asize,omitempty"` 198 199 // vdev indetailed statistics 200 VdevStats []uint64 `json:"vdev_stats,omitempty"` 201 202 ScanStats []uint64 `json:"scan_stats,omitempty"` 203 204 // child vdevs of the logical disk or null for physical disk/sparse 205 Children []Vdev `json:"children,omitempty"` 206 } 207 208 // VdevList is alias of list of Vdevs 209 type VdevList []Vdev 210 211 // Dump runs 'zpool dump' command and unmarshal the output in above schema 212 func Dump() (Topology, error) { 213 var t Topology 214 runnerVar := util.RealRunner{} 215 out, err := runnerVar.RunCombinedOutput(PoolOperator, "dump") 216 if err != nil { 217 return t, err 218 } 219 err = json.Unmarshal(out, &t) 220 return t, err 221 } 222 223 // GetVdevFromPath returns vdev if provided path exists in vdev topology 224 func (l VdevList) GetVdevFromPath(path string) (Vdev, bool) { 225 for _, v := range l { 226 if strings.EqualFold(path, v.Path) { 227 return v, true 228 } 229 for _, p := range v.Children { 230 if strings.EqualFold(path, p.Path) { 231 return p, true 232 } 233 if vdev, r := VdevList(p.Children).GetVdevFromPath(path); r { 234 return vdev, true 235 } 236 } 237 } 238 return Vdev{}, false 239 } 240 241 // GetVdevState returns current state of Vdev 242 // NOTE: Below function is taken from openebs/cstor 243 // https://github.com/openebs/cstor/blob/f0896898a0be2102e2865cf44b16b88c91f6bb91/lib/libzfs/libzfs_pool.c#L183<Paste> 244 func (v Vdev) GetVdevState() string { 245 state := v.VdevStats[VdevStateIndex] 246 aux := v.VdevStats[VdevAuxIndex] 247 switch state { 248 case uint64(VdevStateClosed): 249 fallthrough 250 case uint64(VdevStateOffline): 251 return "OFFLINE" 252 case uint64(VdevStateRemoved): 253 return "REMOVED" 254 case uint64(VdevStateCantOpen): 255 if aux == uint64(VdevAuxCorruptData) || aux == uint64(VdevAuxBadLog) { 256 return "FAULTED" 257 } else if aux == uint64(VdevAuxSplitPool) { 258 return "SPLIT" 259 } else { 260 return "UNAVAILABLE" 261 } 262 case uint64(VdevStateFaulted): 263 return "FAULTED" 264 case uint64(VdevStateDegraded): 265 return "DEGRADED" 266 case uint64(VdevStateHealthy): 267 return "ONLINE" 268 } 269 return "UNKNOWN" 270 }