yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/zstack/storage.go (about) 1 // Copyright 2019 Yunion 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package zstack 16 17 import ( 18 "fmt" 19 "net/url" 20 "strings" 21 22 "yunion.io/x/jsonutils" 23 "yunion.io/x/log" 24 25 api "yunion.io/x/cloudmux/pkg/apis/compute" 26 "yunion.io/x/cloudmux/pkg/cloudprovider" 27 "yunion.io/x/cloudmux/pkg/multicloud" 28 ) 29 30 type TStorageType string 31 32 type TCephPoolType string 33 34 const ( 35 StorageTypeCeph = TStorageType("Ceph") 36 StorageTypeLocal = TStorageType("LocalStorage") 37 StorageTypeVCenter = TStorageType("VCenter") 38 39 CephPoolTypeData = TCephPoolType("Data") 40 CephPoolTypeRoot = TCephPoolType("Root") 41 CephPoolTypeImageCache = TCephPoolType("ImageCache") 42 ) 43 44 type SPool struct { 45 UUID string `json:"uuid"` 46 PrimaryStorageUUID string `json:"primaryStorageUuid"` 47 PoolName string `json:"poolName"` 48 Type TCephPoolType `json:"type"` 49 AvailableCapacity int64 `json:"availableCapacity"` 50 UsedCapacity int64 `json:"usedCapacity"` 51 ReplicatedSize int64 `json:"replicatedSize"` 52 TotalCapacity int64 `json:"totalCapacity"` 53 ZStackTime 54 } 55 56 type SStorage struct { 57 multicloud.SStorageBase 58 ZStackTags 59 region *SRegion 60 61 ZStackBasic 62 VCenterUUID string `json:"VCenterUuid"` 63 Datastore string `json:"datastore"` 64 ZoneUUID string `json:"zoneUuid"` 65 URL string `json:"url"` 66 TotalCapacity int64 `json:"totalCapacity"` 67 AvailableCapacity int `json:"availableCapacity"` 68 TotalPhysicalCapacity int `json:"totalPhysicalCapacity"` 69 AvailablePhysicalCapacity int `json:"availablePhysicalCapacity"` 70 Type TStorageType `json:"type"` 71 State string `json:"state"` 72 Status string `json:"status"` 73 MountPath string `json:"mountPath"` 74 AttachedClusterUUIDs []string `json:"attachedClusterUuids"` 75 76 Pools []SPool `json:"pools"` 77 78 ZStackTime 79 } 80 81 func (region *SRegion) getIStorages(zondId string) ([]cloudprovider.ICloudStorage, error) { 82 primaryStorages, err := region.GetStorages(zondId, "", "") 83 if err != nil { 84 return nil, err 85 } 86 istorage := []cloudprovider.ICloudStorage{} 87 for i := 0; i < len(primaryStorages); i++ { 88 primaryStorage := primaryStorages[i] 89 switch primaryStorage.Type { 90 case StorageTypeLocal: 91 ilocalStorages, err := region.getILocalStorages(primaryStorage.UUID, "") 92 if err != nil { 93 return nil, err 94 } 95 istorage = append(istorage, ilocalStorages...) 96 case StorageTypeCeph: 97 primaryStorage.region = region 98 istorage = append(istorage, &primaryStorage) 99 case StorageTypeVCenter: 100 } 101 } 102 return istorage, nil 103 } 104 105 func (region *SRegion) GetStorage(storageId string) (*SStorage, error) { 106 if len(storageId) == 0 { 107 return nil, cloudprovider.ErrNotFound 108 } 109 storages, err := region.GetStorages("", "", storageId) 110 if err != nil { 111 return nil, err 112 } 113 if len(storages) == 1 && storages[0].UUID == storageId { 114 storages[0].region = region 115 return &storages[0], nil 116 } 117 if len(storages) == 0 { 118 return nil, cloudprovider.ErrNotFound 119 } 120 return nil, cloudprovider.ErrDuplicateId 121 } 122 123 func (region *SRegion) GetStorages(zoneId, clusterId, storageId string) ([]SStorage, error) { 124 storages := []SStorage{} 125 params := url.Values{} 126 if len(zoneId) > 0 { 127 params.Add("q", "zone.uuid="+zoneId) 128 } 129 if len(clusterId) > 0 { 130 params.Add("q", "cluster.uuid="+clusterId) 131 } 132 if SkipEsxi { 133 params.Add("q", "type!=VCenter") 134 } 135 if len(storageId) > 0 { 136 params.Add("q", "uuid="+storageId) 137 } 138 return storages, region.client.listAll("primary-storage", params, &storages) 139 } 140 141 func (storage *SStorage) GetStatus() string { 142 if storage.Status == "Connected" { 143 return api.STORAGE_ONLINE 144 } 145 return api.STORAGE_OFFLINE 146 } 147 148 func (storage *SStorage) GetId() string { 149 return storage.UUID 150 } 151 152 func (storage *SStorage) GetName() string { 153 return storage.Name 154 } 155 156 func (storage *SStorage) GetGlobalId() string { 157 return storage.GetId() 158 } 159 160 func (storage *SStorage) IsEmulated() bool { 161 return false 162 } 163 164 func (storage *SStorage) GetIZone() cloudprovider.ICloudZone { 165 zone, err := storage.region.GetZone(storage.ZoneUUID) 166 if err != nil { 167 log.Errorf("failed to find zone for storage %s(%s)", storage.Name, storage.UUID) 168 return nil 169 } 170 return zone 171 } 172 173 func (storage *SStorage) GetIDisks() ([]cloudprovider.ICloudDisk, error) { 174 disks, err := storage.region.GetDisks(storage.UUID, []string{}, "") 175 if err != nil { 176 return nil, err 177 } 178 idisks := []cloudprovider.ICloudDisk{} 179 for i := 0; i < len(disks); i++ { 180 disks[i].storage = storage 181 disks[i].region = storage.region 182 idisks = append(idisks, &disks[i]) 183 } 184 return idisks, nil 185 } 186 187 func (storage *SStorage) GetStorageType() string { 188 return strings.ToLower(string(storage.Type)) 189 } 190 191 func (storage *SStorage) GetMediumType() string { 192 return api.DISK_TYPE_ROTATE 193 } 194 195 func (storage *SStorage) GetCapacityMB() int64 { 196 return storage.TotalCapacity / 1024 / 1024 197 } 198 199 func (storage *SStorage) GetCapacityUsedMB() int64 { 200 return 0 201 } 202 203 func (storage *SStorage) GetStorageConf() jsonutils.JSONObject { 204 conf := jsonutils.NewDict() 205 return conf 206 } 207 208 func (storage *SStorage) Refresh() error { 209 // do nothing 210 return nil 211 } 212 213 func (storage *SStorage) GetEnabled() bool { 214 return true 215 } 216 217 func (storage *SStorage) GetIStoragecache() cloudprovider.ICloudStoragecache { 218 return &SStoragecache{ZoneId: storage.ZoneUUID, region: storage.region} 219 } 220 221 func (storage *SStorage) CreateIDisk(conf *cloudprovider.DiskCreateConfig) (cloudprovider.ICloudDisk, error) { 222 poolName, err := storage.GetDataPoolName() 223 if err != nil { 224 return nil, err 225 } 226 disk, err := storage.region.CreateDisk(conf.Name, storage.UUID, "", poolName, conf.SizeGb, conf.Desc) 227 if err != nil { 228 return nil, err 229 } 230 disk.storage = storage 231 return disk, nil 232 } 233 234 func (storage *SStorage) GetIDiskById(diskId string) (cloudprovider.ICloudDisk, error) { 235 disk, err := storage.region.GetDisk(diskId) 236 if err != nil { 237 return nil, err 238 } 239 if disk.PrimaryStorageUUID != storage.UUID { 240 return nil, cloudprovider.ErrNotFound 241 } 242 disk.region = storage.region 243 disk.storage = storage 244 return disk, nil 245 } 246 247 func (storage *SStorage) GetMountPoint() string { 248 poolName, _ := storage.GetDataPoolName() 249 if len(poolName) > 0 { 250 return fmt.Sprintf("ceph://%s", poolName) 251 } 252 return "" 253 } 254 255 func (storage *SStorage) IsSysDiskStore() bool { 256 return true 257 } 258 259 func (storage *SStorage) GetDataPoolName() (string, error) { 260 for _, pool := range storage.Pools { 261 if pool.Type == CephPoolTypeData { 262 return pool.PoolName, nil 263 } 264 } 265 return "", fmt.Errorf("failed to found storage %s(%s) data pool name", storage.Name, storage.UUID) 266 }