mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-11-05 23:41:47 +08:00
381 lines
11 KiB
Go
381 lines
11 KiB
Go
package azure
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"yunion.io/x/jsonutils"
|
|
"yunion.io/x/log"
|
|
"yunion.io/x/onecloud/pkg/cloudprovider"
|
|
"yunion.io/x/onecloud/pkg/compute/models"
|
|
|
|
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2018-04-01/compute"
|
|
)
|
|
|
|
type StorageAccountTypes string
|
|
|
|
const (
|
|
// StorageAccountTypesPremiumLRS ...
|
|
StorageAccountTypesPremiumLRS StorageAccountTypes = "Premium_LRS"
|
|
// StorageAccountTypesStandardLRS ...
|
|
StorageAccountTypesStandardLRS StorageAccountTypes = "Standard_LRS"
|
|
// StorageAccountTypesStandardSSDLRS ...
|
|
StorageAccountTypesStandardSSDLRS StorageAccountTypes = "StandardSSD_LRS"
|
|
)
|
|
|
|
type DiskSku struct {
|
|
Name StorageAccountTypes
|
|
Tier string
|
|
}
|
|
|
|
type ImageDiskReference struct {
|
|
ID string
|
|
Lun int32
|
|
}
|
|
|
|
type CreationData struct {
|
|
CreateOption string
|
|
StorageAccountID string
|
|
ImageReference ImageDiskReference
|
|
SourceURI string
|
|
SourceResourceID string
|
|
}
|
|
|
|
type DiskProperties struct {
|
|
TimeCreated time.Time
|
|
OsType OperatingSystemTypes
|
|
CreationData CreationData
|
|
DiskSizeGB int32
|
|
ProvisioningState string
|
|
}
|
|
|
|
type SDisk struct {
|
|
storage *SStorage
|
|
|
|
ManagedBy string
|
|
Sku DiskSku
|
|
Zones []string
|
|
ID string
|
|
Name string
|
|
Type string
|
|
Location string
|
|
Properties DiskProperties
|
|
|
|
Tags map[string]string
|
|
}
|
|
|
|
func (self *SRegion) CreateDisk(storageType string, name string, sizeGb int32, desc string, imageId string) (string, error) {
|
|
return self.createDisk(storageType, name, sizeGb, desc, imageId)
|
|
}
|
|
|
|
func (self *SRegion) createDisk(storageType string, name string, sizeGb int32, desc string, imageId string) (string, error) {
|
|
computeClient := compute.NewDisksClientWithBaseURI(self.client.baseUrl, self.client.subscriptionId)
|
|
computeClient.Authorizer = self.client.authorizer
|
|
sku := compute.DiskSku{Name: compute.StorageAccountTypes(storageType)}
|
|
properties := compute.DiskProperties{DiskSizeGB: &sizeGb, CreationData: &compute.CreationData{CreateOption: compute.Empty}}
|
|
if len(imageId) > 0 {
|
|
globalId, _, _ := pareResourceGroupWithName(imageId, IMAGE_RESOURCE)
|
|
if image, err := self.GetImage(globalId); err != nil {
|
|
return "", err
|
|
} else if blobUri := image.GetBlobUri(); len(blobUri) == 0 {
|
|
return "", fmt.Errorf("failed to find blobUri for image %s", image.Name)
|
|
} else {
|
|
properties.CreationData = &compute.CreationData{
|
|
CreateOption: compute.Import,
|
|
SourceURI: &blobUri,
|
|
}
|
|
properties.OsType = compute.OperatingSystemTypes(image.GetOsType())
|
|
}
|
|
}
|
|
disk := compute.Disk{Name: &name, Location: &self.Name, DiskProperties: &properties, Sku: &sku}
|
|
diskId, resourceGroup, diskName := pareResourceGroupWithName(name, DISK_RESOURCE)
|
|
//log.Debugf("Create disk: %s", jsonutils.Marshal(disk).PrettyString())
|
|
self.CreateResourceGroup(resourceGroup)
|
|
if result, err := computeClient.CreateOrUpdate(context.Background(), resourceGroup, diskName, disk); err != nil {
|
|
return "", err
|
|
} else if err := result.WaitForCompletion(context.Background(), computeClient.Client); err != nil {
|
|
return "", err
|
|
} else {
|
|
return diskId, nil
|
|
}
|
|
}
|
|
|
|
func (self *SRegion) DeleteDisk(diskId string) error {
|
|
return self.deleteDisk(diskId)
|
|
}
|
|
|
|
func (self *SRegion) deleteDisk(diskId string) error {
|
|
diskClient := compute.NewDisksClientWithBaseURI(self.client.baseUrl, self.client.subscriptionId)
|
|
diskClient.Authorizer = self.client.authorizer
|
|
_, resourceGroup, name := pareResourceGroupWithName(diskId, DISK_RESOURCE)
|
|
if result, err := diskClient.Delete(context.Background(), resourceGroup, name); err != nil {
|
|
return err
|
|
} else if err := result.WaitForCompletion(context.Background(), diskClient.Client); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (self *SRegion) ResizeDisk(diskId string, sizeGb int32) error {
|
|
return self.resizeDisk(diskId, sizeGb)
|
|
}
|
|
|
|
func (self *SRegion) resizeDisk(diskId string, sizeGb int32) error {
|
|
diskClient := compute.NewDisksClientWithBaseURI(self.client.baseUrl, self.client.subscriptionId)
|
|
diskClient.Authorizer = self.client.authorizer
|
|
_, resourceGroup, diskName := pareResourceGroupWithName(diskId, DISK_RESOURCE)
|
|
params := compute.DiskUpdate{
|
|
DiskUpdateProperties: &compute.DiskUpdateProperties{
|
|
DiskSizeGB: &sizeGb,
|
|
},
|
|
}
|
|
if result, err := diskClient.Update(context.Background(), resourceGroup, diskName, params); err != nil {
|
|
return err
|
|
} else if err := result.WaitForCompletion(context.Background(), diskClient.Client); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (self *SRegion) GetDisk(diskId string) (*SDisk, error) {
|
|
disk := SDisk{}
|
|
computeClient := compute.NewDisksClientWithBaseURI(self.client.baseUrl, self.client.subscriptionId)
|
|
computeClient.Authorizer = self.client.authorizer
|
|
_, resourceGroup, diskName := pareResourceGroupWithName(diskId, DISK_RESOURCE)
|
|
if len(diskId) == 0 {
|
|
return nil, cloudprovider.ErrNotFound
|
|
}
|
|
if _disk, err := computeClient.Get(context.Background(), resourceGroup, diskName); err != nil {
|
|
if _disk.Response.StatusCode == 404 {
|
|
return nil, cloudprovider.ErrNotFound
|
|
}
|
|
return nil, err
|
|
} else if err := jsonutils.Update(&disk, _disk); err != nil {
|
|
return nil, err
|
|
} else {
|
|
return &disk, nil
|
|
}
|
|
}
|
|
|
|
func (self *SRegion) GetDisks() ([]SDisk, error) {
|
|
disks := make([]SDisk, 0)
|
|
computeClient := compute.NewDisksClientWithBaseURI(self.client.baseUrl, self.client.subscriptionId)
|
|
computeClient.Authorizer = self.client.authorizer
|
|
if diskList, err := computeClient.List(context.Background()); err != nil {
|
|
return nil, err
|
|
} else {
|
|
for _, _disk := range diskList.Values() {
|
|
if *_disk.Location == self.Name {
|
|
disk := SDisk{}
|
|
if err := jsonutils.Update(&disk, _disk); err != nil {
|
|
return disks, err
|
|
}
|
|
disks = append(disks, disk)
|
|
}
|
|
}
|
|
}
|
|
return disks, nil
|
|
}
|
|
|
|
func (self *SDisk) GetMetadata() *jsonutils.JSONDict {
|
|
data := jsonutils.NewDict()
|
|
data.Add(jsonutils.NewString(models.HYPERVISOR_AZURE), "hypervisor")
|
|
return data
|
|
}
|
|
|
|
func (self *SDisk) GetStatus() string {
|
|
status := self.Properties.ProvisioningState
|
|
switch status {
|
|
case "Updating":
|
|
return models.DISK_ALLOCATING
|
|
case "Succeeded":
|
|
return models.DISK_READY
|
|
default:
|
|
log.Errorf("Unknow azure disk status: %s", status)
|
|
return models.DISK_UNKNOWN
|
|
}
|
|
}
|
|
|
|
func (self *SDisk) GetId() string {
|
|
return self.ID
|
|
}
|
|
|
|
func (self *SDisk) Refresh() error {
|
|
if disk, err := self.storage.zone.region.GetDisk(self.ID); err != nil {
|
|
return cloudprovider.ErrNotFound
|
|
} else {
|
|
return jsonutils.Update(self, disk)
|
|
}
|
|
}
|
|
|
|
func (self *SDisk) Delete() error {
|
|
return self.storage.zone.region.deleteDisk(self.ID)
|
|
}
|
|
|
|
func (self *SDisk) Resize(size int64) error {
|
|
return self.storage.zone.region.resizeDisk(self.ID, int32(size))
|
|
}
|
|
|
|
func (self *SDisk) GetName() string {
|
|
if len(self.Name) > 0 {
|
|
return self.Name
|
|
}
|
|
return self.ID
|
|
}
|
|
|
|
func (self *SDisk) GetGlobalId() string {
|
|
return strings.ToLower(self.ID)
|
|
}
|
|
|
|
func (self *SDisk) IsEmulated() bool {
|
|
return false
|
|
}
|
|
|
|
func (self *SDisk) GetIStorge() cloudprovider.ICloudStorage {
|
|
return self.storage
|
|
}
|
|
|
|
func (self *SDisk) GetFsFormat() string {
|
|
return ""
|
|
}
|
|
|
|
func (self *SDisk) GetIsNonPersistent() bool {
|
|
return false
|
|
}
|
|
|
|
func (self *SDisk) GetDriver() string {
|
|
return "scsi"
|
|
}
|
|
|
|
func (self *SDisk) GetCacheMode() string {
|
|
return "none"
|
|
}
|
|
|
|
func (self *SDisk) GetMountpoint() string {
|
|
return ""
|
|
}
|
|
|
|
func (self *SDisk) GetDiskFormat() string {
|
|
return "vhd"
|
|
}
|
|
|
|
func (self *SDisk) GetDiskSizeMB() int {
|
|
return int(self.Properties.DiskSizeGB) * 1024
|
|
}
|
|
|
|
func (self *SDisk) GetIsAutoDelete() bool {
|
|
return false
|
|
}
|
|
|
|
func (self *SDisk) GetTemplateId() string {
|
|
return self.Properties.CreationData.ImageReference.ID
|
|
}
|
|
|
|
func (self *SDisk) GetDiskType() string {
|
|
if len(self.Properties.OsType) > 0 {
|
|
return models.DISK_TYPE_SYS
|
|
}
|
|
return models.DISK_TYPE_DATA
|
|
}
|
|
|
|
func (self *SDisk) CreateISnapshot(name, desc string) (cloudprovider.ICloudSnapshot, error) {
|
|
if snapshot, err := self.storage.zone.region.CreateSnapshot(self.ID, name, desc); err != nil {
|
|
log.Errorf("createSnapshot fail %s", err)
|
|
return nil, err
|
|
} else {
|
|
return snapshot, nil
|
|
}
|
|
}
|
|
|
|
func (self *SDisk) GetISnapshot(snapshotId string) (cloudprovider.ICloudSnapshot, error) {
|
|
return self.GetSnapshotDetail(snapshotId)
|
|
}
|
|
|
|
func (self *SDisk) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
|
|
if snapshots, err := self.storage.zone.region.GetSnapShots(self.ID); err != nil {
|
|
return nil, err
|
|
} else {
|
|
isnapshots := make([]cloudprovider.ICloudSnapshot, len(snapshots))
|
|
for i := 0; i < len(snapshots); i++ {
|
|
isnapshots[i] = &snapshots[i]
|
|
}
|
|
return isnapshots, nil
|
|
}
|
|
}
|
|
|
|
func (self *SDisk) GetBillingType() string {
|
|
return models.BILLING_TYPE_POSTPAID
|
|
}
|
|
|
|
func (self *SDisk) GetExpiredAt() time.Time {
|
|
return time.Now()
|
|
}
|
|
|
|
func (self *SDisk) GetSnapshotDetail(snapshotId string) (*SSnapshot, error) {
|
|
if snapshot, err := self.storage.zone.region.GetSnapshotDetail(snapshotId); err != nil {
|
|
return nil, err
|
|
} else if snapshot.Properties.CreationData.SourceResourceID != self.ID {
|
|
return nil, cloudprovider.ErrNotFound
|
|
} else {
|
|
return snapshot, nil
|
|
}
|
|
}
|
|
|
|
func (region *SRegion) GetSnapshotDetail(snapshotId string) (*SSnapshot, error) {
|
|
snapshot := SSnapshot{}
|
|
_, resourceGroup, snapshotName := pareResourceGroupWithName(snapshotId, SNAPSHOT_RESOURCE)
|
|
snapClient := compute.NewSnapshotsClientWithBaseURI(region.client.baseUrl, region.SubscriptionID)
|
|
snapClient.Authorizer = region.client.authorizer
|
|
if result, err := snapClient.Get(context.Background(), resourceGroup, snapshotName); err != nil {
|
|
if result.Response.StatusCode == 404 {
|
|
return nil, cloudprovider.ErrNotFound
|
|
}
|
|
return nil, err
|
|
} else if err := jsonutils.Update(&snapshot, result); err != nil {
|
|
return nil, err
|
|
}
|
|
snapshot.region = region
|
|
return &snapshot, nil
|
|
}
|
|
|
|
func (region *SRegion) GetSnapShots(diskId string) ([]SSnapshot, error) {
|
|
snapshots := []SSnapshot{}
|
|
snapClient := compute.NewSnapshotsClientWithBaseURI(region.client.baseUrl, region.SubscriptionID)
|
|
snapClient.Authorizer = region.client.authorizer
|
|
if result, err := snapClient.List(context.Background()); err != nil {
|
|
return nil, err
|
|
} else if len(diskId) > 0 {
|
|
globalId, _, _ := pareResourceGroupWithName(diskId, DISK_RESOURCE)
|
|
data := result.Values()
|
|
for i := 0; i < len(data); i++ {
|
|
sourceId := *data[i].CreationData.SourceResourceID
|
|
if len(sourceId) > 0 {
|
|
snap := SSnapshot{}
|
|
_globalId, _, _ := pareResourceGroupWithName(sourceId, DISK_RESOURCE)
|
|
if globalId == _globalId {
|
|
if err := jsonutils.Update(&snap, data[i]); err != nil {
|
|
return nil, err
|
|
}
|
|
snapshots = append(snapshots, snap)
|
|
}
|
|
}
|
|
}
|
|
} else if err := jsonutils.Update(&snapshots, result.Values()); err != nil {
|
|
return snapshots, nil
|
|
}
|
|
for i := 0; i < len(snapshots); i++ {
|
|
snapshots[i].region = region
|
|
}
|
|
return snapshots, nil
|
|
}
|
|
|
|
func (self *SDisk) Reset(snapshotId string) error {
|
|
return self.storage.zone.region.resetDisk(self.ID, snapshotId)
|
|
}
|
|
|
|
func (self *SRegion) resetDisk(diskId, snapshotId string) error {
|
|
return cloudprovider.ErrNotSupported
|
|
}
|