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  }