diff --git a/cmd/climc/shell/cloudaccounts.go b/cmd/climc/shell/cloudaccounts.go index 41cedb17ee..46b7edbdc7 100644 --- a/cmd/climc/shell/cloudaccounts.go +++ b/cmd/climc/shell/cloudaccounts.go @@ -167,6 +167,17 @@ func init() { return nil }) + R(&options.SZStackCloudAccountCreateOptions{}, "cloud-account-create-zstack", "Create a ZStack cloud account", func(s *mcclient.ClientSession, args *options.SZStackCloudAccountCreateOptions) error { + params := jsonutils.Marshal(args) + params.(*jsonutils.JSONDict).Add(jsonutils.NewString("ZStack"), "provider") + result, err := modules.Cloudaccounts.Create(s, params) + if err != nil { + return err + } + printObject(result) + return nil + }) + type CloudaccountUpdateOptions struct { ID string `help:"ID or Name of cloud account"` Name string `help:"New name to update"` @@ -305,6 +316,19 @@ func init() { return nil }) + R(&options.SZStackCloudAccountUpdateOptions{}, "cloud-account-update-zstack", "update a ZStack cloud account", func(s *mcclient.ClientSession, args *options.SZStackCloudAccountUpdateOptions) error { + params := jsonutils.Marshal(args).(*jsonutils.JSONDict) + if params.Size() == 0 { + return InvalidUpdateError() + } + result, err := modules.Cloudaccounts.Update(s, args.ID, params) + if err != nil { + return err + } + printObject(result) + return nil + }) + type CloudaccountShowOptions struct { ID string `help:"ID or Name of cloud account"` } diff --git a/pkg/apis/compute/guest_const.go b/pkg/apis/compute/guest_const.go index f28ea13428..75d351f8cc 100644 --- a/pkg/apis/compute/guest_const.go +++ b/pkg/apis/compute/guest_const.go @@ -124,6 +124,7 @@ const ( HYPERVISOR_HUAWEI = "huawei" HYPERVISOR_OPENSTACK = "openstack" HYPERVISOR_UCLOUD = "ucloud" + HYPERVISOR_ZSTACK = "zstack" // HYPERVISOR_DEFAULT = HYPERVISOR_KVM HYPERVISOR_DEFAULT = HYPERVISOR_KVM @@ -143,6 +144,7 @@ var HYPERVISORS = []string{HYPERVISOR_KVM, HYPERVISOR_HUAWEI, HYPERVISOR_OPENSTACK, HYPERVISOR_UCLOUD, + HYPERVISOR_ZSTACK, } var PUBLIC_CLOUD_HYPERVISORS = []string{ @@ -153,6 +155,7 @@ var PUBLIC_CLOUD_HYPERVISORS = []string{ HYPERVISOR_HUAWEI, HYPERVISOR_OPENSTACK, HYPERVISOR_UCLOUD, + HYPERVISOR_ZSTACK, } // var HYPERVISORS = []string{HYPERVISOR_ALIYUN} @@ -169,6 +172,7 @@ var HYPERVISOR_HOSTTYPE = map[string]string{ HYPERVISOR_HUAWEI: HOST_TYPE_HUAWEI, HYPERVISOR_OPENSTACK: HOST_TYPE_OPENSTACK, HYPERVISOR_UCLOUD: HOST_TYPE_UCLOUD, + HYPERVISOR_ZSTACK: HOST_TYPE_ZSTACK, } var HOSTTYPE_HYPERVISOR = map[string]string{ @@ -183,6 +187,7 @@ var HOSTTYPE_HYPERVISOR = map[string]string{ HOST_TYPE_HUAWEI: HYPERVISOR_HUAWEI, HOST_TYPE_OPENSTACK: HYPERVISOR_OPENSTACK, HOST_TYPE_UCLOUD: HYPERVISOR_UCLOUD, + HOST_TYPE_ZSTACK: HYPERVISOR_ZSTACK, } const ( diff --git a/pkg/cloudprovider/images.go b/pkg/cloudprovider/images.go index 56d24aec35..9ad10a7b52 100644 --- a/pkg/cloudprovider/images.go +++ b/pkg/cloudprovider/images.go @@ -67,7 +67,7 @@ func CloudImage2Image(image ICloudImage) SImage { "os_arch": image.GetOsArch(), }, Protected: true, - SizeBytes: image.GetSize(), + SizeBytes: image.GetSizeByte(), Status: image.GetImageStatus(), } } diff --git a/pkg/cloudprovider/resources.go b/pkg/cloudprovider/resources.go index 6eafa8e166..f05cf2a719 100644 --- a/pkg/cloudprovider/resources.go +++ b/pkg/cloudprovider/resources.go @@ -116,7 +116,7 @@ type ICloudImage interface { Delete(ctx context.Context) error GetIStoragecache() ICloudStoragecache - GetSize() int64 + GetSizeByte() int64 GetImageType() string GetImageStatus() string GetOsType() string @@ -154,7 +154,7 @@ type ICloudStorage interface { GetStorageType() string GetMediumType() string - GetCapacityMB() int // MB + GetCapacityMB() int64 // MB GetStorageConf() jsonutils.JSONObject GetEnabled() bool @@ -184,7 +184,7 @@ type ICloudHost interface { GetAccessMac() string // GetSysInfo() jsonutils.JSONObject GetSN() string - GetCpuCount() int8 + GetCpuCount() int GetNodeCount() int8 GetCpuDesc() string GetCpuMhz() int @@ -216,7 +216,7 @@ type ICloudVM interface { // GetStatus() string // GetRemoteStatus() string - GetVcpuCount() int8 + GetVcpuCount() int GetVmemSizeMB() int //MB GetBootOrder() string GetVga() string diff --git a/pkg/compute/guestdrivers/kvm.go b/pkg/compute/guestdrivers/kvm.go index 92039e9e4e..c385b187be 100644 --- a/pkg/compute/guestdrivers/kvm.go +++ b/pkg/compute/guestdrivers/kvm.go @@ -416,7 +416,7 @@ func (self *SKVMGuestDriver) OnGuestChangeCpuMemFailed(ctx context.Context, gues } if cpuAdded > 0 { _, err := db.Update(guest, func() error { - guest.VcpuCount = guest.VcpuCount + int8(cpuAdded) + guest.VcpuCount = guest.VcpuCount + int(cpuAdded) return nil }) if err != nil { diff --git a/pkg/compute/models/cachedimages.go b/pkg/compute/models/cachedimages.go index 692988b6cc..d16a4b3c87 100644 --- a/pkg/compute/models/cachedimages.go +++ b/pkg/compute/models/cachedimages.go @@ -419,7 +419,7 @@ func (self *SCachedimage) canDeleteLastCache() bool { func (self *SCachedimage) syncWithCloudImage(ctx context.Context, userCred mcclient.TokenCredential, image cloudprovider.ICloudImage) error { diff, err := db.UpdateWithLock(ctx, self, func() error { self.Name = image.GetName() - self.Size = image.GetSize() + self.Size = image.GetSizeByte() self.ExternalId = image.GetGlobalId() self.ImageType = image.GetImageType() sImage := cloudprovider.CloudImage2Image(image) @@ -444,7 +444,7 @@ func (manager *SCachedimageManager) newFromCloudImage(ctx context.Context, userC } cachedImage.Name = newName - cachedImage.Size = image.GetSize() + cachedImage.Size = image.GetSizeByte() sImage := cloudprovider.CloudImage2Image(image) cachedImage.Info = jsonutils.Marshal(&sImage) cachedImage.LastSync = time.Now().UTC() diff --git a/pkg/compute/models/disks.go b/pkg/compute/models/disks.go index 195d42e1d2..81938a4063 100644 --- a/pkg/compute/models/disks.go +++ b/pkg/compute/models/disks.go @@ -432,7 +432,7 @@ func (manager *SDiskManager) validateDiskOnStorage(diskConfig *api.DiskConfig, s if len(hoststorage) == 0 { return httperrors.NewInputParameterError("Storage[%s] must attach to a host", storage.Name) } - if diskConfig.SizeMb > storage.GetFreeCapacity() && !storage.IsEmulated { + if int64(diskConfig.SizeMb) > storage.GetFreeCapacity() && !storage.IsEmulated { return httperrors.NewInputParameterError("Not enough free space") } return nil @@ -716,7 +716,7 @@ func (self *SDisk) PerformResize(ctx context.Context, userCred mcclient.TokenCre return nil, httperrors.NewInputParameterError(err.Error()) } } - if addDisk > storage.GetFreeCapacity() && !storage.IsEmulated { + if int64(addDisk) > storage.GetFreeCapacity() && !storage.IsEmulated { return nil, httperrors.NewOutOfResourceError("Not enough free space") } if guests := self.GetGuests(); len(guests) > 0 { @@ -1065,6 +1065,12 @@ func (self *SDisk) syncWithCloudDisk(ctx context.Context, userCred mcclient.Toke self.AutoDelete = true } // self.TemplateId = extDisk.GetTemplateId() no sync template ID + if templateId := extDisk.GetTemplateId(); len(templateId) > 0 { + cachedImage, err := CachedimageManager.FetchByExternalId(templateId) + if err == nil && cachedImage != nil { + self.TemplateId = cachedImage.GetId() + } + } self.DiskType = extDisk.GetDiskType() if index == 0 { self.DiskType = api.DISK_TYPE_SYS diff --git a/pkg/compute/models/guest_actions.go b/pkg/compute/models/guest_actions.go index 7912628904..c32b4637a7 100644 --- a/pkg/compute/models/guest_actions.go +++ b/pkg/compute/models/guest_actions.go @@ -1312,7 +1312,7 @@ func (self *SGuest) PerformCreatedisk(ctx context.Context, userCred mcclient.Tok logclient.AddActionLogWithContext(ctx, self, logclient.ACT_CREATE, "No valid storage on current host", userCred, false) return nil, httperrors.NewBadRequestError("No valid storage on current host") } - if storage.GetCapacity() > 0 && storage.GetCapacity() < size { + if storage.GetCapacity() > 0 && storage.GetCapacity() < int64(size) { logclient.AddActionLogWithContext(ctx, self, logclient.ACT_CREATE, "Not eough storage space on current host", userCred, false) return nil, httperrors.NewBadRequestError("Not eough storage space on current host") } @@ -1943,7 +1943,7 @@ func (self *SGuest) PerformChangeConfig(ctx context.Context, userCred mcclient.T return nil, httperrors.NewBadRequestError("Fetch storage error: %s", err) } storage := iStorage.(*SStorage) - if storage.GetFreeCapacity() < needSize { + if storage.GetFreeCapacity() < int64(needSize) { return nil, httperrors.NewInsufficientResourceError("Not enough free space") } } @@ -3049,7 +3049,7 @@ func (man *SGuestManager) createImportGuest(ctx context.Context, userCred mcclie gst.Status = api.VM_IMPORT gst.Hypervisor = desc.Hypervisor gst.VmemSize = desc.MemSizeMb - gst.VcpuCount = int8(desc.Cpu) + gst.VcpuCount = desc.Cpu gst.BootOrder = desc.BootOrder gst.Description = desc.Description err = man.TableSpec().Insert(gst) diff --git a/pkg/compute/models/guests.go b/pkg/compute/models/guests.go index 9007399b45..6d652da488 100644 --- a/pkg/compute/models/guests.go +++ b/pkg/compute/models/guests.go @@ -217,8 +217,8 @@ type SGuest struct { SBillingResourceBase - VcpuCount int8 `nullable:"false" default:"1" list:"user" create:"optional"` // Column(TINYINT, nullable=False, default=1) - VmemSize int `nullable:"false" list:"user" create:"required"` // Column(Integer, nullable=False) + VcpuCount int `nullable:"false" default:"1" list:"user" create:"optional"` // Column(TINYINT, nullable=False, default=1) + VmemSize int `nullable:"false" list:"user" create:"required"` // Column(Integer, nullable=False) BootOrder string `width:"8" charset:"ascii" nullable:"true" default:"cdn" list:"user" update:"user" create:"optional"` // Column(VARCHAR(8, charset='ascii'), nullable=True, default='cdn') diff --git a/pkg/compute/models/host_recycle.go b/pkg/compute/models/host_recycle.go index 12a86202c4..a4af4ebee2 100644 --- a/pkg/compute/models/host_recycle.go +++ b/pkg/compute/models/host_recycle.go @@ -17,6 +17,7 @@ package models import ( "context" "fmt" + // "strings" "time" @@ -207,13 +208,13 @@ func (self *SGuest) doPrepaidRecycleNoLock(ctx context.Context, userCred mcclien } } - storageSize := 0 + storageSize := int64(0) var externalId string for i := 0; i < len(guestdisks); i += 1 { disk := guestdisks[i].GetDisk() storage := disk.GetStorage() if disk.BillingType == billing_api.BILLING_TYPE_PREPAID { - storageSize += disk.DiskSize + storageSize += int64(disk.DiskSize) if len(externalId) == 0 { externalId = storage.ExternalId } else { diff --git a/pkg/compute/models/hosts.go b/pkg/compute/models/hosts.go index e1f80beebf..537797205c 100644 --- a/pkg/compute/models/hosts.go +++ b/pkg/compute/models/hosts.go @@ -153,12 +153,12 @@ type SHost struct { SysInfo jsonutils.JSONObject `nullable:"true" search:"admin" list:"admin" update:"admin" create:"admin_optional"` // Column(JSONEncodedDict, nullable=True) SN string `width:"128" charset:"ascii" nullable:"true" list:"admin" update:"admin" create:"admin_optional"` // Column(VARCHAR(128, charset='ascii'), nullable=True) - CpuCount int8 `nullable:"true" list:"admin" update:"admin" create:"admin_optional"` // Column(TINYINT, nullable=True) # cpu count + CpuCount int `nullable:"true" list:"admin" update:"admin" create:"admin_optional"` // Column(TINYINT, nullable=True) # cpu count NodeCount int8 `nullable:"true" list:"admin" update:"admin" create:"admin_optional"` // Column(TINYINT, nullable=True) CpuDesc string `width:"64" charset:"ascii" nullable:"true" get:"admin" update:"admin" create:"admin_optional"` // Column(VARCHAR(64, charset='ascii'), nullable=True) CpuMhz int `nullable:"true" get:"admin" update:"admin" create:"admin_optional"` // Column(Integer, nullable=True) # cpu MHz CpuCache int `nullable:"true" get:"admin" update:"admin" create:"admin_optional"` // Column(Integer, nullable=True) # cpu Cache in KB - CpuReserved int8 `nullable:"true" default:"0" list:"admin" update:"admin" create:"admin_optional"` // Column(TINYINT, nullable=True, default=0) + CpuReserved int `nullable:"true" default:"0" list:"admin" update:"admin" create:"admin_optional"` // Column(TINYINT, nullable=True, default=0) CpuCmtbound float32 `nullable:"true" default:"8" list:"admin" update:"admin" create:"admin_optional"` // = Column(Float, nullable=True) MemSize int `nullable:"true" list:"admin" update:"admin" create:"admin_optional"` // Column(Integer, nullable=True) # memory size in MB @@ -703,7 +703,7 @@ func (self *SHost) PerformUpdateStorage( // 1. create storage storage := SStorage{} storage.Name = fmt.Sprintf("storage%s", self.GetName()) - storage.Capacity = int(capacity) + storage.Capacity = capacity storage.StorageType = api.STORAGE_BAREMETAL storage.MediumType = self.StorageType storage.Cmtbound = 1.0 @@ -719,7 +719,7 @@ func (self *SHost) PerformUpdateStorage( bmStorage := SHoststorage{} bmStorage.HostId = self.Id bmStorage.StorageId = storage.Id - bmStorage.RealCapacity = int(capacity) + bmStorage.RealCapacity = capacity bmStorage.MountPoint = "" err = HoststorageManager.TableSpec().Insert(&bmStorage) if err != nil { @@ -732,7 +732,7 @@ func (self *SHost) PerformUpdateStorage( storage := bs.GetStorage() if capacity != int64(storage.Capacity) { diff, err := db.Update(storage, func() error { - storage.Capacity = int(capacity) + storage.Capacity = capacity return nil }) if err != nil { @@ -1010,13 +1010,13 @@ func (self *SHost) GetHardwareSpecification() *jsonutils.JSONDict { } type SStorageCapacity struct { - Capacity int `json:"capacity,omitzero"` - Used int `json:"used_capacity,omitzero"` - Wasted int `json:"waste_capacity,omitzero"` - VCapacity int `json:"virtual_capacity,omitzero"` + Capacity int64 `json:"capacity,omitzero"` + Used int64 `json:"used_capacity,omitzero"` + Wasted int64 `json:"waste_capacity,omitzero"` + VCapacity int64 `json:"virtual_capacity,omitzero"` } -func (cap *SStorageCapacity) GetFree() int { +func (cap *SStorageCapacity) GetFree() int64 { return cap.VCapacity - cap.Used - cap.Wasted } @@ -1053,7 +1053,7 @@ func (self *SHost) GetAttachedStorageCapacity() SStorageCapacity { func _getLeastUsedStorage(storages []SStorage, backends []string) *SStorage { var best *SStorage - var bestCap int + var bestCap int64 for i := 0; i < len(storages); i++ { s := storages[i] if len(backends) > 0 { @@ -2984,7 +2984,7 @@ func (self *SHost) PerformInitialize( "is_fake_baremetal_server": true, "host_ip": self.AccessIp}, userCred) caps := self.GetAttachedStorageCapacity() - diskConfig := &api.DiskConfig{SizeMb: caps.GetFree()} + diskConfig := &api.DiskConfig{SizeMb: int(caps.GetFree())} err = guest.CreateDisksOnHost(ctx, userCred, self, []*api.DiskConfig{diskConfig}, nil, true, true, nil, nil) if err != nil { log.Errorf("Host perform initialize failed on create disk %s", err) @@ -3666,7 +3666,7 @@ func (self *SHost) UpdateDiskConfig(userCred mcclient.TokenCredential, layouts [ for i := 0; i < len(layouts); i++ { size += layouts[i].Size } - bs.RealCapacity = int(size) + bs.RealCapacity = size } else { bs.Config = jsonutils.NewArray() bs.RealCapacity = bs.GetStorage().Capacity diff --git a/pkg/compute/models/hoststorages.go b/pkg/compute/models/hoststorages.go index 0a7a18495f..7430f51980 100644 --- a/pkg/compute/models/hoststorages.go +++ b/pkg/compute/models/hoststorages.go @@ -59,7 +59,7 @@ type SHoststorage struct { StorageId string `width:"36" charset:"ascii" nullable:"false" list:"admin" create:"required"` // Column(VARCHAR(36, charset='ascii'), nullable=False) Config *jsonutils.JSONArray `nullable:"true" get:"admin"` // Column(JSONEncodedDict, nullable=True) - RealCapacity int `nullable:"true" list:"admin"` // Column(Integer, nullable=True) + RealCapacity int64 `nullable:"true" list:"admin"` // Column(Integer, nullable=True) } func (joint *SHoststorage) Master() db.IStandaloneModel { diff --git a/pkg/compute/models/storages.go b/pkg/compute/models/storages.go index a6c83b0973..34a67f2b73 100644 --- a/pkg/compute/models/storages.go +++ b/pkg/compute/models/storages.go @@ -130,8 +130,8 @@ type SStorage struct { db.SStandaloneResourceBase SManagedResourceBase - Capacity int `nullable:"false" list:"admin" update:"admin" create:"admin_required"` // Column(Integer, nullable=False) # capacity of disk in MB - Reserved int `nullable:"true" default:"0" list:"admin" update:"admin"` // Column(Integer, nullable=True, default=0) + Capacity int64 `nullable:"false" list:"admin" update:"admin" create:"admin_required"` // Column(Integer, nullable=False) # capacity of disk in MB + Reserved int64 `nullable:"true" default:"0" list:"admin" update:"admin"` // Column(Integer, nullable=True, default=0) StorageType string `width:"32" charset:"ascii" nullable:"false" list:"user" update:"admin" create:"admin_required"` // Column(VARCHAR(32, charset='ascii'), nullable=False) MediumType string `width:"32" charset:"ascii" nullable:"false" list:"user" update:"admin" create:"admin_required"` // Column(VARCHAR(32, charset='ascii'), nullable=False) Cmtbound float32 `nullable:"true" default:"1" list:"admin" update:"admin"` // Column(Float, nullable=True) @@ -394,7 +394,7 @@ func (self *SStorage) getStorageCapacity() SStorageCapacity { capa.Capacity = self.GetCapacity() capa.Used = self.GetUsedCapacity(tristate.True) capa.Wasted = self.GetUsedCapacity(tristate.False) - capa.VCapacity = int(float32(self.GetCapacity()) * self.GetOvercommitBound()) + capa.VCapacity = int64(float32(self.GetCapacity()) * self.GetOvercommitBound()) return capa } @@ -425,7 +425,7 @@ func (self *SStorage) GetExtraDetails(ctx context.Context, userCred mcclient.Tok return self.getMoreDetails(ctx, extra), nil } -func (self *SStorage) GetUsedCapacity(isReady tristate.TriState) int { +func (self *SStorage) GetUsedCapacity(isReady tristate.TriState) int64 { disks := DiskManager.Query().SubQuery() q := disks.Query(sqlchemy.SUM("sum", disks.Field("disk_size"))).Equals("storage_id", self.Id) switch isReady { @@ -435,7 +435,7 @@ func (self *SStorage) GetUsedCapacity(isReady tristate.TriState) int { q = q.NotEquals("status", api.DISK_READY) } row := q.Row() - var sum int + var sum int64 err := row.Scan(&sum) if err != nil { log.Errorf("GetUsedCapacity fail: %s", err) @@ -508,16 +508,16 @@ func (self *SStorage) GetRegion() *SCloudregion { return zone.GetRegion() } -func (self *SStorage) GetReserved() int { +func (self *SStorage) GetReserved() int64 { return self.Reserved } -func (self *SStorage) GetCapacity() int { +func (self *SStorage) GetCapacity() int64 { return self.Capacity - self.GetReserved() } -func (self *SStorage) GetFreeCapacity() int { - return int(float32(self.GetCapacity())*self.GetOvercommitBound()) - self.GetUsedCapacity(tristate.None) +func (self *SStorage) GetFreeCapacity() int64 { + return int64(float32(self.GetCapacity())*self.GetOvercommitBound()) - self.GetUsedCapacity(tristate.None) } func (self *SStorage) GetAttachedHosts() []SHost { diff --git a/pkg/compute/service/service.go b/pkg/compute/service/service.go index bcb6c6c518..c51824e009 100644 --- a/pkg/compute/service/service.go +++ b/pkg/compute/service/service.go @@ -42,6 +42,7 @@ import ( _ "yunion.io/x/onecloud/pkg/util/openstack/provider" _ "yunion.io/x/onecloud/pkg/util/qcloud/provider" _ "yunion.io/x/onecloud/pkg/util/ucloud/provider" + _ "yunion.io/x/onecloud/pkg/util/zstack/provider" ) func StartService() { diff --git a/pkg/compute/tasks/guest_change_config_task.go b/pkg/compute/tasks/guest_change_config_task.go index 1dee670c2f..77c19c8d93 100644 --- a/pkg/compute/tasks/guest_change_config_task.go +++ b/pkg/compute/tasks/guest_change_config_task.go @@ -165,7 +165,7 @@ func (self *GuestChangeConfigTask) OnGuestChangeCpuMemSpecComplete(ctx context.C _, err := db.Update(guest, func() error { if vcpuCount > 0 { - guest.VcpuCount = int8(vcpuCount) + guest.VcpuCount = int(vcpuCount) } if vmemSize > 0 { guest.VmemSize = int(vmemSize) diff --git a/pkg/mcclient/options/cloudaccounts.go b/pkg/mcclient/options/cloudaccounts.go index 0761cd7878..daf5ffe156 100644 --- a/pkg/mcclient/options/cloudaccounts.go +++ b/pkg/mcclient/options/cloudaccounts.go @@ -125,6 +125,12 @@ type SUcloudCloudAccountCreateOptions struct { SAccessKeyCredential } +type SZStackCloudAccountCreateOptions struct { + SCloudAccountCreateBaseOptions + SUserPasswordCredential + AuthURL string `help:"ZStack auth_url" positional:"true" json:"auth_url"` +} + // update credential options type SCloudAccountUpdateCredentialBaseOptions struct { @@ -211,3 +217,8 @@ type SOpenStackCloudAccountUpdateOptions struct { type SHuaweiCloudAccountUpdateOptions struct { SCloudAccountUpdateBaseOptions } + +type SZStackCloudAccountUpdateOptions struct { + SCloudAccountUpdateBaseOptions + SUserPasswordCredential +} diff --git a/pkg/scheduler/algorithm/predicates/disk_schedtag_predicate.go b/pkg/scheduler/algorithm/predicates/disk_schedtag_predicate.go index 4c5884d61c..1cf30b6f4d 100644 --- a/pkg/scheduler/algorithm/predicates/disk_schedtag_predicate.go +++ b/pkg/scheduler/algorithm/predicates/disk_schedtag_predicate.go @@ -116,7 +116,7 @@ func (p *DiskSchedtagPredicate) DoSelect( return p.GetUsedStorages(res, input.(*diskW).Backend) } -func (p *DiskSchedtagPredicate) GetCandidateResourceSortScore(selectRes ISchedtagCandidateResource) int { +func (p *DiskSchedtagPredicate) GetCandidateResourceSortScore(selectRes ISchedtagCandidateResource) int64 { return selectRes.(*api.CandidateStorage).GetFreeCapacity() } diff --git a/pkg/scheduler/algorithm/predicates/network_schedtag_predicate.go b/pkg/scheduler/algorithm/predicates/network_schedtag_predicate.go index 41adcd756c..1083f80279 100644 --- a/pkg/scheduler/algorithm/predicates/network_schedtag_predicate.go +++ b/pkg/scheduler/algorithm/predicates/network_schedtag_predicate.go @@ -143,12 +143,12 @@ func (p *NetworkSchedtagPredicate) OnSelectEnd(u *core.Unit, c core.Candidater, p.BaseSchedtagPredicate.OnSelectEnd(p, u, c, count) } -func (p *NetworkSchedtagPredicate) GetCandidateResourceSortScore(selectRes ISchedtagCandidateResource) int { +func (p *NetworkSchedtagPredicate) GetCandidateResourceSortScore(selectRes ISchedtagCandidateResource) int64 { cnt, err := selectRes.(*api.CandidateNetwork).GetFreeAddressCount() if err != nil { return -1 } - return cnt + return int64(cnt) } func (p *NetworkSchedtagPredicate) DoSelect( diff --git a/pkg/scheduler/algorithm/predicates/predicates.go b/pkg/scheduler/algorithm/predicates/predicates.go index b1aa0185d6..498dc6c23b 100644 --- a/pkg/scheduler/algorithm/predicates/predicates.go +++ b/pkg/scheduler/algorithm/predicates/predicates.go @@ -241,7 +241,7 @@ type ISchedtagPredicateInstance interface { DoSelect(c core.Candidater, input ISchedtagCustomer, res []ISchedtagCandidateResource) []ISchedtagCandidateResource AddSelectResult(index int, selectRes []ISchedtagCandidateResource, output *core.AllocatedResource) - GetCandidateResourceSortScore(candidate ISchedtagCandidateResource) int + GetCandidateResourceSortScore(candidate ISchedtagCandidateResource) int64 } type BaseSchedtagPredicate struct { diff --git a/pkg/util/aliyun/host.go b/pkg/util/aliyun/host.go index 80db95c397..8b559243e5 100644 --- a/pkg/util/aliyun/host.go +++ b/pkg/util/aliyun/host.go @@ -135,7 +135,7 @@ func (self *SHost) GetSN() string { return "" } -func (self *SHost) GetCpuCount() int8 { +func (self *SHost) GetCpuCount() int { return 0 } diff --git a/pkg/util/aliyun/image.go b/pkg/util/aliyun/image.go index e6ca99df71..0f943dc372 100644 --- a/pkg/util/aliyun/image.go +++ b/pkg/util/aliyun/image.go @@ -176,7 +176,7 @@ func (self *SImage) GetImageType() string { } } -func (self *SImage) GetSize() int64 { +func (self *SImage) GetSizeByte() int64 { return int64(self.Size) * 1024 * 1024 * 1024 } diff --git a/pkg/util/aliyun/instance.go b/pkg/util/aliyun/instance.go index db90b30de8..8f20d74a11 100644 --- a/pkg/util/aliyun/instance.go +++ b/pkg/util/aliyun/instance.go @@ -86,7 +86,7 @@ type SInstance struct { AutoReleaseTime string ClusterId string - Cpu int8 + Cpu int CreationTime time.Time DedicatedHostAttribute SDedicatedHostAttribute Description string @@ -343,7 +343,7 @@ func (self *SInstance) GetINics() ([]cloudprovider.ICloudNic, error) { return nics, nil } -func (self *SInstance) GetVcpuCount() int8 { +func (self *SInstance) GetVcpuCount() int { return self.Cpu } diff --git a/pkg/util/aliyun/storage.go b/pkg/util/aliyun/storage.go index df857f02ac..e48c4e3206 100644 --- a/pkg/util/aliyun/storage.go +++ b/pkg/util/aliyun/storage.go @@ -89,7 +89,7 @@ func (self *SStorage) GetMediumType() string { } } -func (self *SStorage) GetCapacityMB() int { +func (self *SStorage) GetCapacityMB() int64 { return 0 // unlimited } diff --git a/pkg/util/aws/host.go b/pkg/util/aws/host.go index 0c7d2b32c7..5ae444841a 100644 --- a/pkg/util/aws/host.go +++ b/pkg/util/aws/host.go @@ -129,7 +129,7 @@ func (self *SHost) GetSN() string { return "" } -func (self *SHost) GetCpuCount() int8 { +func (self *SHost) GetCpuCount() int { return 0 } diff --git a/pkg/util/aws/image.go b/pkg/util/aws/image.go index 94abe056d1..069c8a3443 100644 --- a/pkg/util/aws/image.go +++ b/pkg/util/aws/image.go @@ -153,7 +153,7 @@ func (self *SImage) GetImageType() string { return self.ImageType } -func (self *SImage) GetSize() int64 { +func (self *SImage) GetSizeByte() int64 { return int64(self.SizeGB) * 1024 * 1024 * 1024 } diff --git a/pkg/util/aws/instance.go b/pkg/util/aws/instance.go index d492a53347..b43a57a228 100644 --- a/pkg/util/aws/instance.go +++ b/pkg/util/aws/instance.go @@ -79,7 +79,7 @@ type SInstance struct { HostName string InstanceName string InstanceType string - Cpu int8 + Cpu int Memory int // MB IoOptimized bool KeyPairName string @@ -305,7 +305,7 @@ func (self *SInstance) GetIEIP() (cloudprovider.ICloudEIP, error) { } } -func (self *SInstance) GetVcpuCount() int8 { +func (self *SInstance) GetVcpuCount() int { return self.Cpu } @@ -594,7 +594,7 @@ func (self *SRegion) GetInstances(zoneId string, ids []string, offset int, limit InstanceId: *instance.InstanceId, ImageId: *instance.ImageId, InstanceType: *instance.InstanceType, - Cpu: int8(*instance.CpuOptions.CoreCount), + Cpu: int(*instance.CpuOptions.CoreCount), IoOptimized: *instance.EbsOptimized, KeyPairName: *instance.KeyName, CreationTime: *instance.LaunchTime, diff --git a/pkg/util/aws/storage.go b/pkg/util/aws/storage.go index 2ce93c096b..01a81b405e 100644 --- a/pkg/util/aws/storage.go +++ b/pkg/util/aws/storage.go @@ -98,7 +98,7 @@ func (self *SStorage) GetMediumType() string { } } -func (self *SStorage) GetCapacityMB() int { +func (self *SStorage) GetCapacityMB() int64 { return 0 // unlimited } diff --git a/pkg/util/azure/classic_host.go b/pkg/util/azure/classic_host.go index 883b6ad191..0c355afc07 100644 --- a/pkg/util/azure/classic_host.go +++ b/pkg/util/azure/classic_host.go @@ -68,7 +68,7 @@ func (self *SClassicHost) GetAccessMac() string { return "" } -func (self *SClassicHost) GetCpuCount() int8 { +func (self *SClassicHost) GetCpuCount() int { return 0 } diff --git a/pkg/util/azure/classic_instance.go b/pkg/util/azure/classic_instance.go index 15ea8ec37f..b2a0d11113 100644 --- a/pkg/util/azure/classic_instance.go +++ b/pkg/util/azure/classic_instance.go @@ -421,7 +421,7 @@ func (self *SClassicInstance) GetVdi() string { return "vnc" } -func (self *SClassicInstance) GetVcpuCount() int8 { +func (self *SClassicInstance) GetVcpuCount() int { if vmSize, ok := CLASSIC_VM_SIZES[self.Properties.HardwareProfile.Size]; ok { return vmSize.NumberOfCores } diff --git a/pkg/util/azure/classic_instancesize.go b/pkg/util/azure/classic_instancesize.go index 18fc1408bc..b9b4a66714 100644 --- a/pkg/util/azure/classic_instancesize.go +++ b/pkg/util/azure/classic_instancesize.go @@ -16,7 +16,7 @@ package azure type ClassicVMSize struct { MemoryInMB int - NumberOfCores int8 + NumberOfCores int StorageSize int MaxNic int } diff --git a/pkg/util/azure/classic_storage.go b/pkg/util/azure/classic_storage.go index 41d28b5d11..0917ae4d86 100644 --- a/pkg/util/azure/classic_storage.go +++ b/pkg/util/azure/classic_storage.go @@ -73,7 +73,7 @@ func (self *SClassicStorage) GetEnabled() bool { return false } -func (self *SClassicStorage) GetCapacityMB() int { +func (self *SClassicStorage) GetCapacityMB() int64 { return 0 // unlimited } diff --git a/pkg/util/azure/host.go b/pkg/util/azure/host.go index f4495a15a3..9f66855627 100644 --- a/pkg/util/azure/host.go +++ b/pkg/util/azure/host.go @@ -249,7 +249,7 @@ func (self *SHost) GetAccessMac() string { return "" } -func (self *SHost) GetCpuCount() int8 { +func (self *SHost) GetCpuCount() int { return 0 } diff --git a/pkg/util/azure/image.go b/pkg/util/azure/image.go index 9cc8030783..66f3fba864 100644 --- a/pkg/util/azure/image.go +++ b/pkg/util/azure/image.go @@ -159,7 +159,7 @@ func (self *SImage) GetImageType() string { return self.ImageType } -func (self *SImage) GetSize() int64 { +func (self *SImage) GetSizeByte() int64 { return int64(self.Properties.StorageProfile.OsDisk.DiskSizeGB) * 1024 * 1024 * 1024 } diff --git a/pkg/util/azure/instance.go b/pkg/util/azure/instance.go index 1192384281..8d8ae7c7cb 100644 --- a/pkg/util/azure/instance.go +++ b/pkg/util/azure/instance.go @@ -777,7 +777,7 @@ func (self *SInstance) RebuildRoot(ctx context.Context, imageId string, passwd s return self.host.zone.region.ReplaceSystemDisk(self, cpu, memoryMb, imageId, passwd, publicKey, sysSizeGB) } -func (region *SRegion) ReplaceSystemDisk(instance *SInstance, cpu int8, memoryMb int, imageId, passwd, publicKey string, sysSizeGB int) (string, error) { +func (region *SRegion) ReplaceSystemDisk(instance *SInstance, cpu int, memoryMb int, imageId, passwd, publicKey string, sysSizeGB int) (string, error) { log.Debugf("ReplaceSystemDisk %s image: %s", instance.ID, imageId) storageType := instance.Properties.StorageProfile.OsDisk.ManagedDisk.StorageAccountType if len(storageType) == 0 { @@ -1019,13 +1019,13 @@ func (self *SInstance) fetchVMSize() error { return nil } -func (self *SInstance) GetVcpuCount() int8 { +func (self *SInstance) GetVcpuCount() int { err := self.fetchVMSize() if err != nil { log.Errorf("fetchVMSize error: %v", err) return 0 } - return int8(self.vmSize.NumberOfCores) + return self.vmSize.NumberOfCores } func (self *SInstance) GetVmemSizeMB() int { diff --git a/pkg/util/azure/region.go b/pkg/util/azure/region.go index 538b71cc6f..3970e7664e 100644 --- a/pkg/util/azure/region.go +++ b/pkg/util/azure/region.go @@ -29,7 +29,7 @@ import ( type SVMSize struct { //MaxDataDiskCount int32 `json:"maxDataDiskCount,omitempty"` //Unmarshal会出错 MemoryInMB int32 `json:"memoryInMB,omitempty"` - NumberOfCores int32 `json:"numberOfCores,omitempty"` + NumberOfCores int `json:"numberOfCores,omitempty"` Name string OsDiskSizeInMB int32 `json:"osDiskSizeInMB,omitempty"` ResourceDiskSizeInMB int32 `json:"resourceDiskSizeInMB,omitempty"` @@ -88,7 +88,7 @@ func (self *SRegion) getHardwareProfile(cpu, memMB int) []string { } else { profiles := make([]string, 0) for vmSize, info := range vmSizes { - if info.MemoryInMB == int32(memMB) && info.NumberOfCores == int32(cpu) { + if info.MemoryInMB == int32(memMB) && info.NumberOfCores == cpu { profiles = append(profiles, vmSize) } } @@ -414,7 +414,7 @@ func (self *SRegion) fetchInfrastructure() error { return nil } -func (self *SRegion) CreateInstanceSimple(name string, imgId, osType string, cpu int8, memMb int, sysDiskSizeGB int, storageType string, dataDiskSizesGB []int, networkId string, passwd string, publicKey string) (*SInstance, error) { +func (self *SRegion) CreateInstanceSimple(name string, imgId, osType string, cpu int, memMb int, sysDiskSizeGB int, storageType string, dataDiskSizesGB []int, networkId string, passwd string, publicKey string) (*SInstance, error) { izones, err := self.GetIZones() if err != nil { return nil, err @@ -428,7 +428,7 @@ func (self *SRegion) CreateInstanceSimple(name string, imgId, osType string, cpu Name: name, ExternalImageId: imgId, SysDisk: cloudprovider.SDiskInfo{SizeGB: sysDiskSizeGB, StorageType: storageType}, - Cpu: int(cpu), + Cpu: cpu, MemoryMB: memMb, ExternalNetworkId: networkId, Password: seclib2.RandomPassword2(12), diff --git a/pkg/util/azure/shell/instance.go b/pkg/util/azure/shell/instance.go index e979783338..610a64f090 100644 --- a/pkg/util/azure/shell/instance.go +++ b/pkg/util/azure/shell/instance.go @@ -77,7 +77,7 @@ func init() { type InstanceCreateOptions struct { NAME string `help:"Name of instance"` IMAGE string `help:"image ID"` - CPU int8 `help:"CPU count"` + CPU int `help:"CPU count"` MEMORYGB int `help:"MemoryGB"` SYSDISKSIZEGB int `help:"System Disk Size"` Disk []int `help:"Data disk sizes int GB"` @@ -122,7 +122,7 @@ func init() { type InstanceRebuildOptions struct { ID string `help:"Instance ID"` - CPU int8 `help:"Instance CPU core"` + CPU int `help:"Instance CPU core"` MEMORYMB int `help:"Instance Memory MB"` IMAGE string `help:"Image ID"` Password string `help:"pasword"` diff --git a/pkg/util/azure/storage.go b/pkg/util/azure/storage.go index 5cb22bd57e..5e4aa86287 100644 --- a/pkg/util/azure/storage.go +++ b/pkg/util/azure/storage.go @@ -72,7 +72,7 @@ func (self *SStorage) GetEnabled() bool { return true } -func (self *SStorage) GetCapacityMB() int { +func (self *SStorage) GetCapacityMB() int64 { return 0 // unlimited } diff --git a/pkg/util/esxi/host.go b/pkg/util/esxi/host.go index 27c3f30932..ec8029e58b 100644 --- a/pkg/util/esxi/host.go +++ b/pkg/util/esxi/host.go @@ -360,8 +360,8 @@ func (self *SHost) GetSN() string { return self.getHostSystem().Hardware.SystemInfo.SerialNumber } -func (self *SHost) GetCpuCount() int8 { - return int8(self.getHostSystem().Summary.Hardware.NumCpuThreads) +func (self *SHost) GetCpuCount() int { + return int(self.getHostSystem().Summary.Hardware.NumCpuThreads) } func (self *SHost) GetNodeCount() int8 { @@ -575,7 +575,7 @@ func (host *SHost) newLocalStorageCache() (*SDatastoreImageCache, error) { var errmsg string var cacheDs *SDatastore var maxDs *SDatastore - var maxCapacity int + var maxCapacity int64 for i := 0; i < len(istorages); i += 1 { ds := istorages[i].(*SDatastore) if !ds.isLocalVMFS() { diff --git a/pkg/util/esxi/image.go b/pkg/util/esxi/image.go index ec88e38622..def36aaf11 100644 --- a/pkg/util/esxi/image.go +++ b/pkg/util/esxi/image.go @@ -105,7 +105,7 @@ func (self *SImage) GetImageType() string { return cloudprovider.CachedImageTypeCustomized } -func (self *SImage) GetSize() int64 { +func (self *SImage) GetSizeByte() int64 { return self.size } @@ -126,7 +126,7 @@ func (self *SImage) GetOsArch() string { } func (self *SImage) GetMinOsDiskSizeGb() int { - return int(self.GetSize() / 1024 / 1024 / 1024) + return int(self.GetSizeByte() / 1024 / 1024 / 1024) } func (self *SImage) GetImageFormat() string { diff --git a/pkg/util/esxi/storage.go b/pkg/util/esxi/storage.go index d87c73a07b..f7ec12fdb6 100644 --- a/pkg/util/esxi/storage.go +++ b/pkg/util/esxi/storage.go @@ -79,9 +79,9 @@ func (self *SDatastore) GetName() string { return fmt.Sprintf("%s-%s", self.getVolumeType(), volName) } -func (self *SDatastore) GetCapacityMB() int { +func (self *SDatastore) GetCapacityMB() int64 { moStore := self.getDatastore() - return int(moStore.Summary.Capacity / 1024 / 1024) + return moStore.Summary.Capacity / 1024 / 1024 } func (self *SDatastore) GetEnabled() bool { diff --git a/pkg/util/esxi/virtualmachine.go b/pkg/util/esxi/virtualmachine.go index fb0e9f3527..144b0431c9 100644 --- a/pkg/util/esxi/virtualmachine.go +++ b/pkg/util/esxi/virtualmachine.go @@ -213,8 +213,8 @@ func (self *SVirtualMachine) GetIEIP() (cloudprovider.ICloudEIP, error) { return nil, nil } -func (self *SVirtualMachine) GetVcpuCount() int8 { - return int8(self.getVirtualMachine().Summary.Config.NumCpu) +func (self *SVirtualMachine) GetVcpuCount() int { + return int(self.getVirtualMachine().Summary.Config.NumCpu) } func (self *SVirtualMachine) GetVmemSizeMB() int { @@ -526,7 +526,7 @@ func (self *SVirtualMachine) GetVersion() string { func (self *SVirtualMachine) doChangeConfig(ctx context.Context, ncpu int32, vmemMB int64, guestId string, version string) error { changed := false configSpec := types.VirtualMachineConfigSpec{} - if int8(ncpu) != self.GetVcpuCount() { + if int(ncpu) != self.GetVcpuCount() { configSpec.NumCPUs = ncpu changed = true } diff --git a/pkg/util/huawei/host.go b/pkg/util/huawei/host.go index 2810930427..bccd65e8f1 100644 --- a/pkg/util/huawei/host.go +++ b/pkg/util/huawei/host.go @@ -124,7 +124,7 @@ func (self *SHost) GetSN() string { return "" } -func (self *SHost) GetCpuCount() int8 { +func (self *SHost) GetCpuCount() int { return 0 } diff --git a/pkg/util/huawei/image.go b/pkg/util/huawei/image.go index f6d4d7243d..7334217bfe 100644 --- a/pkg/util/huawei/image.go +++ b/pkg/util/huawei/image.go @@ -148,7 +148,7 @@ func (self *SImage) GetImageType() string { } } -func (self *SImage) GetSize() int64 { +func (self *SImage) GetSizeByte() int64 { return int64(self.MinDiskGB) * 1024 * 1024 * 1024 } diff --git a/pkg/util/huawei/instance.go b/pkg/util/huawei/instance.go index 420764e8d6..6b595663b3 100644 --- a/pkg/util/huawei/instance.go +++ b/pkg/util/huawei/instance.go @@ -378,9 +378,9 @@ func (self *SInstance) GetIEIP() (cloudprovider.ICloudEIP, error) { return nil, nil } -func (self *SInstance) GetVcpuCount() int8 { +func (self *SInstance) GetVcpuCount() int { cpu, _ := strconv.Atoi(self.Flavor.Vcpus) - return int8(cpu) + return cpu } func (self *SInstance) GetVmemSizeMB() int { diff --git a/pkg/util/huawei/storage.go b/pkg/util/huawei/storage.go index f60a11ea7e..5132c9de4a 100644 --- a/pkg/util/huawei/storage.go +++ b/pkg/util/huawei/storage.go @@ -101,7 +101,7 @@ func (self *SStorage) GetMediumType() string { } } -func (self *SStorage) GetCapacityMB() int { +func (self *SStorage) GetCapacityMB() int64 { return 0 // unlimited } diff --git a/pkg/util/openstack/flavor.go b/pkg/util/openstack/flavor.go index 681225e1be..db00fd9b50 100644 --- a/pkg/util/openstack/flavor.go +++ b/pkg/util/openstack/flavor.go @@ -32,7 +32,7 @@ type SFlavor struct { Name string RAM int Swap string - Vcpus int8 + Vcpus int } func (region *SRegion) GetFlavors() ([]SFlavor, error) { diff --git a/pkg/util/openstack/host.go b/pkg/util/openstack/host.go index 7d4231c8af..6b5e936bc5 100644 --- a/pkg/util/openstack/host.go +++ b/pkg/util/openstack/host.go @@ -43,7 +43,7 @@ type Service struct { } type SResource struct { - CPU int8 + CPU int DiskGB int Host string MemoryMb int @@ -72,7 +72,7 @@ type SHost struct { MemoryMbUsed int RunningVms int Service Service - Vcpus int8 + Vcpus int VcpusUsed int8 // less then version 2.28 @@ -293,7 +293,7 @@ func (host *SHost) GetSN() string { return "" } -func (host *SHost) GetCpuCount() int8 { +func (host *SHost) GetCpuCount() int { if host.Vcpus > 0 { return host.Vcpus } @@ -314,7 +314,7 @@ func (host *SHost) GetNodeCount() int8 { } } } - return host.GetCpuCount() + return int8(host.GetCpuCount()) } func (host *SHost) GetCpuDesc() string { diff --git a/pkg/util/openstack/image.go b/pkg/util/openstack/image.go index f040d7b687..4902415932 100644 --- a/pkg/util/openstack/image.go +++ b/pkg/util/openstack/image.go @@ -158,7 +158,7 @@ func (image *SImage) GetImageType() string { } } -func (image *SImage) GetSize() int64 { +func (image *SImage) GetSizeByte() int64 { return int64(image.Size) } diff --git a/pkg/util/openstack/instance.go b/pkg/util/openstack/instance.go index 147eabe5e3..1589cbae9d 100644 --- a/pkg/util/openstack/instance.go +++ b/pkg/util/openstack/instance.go @@ -273,7 +273,7 @@ func (instance *SInstance) GetINics() ([]cloudprovider.ICloudNic, error) { return nics, nil } -func (instance *SInstance) GetVcpuCount() int8 { +func (instance *SInstance) GetVcpuCount() int { instance.fetchFlavor() return instance.Flavor.Vcpus } @@ -418,7 +418,7 @@ func (instance *SInstance) RebuildRoot(ctx context.Context, imageId string, pass } func (instance *SInstance) ChangeConfig(ctx context.Context, ncpu int, vmem int) error { - if instance.GetVcpuCount() != int8(ncpu) || instance.GetVmemSizeMB() != vmem { + if instance.GetVcpuCount() != ncpu || instance.GetVmemSizeMB() != vmem { flavorId, err := instance.host.zone.region.syncFlavor("", ncpu, vmem, 40) if err != nil { return err diff --git a/pkg/util/openstack/storage.go b/pkg/util/openstack/storage.go index f7cae2c435..802a4fd0de 100644 --- a/pkg/util/openstack/storage.go +++ b/pkg/util/openstack/storage.go @@ -84,7 +84,7 @@ func (storage *SStorage) GetMediumType() string { return api.DISK_TYPE_ROTATE } -func (storage *SStorage) GetCapacityMB() int { +func (storage *SStorage) GetCapacityMB() int64 { return 0 // unlimited } diff --git a/pkg/util/qcloud/host.go b/pkg/util/qcloud/host.go index 7fdbe9629d..042622615b 100644 --- a/pkg/util/qcloud/host.go +++ b/pkg/util/qcloud/host.go @@ -194,7 +194,7 @@ func (self *SHost) GetSN() string { return "" } -func (self *SHost) GetCpuCount() int8 { +func (self *SHost) GetCpuCount() int { return 0 } diff --git a/pkg/util/qcloud/image.go b/pkg/util/qcloud/image.go index d6f30b9c91..276c72a056 100644 --- a/pkg/util/qcloud/image.go +++ b/pkg/util/qcloud/image.go @@ -177,7 +177,7 @@ func (self *SImage) GetImageType() string { } } -func (self *SImage) GetSize() int64 { +func (self *SImage) GetSizeByte() int64 { return int64(self.ImageSize) * 1024 * 1024 * 1024 } diff --git a/pkg/util/qcloud/instance.go b/pkg/util/qcloud/instance.go index 2147a21908..213fefe8d2 100644 --- a/pkg/util/qcloud/instance.go +++ b/pkg/util/qcloud/instance.go @@ -100,7 +100,7 @@ type SInstance struct { Placement Placement InstanceId string InstanceType string - CPU int8 + CPU int Memory int RestrictState string //NORMAL EXPIRED PROTECTIVELY_ISOLATED InstanceName string @@ -280,7 +280,7 @@ func (self *SInstance) GetINics() ([]cloudprovider.ICloudNic, error) { return nics, nil } -func (self *SInstance) GetVcpuCount() int8 { +func (self *SInstance) GetVcpuCount() int { return self.CPU } diff --git a/pkg/util/qcloud/localstorage.go b/pkg/util/qcloud/localstorage.go index 8ac1162d5e..4dc6f9c0cf 100644 --- a/pkg/util/qcloud/localstorage.go +++ b/pkg/util/qcloud/localstorage.go @@ -74,7 +74,7 @@ func (self *SLocalStorage) GetMediumType() string { return api.DISK_TYPE_SSD } -func (self *SLocalStorage) GetCapacityMB() int { +func (self *SLocalStorage) GetCapacityMB() int64 { return 0 // unlimited } diff --git a/pkg/util/qcloud/storage.go b/pkg/util/qcloud/storage.go index 60e5b6aaad..71dd329533 100644 --- a/pkg/util/qcloud/storage.go +++ b/pkg/util/qcloud/storage.go @@ -87,7 +87,7 @@ func (self *SStorage) GetMediumType() string { return api.DISK_TYPE_SSD } -func (self *SStorage) GetCapacityMB() int { +func (self *SStorage) GetCapacityMB() int64 { return 0 // unlimited } diff --git a/pkg/util/ucloud/host.go b/pkg/util/ucloud/host.go index 87676a59cd..984962bf23 100644 --- a/pkg/util/ucloud/host.go +++ b/pkg/util/ucloud/host.go @@ -126,7 +126,7 @@ func (self *SHost) GetSN() string { return "" } -func (self *SHost) GetCpuCount() int8 { +func (self *SHost) GetCpuCount() int { return 0 } diff --git a/pkg/util/ucloud/image.go b/pkg/util/ucloud/image.go index 7ef509cdb7..e25c5a9c40 100644 --- a/pkg/util/ucloud/image.go +++ b/pkg/util/ucloud/image.go @@ -113,7 +113,7 @@ func (self *SImage) GetIStoragecache() cloudprovider.ICloudStoragecache { return self.storageCache } -func (self *SImage) GetSize() int64 { +func (self *SImage) GetSizeByte() int64 { return self.ImageSizeGB * 1024 * 1024 * 1024 } diff --git a/pkg/util/ucloud/instance.go b/pkg/util/ucloud/instance.go index d6432f89f4..8eda93cbc9 100644 --- a/pkg/util/ucloud/instance.go +++ b/pkg/util/ucloud/instance.go @@ -285,8 +285,8 @@ func (self *SInstance) GetIEIP() (cloudprovider.ICloudEIP, error) { return nil, nil } -func (self *SInstance) GetVcpuCount() int8 { - return int8(self.CPU) +func (self *SInstance) GetVcpuCount() int { + return self.CPU } func (self *SInstance) GetVmemSizeMB() int { diff --git a/pkg/util/ucloud/storage.go b/pkg/util/ucloud/storage.go index 3d38e8b293..6b7c6df914 100644 --- a/pkg/util/ucloud/storage.go +++ b/pkg/util/ucloud/storage.go @@ -104,7 +104,7 @@ func (self *SStorage) GetMediumType() string { } } -func (self *SStorage) GetCapacityMB() int { +func (self *SStorage) GetCapacityMB() int64 { return 0 // unlimited } diff --git a/pkg/util/zstack/cluster.go b/pkg/util/zstack/cluster.go new file mode 100644 index 0000000000..8f7f5b5f7d --- /dev/null +++ b/pkg/util/zstack/cluster.go @@ -0,0 +1,32 @@ +package zstack + +type SCluster struct { + ZStackBasic + Description string `json:"description"` + State string `json:"State"` + HypervisorType string `json:"hypervisorType"` + ZStackTime + ZoneUUID string `json:"zoneUuid"` + Type string `json:"type"` +} + +func (region *SRegion) GetClusters() ([]SCluster, error) { + clusters := []SCluster{} + params := []string{} + if SkipEsxi { + params = append(params, "q=type!=vmware") + } + return clusters, region.client.listAll("clusters", params, &clusters) +} + +func (region *SRegion) GetClusterIds() ([]string, error) { + clusters, err := region.GetClusters() + if err != nil { + return nil, err + } + clusterIds := []string{} + for i := 0; i < len(clusters); i++ { + clusterIds = append(clusterIds, clusters[i].UUID) + } + return clusterIds, nil +} diff --git a/pkg/util/zstack/disk.go b/pkg/util/zstack/disk.go index a2b2bbb6b5..f113f1b8fd 100644 --- a/pkg/util/zstack/disk.go +++ b/pkg/util/zstack/disk.go @@ -8,29 +8,60 @@ import ( "yunion.io/x/jsonutils" "yunion.io/x/log" "yunion.io/x/onecloud/pkg/cloudprovider" - "yunion.io/x/onecloud/pkg/compute/models" - "yunion.io/x/pkg/utils" + + api "yunion.io/x/onecloud/pkg/apis/compute" ) type SDisk struct { storage *SStorage - UUID string `json:"uuid"` - Name string `json:"name"` - PrimaryStorageUUID string `json:"primaryStorageUuid"` - VMInstanceUUID string `json:"vmInstanceUuid"` - DiskOfferingUUID string `json:"diskOfferingUuid"` - RootImageUUID string `json:"rootImageUuid"` - InstallPath string `json:"installPath"` - Type string `json:"Type"` - Format string `json:"format"` - Size int `json:"size"` - ActualSize int `json:"actualSize"` - DeviceID float32 `json:"deviceId"` - State string `json:"state"` - Status string `json:"status"` - CreateDate time.Time `json:"createDate"` - LastOpDate time.Time `json:"lastOpDate"` + ZStackBasic + PrimaryStorageUUID string `json:"primaryStorageUuid"` + VMInstanceUUID string `json:"vmInstanceUuid"` + DiskOfferingUUID string `json:"diskOfferingUuid"` + RootImageUUID string `json:"rootImageUuid"` + InstallPath string `json:"installPath"` + Type string `json:"Type"` + Format string `json:"format"` + Size int `json:"size"` + ActualSize int `json:"actualSize"` + DeviceID float32 `json:"deviceId"` + State string `json:"state"` + Status string `json:"status"` + + ZStackTime +} + +func (region *SRegion) GetDiskWithStorage(diskId string) (*SDisk, error) { + disk, err := region.GetDisk(diskId) + if err != nil { + log.Errorf("failed to found disk %s error: %v", diskId, err) + return nil, err + } + storage, err := region.GetStorageWithZone(disk.PrimaryStorageUUID) + if err != nil { + log.Errorf("failed to found storage %s for disk %s error: %v", disk.PrimaryStorageUUID, disk.Name, err) + return nil, err + } + disk.storage = storage + return disk, nil +} + +func (region *SRegion) GetDisk(diskId string) (*SDisk, error) { + disks, err := region.GetDisks("", diskId) + if err != nil { + return nil, err + } + if len(disks) == 1 { + if disks[0].UUID == diskId { + return &disks[0], nil + } + return nil, cloudprovider.ErrNotFound + } + if len(disks) == 0 { + return nil, cloudprovider.ErrNotFound + } + return nil, cloudprovider.ErrDuplicateId } func (region *SRegion) GetDisks(storageId, diskId string) ([]SDisk, error) { @@ -52,11 +83,7 @@ func (region *SRegion) GetDisks(storageId, diskId string) ([]SDisk, error) { func (disk *SDisk) GetMetadata() *jsonutils.JSONDict { data := jsonutils.NewDict() - //priceKey := fmt.Sprintf("%s::%s::%s", disk.RegionId, disk.Category, disk.Type) - //data.Add(jsonutils.NewString(priceKey), "price_key") - - data.Add(jsonutils.NewString(models.HYPERVISOR_ALIYUN), "hypervisor") - + data.Add(jsonutils.NewString(api.HYPERVISOR_ZSTACK), "hypervisor") return data } @@ -65,46 +92,19 @@ func (disk *SDisk) GetId() string { } func (disk *SDisk) Delete(ctx context.Context) error { - _, err := disk.storage.zone.region.getDisk(disk.DiskId) - if err != nil { - if err == cloudprovider.ErrNotFound { - // 未找到disk, 说明disk已经被删除了. 避免回收站中disk-delete循环删除失败 - return nil - } - log.Errorf("Failed to find disk %s when delete: %s", disk.DiskId, err) - return err - } - - for { - err := disk.storage.zone.region.DeleteDisk(disk.DiskId) - if err != nil { - if isError(err, "IncorrectDiskStatus") { - log.Infof("The disk is initializing, try later ...") - time.Sleep(10 * time.Second) - } else { - log.Errorf("DeleteDisk fail: %s", err) - return err - } - } else { - break - } - } - return cloudprovider.WaitDeleted(disk, 10*time.Second, 300*time.Second) // 5minutes + return disk.storage.zone.region.DeleteDisk(disk.UUID) } func (disk *SDisk) Resize(ctx context.Context, sizeMb int64) error { - return disk.storage.zone.region.resizeDisk(disk.DiskId, sizeMb) + return disk.storage.zone.region.ResizeDisk(disk.UUID, disk.GetDiskType(), sizeMb) } func (disk *SDisk) GetName() string { - if len(disk.DiskName) > 0 { - return disk.DiskName - } - return disk.DiskId + return disk.Name } func (disk *SDisk) GetGlobalId() string { - return disk.DiskId + return disk.UUID } func (disk *SDisk) IsEmulated() bool { @@ -116,53 +116,47 @@ func (disk *SDisk) GetIStorage() (cloudprovider.ICloudStorage, error) { } func (disk *SDisk) GetStatus() string { - // In_use Available Attaching Detaching Creating ReIniting All switch disk.Status { - case "Creating", "ReIniting": - return models.DISK_ALLOCATING + case "Ready": + return api.DISK_READY + case "NotInstantiated": + return api.DISK_READY default: - return models.DISK_READY + log.Errorf("Unknown disk %s(%s) status %s", disk.Name, disk.UUID, disk.Status) + return api.DISK_UNKNOWN } } func (disk *SDisk) Refresh() error { - new, err := disk.storage.zone.region.getDisk(disk.DiskId) + new, err := disk.storage.zone.region.GetDisks("", disk.UUID) if err != nil { return err } return jsonutils.Update(disk, new) } -func (disk *SDisk) ResizeDisk(newSize int64) error { - // newSize 单位为 GB. 范围在20 ~2000. 只能往大调。不能调小 - // https://help.aliyun.com/document_detail/25522.html?spm=a2c4g.11174283.6.897.aHwqkS - return disk.storage.zone.region.resizeDisk(disk.DiskId, newSize) -} - func (disk *SDisk) GetDiskFormat() string { - return "vhd" + return disk.Format } func (disk *SDisk) GetDiskSizeMB() int { - return disk.Size * 1024 + return disk.Size / 1024 / 1024 } func (disk *SDisk) GetIsAutoDelete() bool { - return disk.DeleteWithInstance + return false } func (disk *SDisk) GetTemplateId() string { - return disk.ImageId + return disk.RootImageUUID } func (disk *SDisk) GetDiskType() string { switch disk.Type { - case "system": - return models.DISK_TYPE_SYS - case "data": - return models.DISK_TYPE_DATA + case "Root": + return api.DISK_TYPE_SYS default: - return models.DISK_TYPE_DATA + return api.DISK_TYPE_DATA } } @@ -186,179 +180,90 @@ func (disk *SDisk) GetMountpoint() string { return "" } -func (disk *SRegion) CreateDisk(zoneId string, category string, name string, sizeGb int, desc string) (string, error) { - params := make(map[string]string) - params["ZoneId"] = zoneId - params["DiskName"] = name - if len(desc) > 0 { - params["Description"] = desc - } - params["Encrypted"] = "false" - params["DiskCategory"] = category - params["Size"] = fmt.Sprintf("%d", sizeGb) - params["ClientToken"] = utils.GenRequestId(20) - - body, err := disk.ecsRequest("CreateDisk", params) - if err != nil { - return "", err - } - return body.GetString("DiskId") +func (region *SRegion) CreateDisk(zoneId string, category string, name string, sizeGb int, desc string) (string, error) { + return "", cloudprovider.ErrNotImplemented } -func (disk *SRegion) getDisk(diskId string) (*SDisk, error) { - disks, total, err := disk.GetDisks("", "", "", []string{diskId}, 0, 1) - if err != nil { - return nil, err - } - if total != 1 { - return nil, cloudprovider.ErrNotFound - } - return &disks[0], nil -} - -func (disk *SRegion) DeleteDisk(diskId string) error { - params := make(map[string]string) - params["DiskId"] = diskId - - _, err := disk.ecsRequest("DeleteDisk", params) +func (region *SRegion) DeleteDisk(diskId string) error { + _, err := region.client.delete("volumes", diskId, "Enforcing") return err } -func (disk *SRegion) resizeDisk(diskId string, sizeMb int64) error { - sizeGb := sizeMb / 1024 - params := make(map[string]string) - params["DiskId"] = diskId - params["NewSize"] = fmt.Sprintf("%d", sizeGb) - - _, err := disk.ecsRequest("ResizeDisk", params) - if err != nil { - log.Errorf("resizing disk (%s) to %d GiB failed: %s", diskId, sizeGb, err) - return err +func (region *SRegion) ResizeDisk(diskId string, diskType string, sizeMb int64) error { + switch diskType { + case api.DISK_TYPE_SYS: + diskType = "Root" + default: + diskType = "Data" } - - return nil -} - -func (disk *SRegion) resetDisk(diskId, snapshotId string) error { - params := make(map[string]string) - params["DiskId"] = diskId - params["SnapshotId"] = snapshotId - _, err := disk.ecsRequest("ResetDisk", params) - if err != nil { - log.Errorf("ResetDisk %s to snapshot %s fail %s", diskId, snapshotId, err) - return err - } - - return nil + params := jsonutils.Marshal(map[string]interface{}{ + fmt.Sprintf("resize%sVolume", diskType): map[string]int64{ + "size": sizeMb * 1024 * 1024, + }, + }) + _, err := region.client.put("volumes/resize", diskId, params) + return err } func (disk *SDisk) CreateISnapshot(ctx context.Context, name, desc string) (cloudprovider.ICloudSnapshot, error) { - if snapshotId, err := disk.storage.zone.region.CreateSnapshot(disk.DiskId, name, desc); err != nil { - log.Errorf("createSnapshot fail %s", err) - return nil, err - } else if snapshot, err := disk.getSnapshot(snapshotId); err != nil { - return nil, err - } else { - snapshot.region = disk.storage.zone.region - if err := cloudprovider.WaitStatus(snapshot, models.SNAPSHOT_READY, 15*time.Second, 3600*time.Second); err != nil { - return nil, err - } - return snapshot, nil - } -} - -func (disk *SRegion) CreateSnapshot(diskId, name, desc string) (string, error) { - params := make(map[string]string) - params["RegionId"] = disk.RegionId - params["DiskId"] = diskId - params["SnapshotName"] = name - params["Description"] = desc - - if body, err := disk.ecsRequest("CreateSnapshot", params); err != nil { - log.Errorf("CreateSnapshot fail %s", err) - return "", err - } else { - return body.GetString("SnapshotId") - } + return nil, cloudprovider.ErrNotImplemented } func (disk *SDisk) GetISnapshot(snapshotId string) (cloudprovider.ICloudSnapshot, error) { - if snapshot, err := disk.getSnapshot(snapshotId); err != nil { + snapshots, err := disk.storage.zone.region.GetSnapshots(snapshotId, disk.UUID) + if err != nil { return nil, err - } else { - snapshot.region = disk.storage.zone.region - return snapshot, nil } -} - -func (disk *SDisk) getSnapshot(snapshotId string) (*SSnapshot, error) { - if snapshots, total, err := disk.storage.zone.region.GetSnapshots("", "", "", []string{snapshotId}, 0, 1); err != nil { - return nil, err - } else if total != 1 { + if len(snapshots) == 1 { + if snapshots[0].UUID == snapshotId { + return &snapshots[0], nil + } return nil, cloudprovider.ErrNotFound - } else { - return &snapshots[0], nil } + if len(snapshots) > 1 { + return nil, cloudprovider.ErrDuplicateId + } + return nil, cloudprovider.ErrNotFound } func (disk *SDisk) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) { - snapshots := make([]SSnapshot, 0) - for { - if parts, total, err := disk.storage.zone.region.GetSnapshots("", disk.DiskId, "", []string{}, 0, 20); err != nil { - log.Errorf("GetDisks fail %s", err) - return nil, err - } else { - snapshots = append(snapshots, parts...) - if len(snapshots) >= total { - break - } - } + snapshots, err := disk.storage.zone.region.GetSnapshots("", disk.UUID) + if err != nil { + return nil, err } - isnapshots := make([]cloudprovider.ICloudSnapshot, len(snapshots)) + isnapshots := []cloudprovider.ICloudSnapshot{} for i := 0; i < len(snapshots); i++ { - snapshots[i].region = disk.storage.zone.region - isnapshots[i] = &snapshots[i] + isnapshots = append(isnapshots, &snapshots[i]) } return isnapshots, nil } func (disk *SDisk) Reset(ctx context.Context, snapshotId string) (string, error) { - return "", disk.storage.zone.region.resetDisk(disk.DiskId, snapshotId) + return "", cloudprovider.ErrNotImplemented } func (disk *SDisk) GetBillingType() string { - return convertChargeType(disk.DiskChargeType) -} - -func (disk *SDisk) GetExpiredAt() time.Time { - return convertExpiredAt(disk.ExpiredTime) -} - -func (disk *SDisk) GetAccessPath() string { return "" } -func (disk *SDisk) Rebuild(ctx context.Context) error { - err := disk.storage.zone.region.rebuildDisk(disk.DiskId) - if err != nil { - if isError(err, "IncorrectInstanceStatus") { - return nil - } - log.Errorf("rebuild disk fail %s", err) - return err - } - return nil +func (disk *SDisk) GetExpiredAt() time.Time { + return time.Time{} } -func (disk *SRegion) rebuildDisk(diskId string) error { - params := make(map[string]string) - params["DiskId"] = diskId - _, err := disk.ecsRequest("ReInitDisk", params) - if err != nil { - log.Errorf("ReInitDisk %s fail %s", diskId, err) - return err - } - return nil +func (disk *SDisk) GetCreatedAt() time.Time { + return disk.CreateDate +} + +func (disk *SDisk) GetAccessPath() string { + return disk.InstallPath +} + +func (disk *SDisk) Rebuild(ctx context.Context) error { + return disk.storage.zone.region.RebuildDisk(disk.UUID) +} + +func (region *SRegion) RebuildDisk(diskId string) error { + return cloudprovider.ErrNotImplemented } func (disk *SDisk) GetProjectId() string { diff --git a/pkg/util/zstack/doc.go b/pkg/util/zstack/doc.go new file mode 100644 index 0000000000..9344a60cd9 --- /dev/null +++ b/pkg/util/zstack/doc.go @@ -0,0 +1 @@ +package zstack // import "yunion.io/x/onecloud/pkg/util/zstack" diff --git a/pkg/util/zstack/eip.go b/pkg/util/zstack/eip.go new file mode 100644 index 0000000000..0ab7b9d755 --- /dev/null +++ b/pkg/util/zstack/eip.go @@ -0,0 +1,156 @@ +package zstack + +import ( + "time" + + "yunion.io/x/jsonutils" + "yunion.io/x/onecloud/pkg/cloudprovider" + + api "yunion.io/x/onecloud/pkg/apis/compute" +) + +type SEipAddress struct { + region *SRegion + + ZStackBasic + VMNicUUID string `json:"vmNicUuid"` + VipUUID string `json:"vipUuid"` + State string `json:"state"` + VipIP string `json:"vipIp"` + GuestIP string `json:"guestIp"` + ZStackTime +} + +func (region *SRegion) GetEip(eipId string) (*SEipAddress, error) { + eips, err := region.GetEips(eipId, "") + if err != nil { + return nil, err + } + if len(eips) == 1 { + if eips[0].UUID == eipId { + return &eips[0], nil + } + return nil, cloudprovider.ErrNotFound + } + if len(eips) == 0 { + return nil, cloudprovider.ErrNotFound + } + return nil, cloudprovider.ErrDuplicateId +} + +func (region *SRegion) GetEips(eipId, instanceId string) ([]SEipAddress, error) { + eips := []SEipAddress{} + params := []string{} + if len(eipId) > 0 { + params = append(params, "q=uuid="+eipId) + } + if len(instanceId) > 0 { + params = append(params, "q=vmNic.vmInstanceUuid="+instanceId) + } + err := region.client.listAll("eips", params, &eips) + if err != nil { + return nil, err + } + for i := 0; i < len(eips); i++ { + eips[i].region = region + } + return eips, nil +} + +func (eip *SEipAddress) GetId() string { + return eip.UUID +} + +func (eip *SEipAddress) GetName() string { + return eip.Name +} + +func (eip *SEipAddress) GetGlobalId() string { + return eip.UUID +} + +func (eip *SEipAddress) GetStatus() string { + return api.EIP_STATUS_READY +} + +func (eip *SEipAddress) Refresh() error { + new, err := eip.region.GetEip(eip.UUID) + if err != nil { + return err + } + return jsonutils.Update(eip, new) +} + +func (eip *SEipAddress) IsEmulated() bool { + return false +} + +func (eip *SEipAddress) GetMetadata() *jsonutils.JSONDict { + return nil +} + +func (eip *SEipAddress) GetIpAddr() string { + return eip.VipIP +} + +func (eip *SEipAddress) GetMode() string { + return api.EIP_MODE_STANDALONE_EIP +} + +func (eip *SEipAddress) GetAssociationType() string { + return "server" +} + +func (eip *SEipAddress) GetAssociationExternalId() string { + if len(eip.VMNicUUID) > 0 { + instances, err := eip.region.GetInstances("", "", eip.VMNicUUID) + if err != nil && len(instances) == 1 { + return instances[0].UUID + } + } + return "" +} + +func (eip *SEipAddress) GetManagerId() string { + return eip.region.client.providerID +} + +func (eip *SEipAddress) GetBillingType() string { + return "" +} + +func (eip *SEipAddress) GetCreatedAt() time.Time { + return eip.CreateDate +} + +func (eip *SEipAddress) GetExpiredAt() time.Time { + return time.Time{} +} + +func (eip *SEipAddress) Delete() error { + return cloudprovider.ErrNotImplemented +} + +func (eip *SEipAddress) GetBandwidth() int { + return 0 +} + +func (eip *SEipAddress) GetInternetChargeType() string { + return api.EIP_CHARGE_TYPE_BY_TRAFFIC +} + +func (eip *SEipAddress) Associate(instanceId string) error { + return cloudprovider.ErrNotImplemented +} + +func (eip *SEipAddress) Dissociate() error { + return cloudprovider.ErrNotImplemented +} + +func (eip *SEipAddress) ChangeBandwidth(bw int) error { + return cloudprovider.ErrNotSupported +} + +func (eip *SEipAddress) GetProjectId() string { + return "" +} diff --git a/pkg/util/zstack/host.go b/pkg/util/zstack/host.go index bcfbc3dee7..05230e382e 100644 --- a/pkg/util/zstack/host.go +++ b/pkg/util/zstack/host.go @@ -1,21 +1,22 @@ package zstack import ( + "fmt" + "yunion.io/x/jsonutils" "yunion.io/x/onecloud/pkg/cloudprovider" - "yunion.io/x/onecloud/pkg/compute/models" + + api "yunion.io/x/onecloud/pkg/apis/compute" ) type SHost struct { zone *SZone + ZStackBasic Username string `json:"username"` SSHPort int `json:"sshPort"` ZoneUUID string `json:"zoneUuid"` - Name string `json:"name"` - UUID string `json:"uuid"` ClusterUUID string `json:"clusterUuid"` - Description string `json:"description"` ManagementIP string `json:"managementIp"` HypervisorType string `json:"hypervisorType"` State string `json:"state"` @@ -26,8 +27,7 @@ type SHost struct { TotalMemoryCapacity int `json:"totalMemoryCapacity"` AvailableMemoryCapacity int `json:"availableMemoryCapacity"` CPUNum int `json:"cpuNum"` - //CreateDate time.Time `json:"createDate"` - //LastOpDate time.Time `json:"lastOpDate"` + ZStackTime } func (host *SHost) GetMetadata() *jsonutils.JSONDict { @@ -35,16 +35,25 @@ func (host *SHost) GetMetadata() *jsonutils.JSONDict { } func (host *SHost) GetIWires() ([]cloudprovider.ICloudWire, error) { - return host.zone.GetIWires() + wires, err := host.zone.region.GetWires(host.ZoneUUID, "", host.ClusterUUID) + if err != nil { + return nil, err + } + iwires := []cloudprovider.ICloudWire{} + for i := 0; i < len(wires); i++ { + iwires = append(iwires, &wires[i]) + } + return iwires, nil } func (host *SHost) GetIStorages() ([]cloudprovider.ICloudStorage, error) { - storages, err := host.zone.getStorages(host.ClusterUUID) + storages, err := host.zone.region.GetStorages(host.zone.UUID, host.ClusterUUID, "") if err != nil { return nil, err } istorages := []cloudprovider.ICloudStorage{} for i := 0; i < len(storages); i++ { + storages[i].zone = host.zone istorages = append(istorages, &storages[i]) } return istorages, nil @@ -55,11 +64,34 @@ func (host *SHost) GetIStorageById(id string) (cloudprovider.ICloudStorage, erro } func (host *SHost) GetIVMs() ([]cloudprovider.ICloudVM, error) { - return nil, cloudprovider.ErrNotFound + instances, err := host.zone.region.GetInstances(host.UUID, "", "") + if err != nil { + return nil, err + } + iInstnace := []cloudprovider.ICloudVM{} + for i := 0; i < len(instances); i++ { + instances[i].host = host + iInstnace = append(iInstnace, &instances[i]) + } + return iInstnace, nil } -func (host *SHost) GetIVMById(gid string) (cloudprovider.ICloudVM, error) { - return nil, cloudprovider.ErrNotFound +func (host *SHost) GetIVMById(instanceId string) (cloudprovider.ICloudVM, error) { + instances, err := host.zone.region.GetInstances(host.UUID, instanceId, "") + if err != nil { + return nil, err + } + if len(instances) == 1 { + if instances[0].UUID == instanceId { + instances[0].host = host + return &instances[0], nil + } + return nil, cloudprovider.ErrNotFound + } + if len(instances) == 0 { + return nil, cloudprovider.ErrNotFound + } + return nil, cloudprovider.ErrDuplicateId } func (host *SHost) GetId() string { @@ -80,7 +112,7 @@ func (host *SHost) IsEmulated() bool { func (host *SHost) GetStatus() string { //TODO - return models.HOST_STATUS_RUNNING + return api.HOST_STATUS_RUNNING } func (host *SHost) Refresh() error { @@ -88,7 +120,7 @@ func (host *SHost) Refresh() error { } func (host *SHost) GetHostStatus() string { - return models.HOST_ONLINE + return api.HOST_ONLINE } func (host *SHost) GetEnabled() bool { @@ -113,8 +145,8 @@ func (host *SHost) GetSN() string { return "" } -func (host *SHost) GetCpuCount() int8 { - return int8(host.CPUNum) +func (host *SHost) GetCpuCount() int { + return host.TotalCPUCapacity } func (host *SHost) GetNodeCount() int8 { @@ -130,29 +162,58 @@ func (host *SHost) GetCpuMhz() int { } func (host *SHost) GetMemSizeMB() int { - return 0 + return host.TotalMemoryCapacity / 1024 / 1024 +} + +type SLocalStorageCapacity struct { + HostUUID string `json:"hostUuid"` + TotalCapacity int `json:"totalCapacity"` + AvailableCapacity int `json:"availableCapacity"` + TotalPhysicalCapacity int `json:"totalPhysicalCapacity"` + AvailablePhysicalCapacity int `json:"availablePhysicalCapacity"` +} + +func (region *SRegion) GetLocalStorage(storageId string, hostId string) ([]SLocalStorageCapacity, error) { + localStorage := []SLocalStorageCapacity{} + params := []string{} + if len(hostId) > 0 { + params = append(params, "hostUuid="+hostId) + } + return localStorage, region.client.listAll(fmt.Sprintf("primary-storage/local-storage/%s/capacities", storageId), params, &localStorage) } func (host *SHost) GetStorageSizeMB() int { - return 0 + storages, err := host.zone.region.GetStorages(host.zone.UUID, host.ClusterUUID, "") + if err != nil { + return 0 + } + totalStorage := 0 + for _, storage := range storages { + if storage.Type == "LocalStorage" { + localStorages, err := host.zone.region.GetLocalStorage(storage.UUID, host.UUID) + if err != nil { + return 0 + } + for i := 0; i < len(localStorages); i++ { + totalStorage += localStorages[i].TotalCapacity + } + } + } + return totalStorage / 1024 / 1024 } func (host *SHost) GetStorageType() string { - return models.DISK_TYPE_HYBRID + return api.DISK_TYPE_HYBRID } func (host *SHost) GetHostType() string { - return models.HOST_TYPE_ZSTACK + return api.HOST_TYPE_ZSTACK } func (host *SHost) GetManagerId() string { return host.zone.region.client.providerID } -// func (host *SHost) GetInstanceById(instanceId string) (*SInstance, error) { -// return nil, cloudprovider.ErrNotImplemented -// } - func (host *SHost) CreateVM(desc *cloudprovider.SManagedVMCreateConfig) (cloudprovider.ICloudVM, error) { return nil, cloudprovider.ErrNotImplemented } diff --git a/pkg/util/zstack/image.go b/pkg/util/zstack/image.go new file mode 100644 index 0000000000..c560d94d15 --- /dev/null +++ b/pkg/util/zstack/image.go @@ -0,0 +1,172 @@ +package zstack + +import ( + "context" + "time" + + "yunion.io/x/jsonutils" + "yunion.io/x/log" + "yunion.io/x/onecloud/pkg/cloudprovider" + + api "yunion.io/x/onecloud/pkg/apis/compute" +) + +type SBackupStorageRef struct { + NackupStorageUUID string `json:"backupStorageUuid"` + CreateDate time.Time `json:"createDate"` + ImageUUID string `json:"ImageUuid"` + InstallPath string `json:"installPath"` + LastOpDate time.Time `json:"lastOpDate"` + Status string `json:"status"` +} + +type SImage struct { + storageCache *SStoragecache + + BackupStorageRefs []SBackupStorageRef `json:"backupStorageRefs"` + ActualSize int `json:"actualSize"` + CreateDate time.Time `json:"createDate"` + Description string `json:"description"` + Format string `json:"format"` + LastOpDate time.Time `json:"lastOpDate"` + MD5Sum string `json:"md5sum"` + MediaType string `json:"mediaType"` + Name string `json:"name"` + Platform string `json:"platform"` + Size int `json:"size"` + State string `json:"state"` + Status string `json:"Ready"` + System bool `json:"system"` + Type string `json:"type"` + URL string `json:"url"` + UUID string `json:"uuid"` +} + +func (image *SImage) GetMinRamSizeMb() int { + return 0 +} + +func (image *SImage) GetMetadata() *jsonutils.JSONDict { + data := jsonutils.NewDict() + return data +} + +func (image *SImage) GetId() string { + return image.UUID +} + +func (image *SImage) GetName() string { + return image.Name +} + +func (image *SImage) IsEmulated() bool { + return false +} + +func (image *SImage) Delete(ctx context.Context) error { + return cloudprovider.ErrNotImplemented + //return image.storageCache.region.DeleteImage(image.UUID) +} + +func (image *SImage) GetGlobalId() string { + return image.UUID +} + +func (image *SImage) GetIStoragecache() cloudprovider.ICloudStoragecache { + return image.storageCache +} + +func (image *SImage) GetStatus() string { + switch image.Status { + case "Ready": + return api.CACHED_IMAGE_STATUS_READY + default: + log.Errorf("Unknown image status: %s", image.Status) + return api.CACHED_IMAGE_STATUS_CACHE_FAILED + } +} + +func (image *SImage) GetImageStatus() string { + switch image.Status { + case "Ready": + return cloudprovider.IMAGE_STATUS_ACTIVE + default: + return cloudprovider.IMAGE_STATUS_KILLED + } +} + +func (image *SImage) Refresh() error { + new, err := image.storageCache.region.GetImage(image.UUID) + if err != nil { + return err + } + return jsonutils.Update(image, new) +} + +func (image *SImage) GetImageType() string { + if image.System { + return cloudprovider.CachedImageTypeSystem + } + return cloudprovider.CachedImageTypeCustomized +} + +func (image *SImage) GetSizeByte() int64 { + return int64(image.Size) +} + +func (image *SImage) GetOsType() string { + return image.Platform +} + +func (image *SImage) GetOsDist() string { + return "" +} + +func (image *SImage) GetOsVersion() string { + return "" +} + +func (image *SImage) GetOsArch() string { + return "" +} + +func (image *SImage) GetMinOsDiskSizeGb() int { + return 10 +} + +func (image *SImage) GetImageFormat() string { + return image.Format +} + +func (image *SImage) GetCreateTime() time.Time { + return image.CreateDate +} + +func (region *SRegion) GetImage(imageId string) (*SImage, error) { + images, err := region.GetImages(imageId) + if err != nil { + return nil, err + } + if len(images) == 1 { + if images[0].UUID == imageId { + return &images[0], nil + } + return nil, cloudprovider.ErrNotFound + } + if len(images) == 0 { + return nil, cloudprovider.ErrNotFound + } + return nil, cloudprovider.ErrDuplicateId +} + +func (region *SRegion) GetImages(imageId string) ([]SImage, error) { + images := []SImage{} + params := []string{} + if len(imageId) > 0 { + params = append(params, "q=uuid="+imageId) + } + if SkipEsxi { + params = append(params, "q=type!=vmware") + } + return images, region.client.listAll("images", params, &images) +} diff --git a/pkg/util/zstack/instance.go b/pkg/util/zstack/instance.go new file mode 100644 index 0000000000..9e3b46511d --- /dev/null +++ b/pkg/util/zstack/instance.go @@ -0,0 +1,365 @@ +package zstack + +import ( + "context" + "fmt" + "net/url" + "time" + + "yunion.io/x/jsonutils" + "yunion.io/x/log" + "yunion.io/x/onecloud/pkg/cloudprovider" + "yunion.io/x/onecloud/pkg/util/billing" + "yunion.io/x/pkg/util/osprofile" + + api "yunion.io/x/onecloud/pkg/apis/compute" +) + +type SInstanceCdrome struct { +} + +type SInstance struct { + host *SHost + + ZStackBasic + ZoneUUID string `json:"zoneUuid"` + ClusterUUID string `json:"clusterUuid"` + HostUUID string `json:"hostUuid"` + LastHostUUID string `json:"lastHostUuid"` + RootVolumeUUID string `json:"rootVolumeUuid"` + Platform string `json:"platform"` + InstanceOfferingUUID string `json:"instanceOfferingUuid"` + + DefaultL3NetworkUUID string `json:"defaultL3NetworkUuid"` + Type string `json:"type"` + HypervisorType string `json:"hypervisorType"` + MemorySize int `json:"memorySize"` + CPUNum int `json:"cpuNum"` + CPUSpeed int `json:"cpuSpeed"` + State string `json:"state"` + InternalID string `json:"internalId"` + VMNics []SInstanceNic `json:"vmNics"` + AllVolumes []SDisk `json:"allVolumes"` + VMCdRoms []SInstanceCdrome `json:"vmCdRoms"` + ZStackTime +} + +func (region *SRegion) GetInstance(instanceId string) (*SInstance, error) { + instances, err := region.GetInstances("", instanceId, "") + if err != nil { + return nil, err + } + if len(instances) == 1 { + if instances[0].UUID == instanceId { + return &instances[0], nil + } + return nil, cloudprovider.ErrNotFound + } + if len(instances) == 0 { + return nil, cloudprovider.ErrNotFound + } + return nil, cloudprovider.ErrDuplicateId +} + +func (region *SRegion) GetInstances(hostId string, instanceId string, nicId string) ([]SInstance, error) { + instance := []SInstance{} + params := []string{"q=type=UserVm"} + if len(hostId) > 0 { + params = append(params, "q=lastHostUuid="+hostId) + } + if len(instanceId) > 0 { + params = append(params, "q=uuid="+instanceId) + } + if len(nicId) > 0 { + params = append(params, "q=vmNics.uuid="+nicId) + } + if SkipEsxi { + params = append(params, "q=hypervisorType!=ESX") + } + return instance, region.client.listAll("vm-instances", params, &instance) +} + +func (instance *SInstance) GetSecurityGroupIds() ([]string, error) { + ids := []string{} + secgroups, err := instance.host.zone.region.GetSecurityGroups("", instance.UUID) + if err != nil { + return nil, err + } + for _, secgroup := range secgroups { + ids = append(ids, secgroup.UUID) + } + return ids, nil +} + +func (instance *SInstance) GetMetadata() *jsonutils.JSONDict { + data := jsonutils.NewDict() + + return data +} + +func (instance *SInstance) GetCreateTime() time.Time { + return instance.CreateDate +} + +func (instance *SInstance) GetIHost() cloudprovider.ICloudHost { + return instance.host +} + +func (instance *SInstance) GetId() string { + return instance.UUID +} + +func (instance *SInstance) GetName() string { + return instance.Name +} + +func (instance *SInstance) GetGlobalId() string { + return instance.GetId() +} + +func (instance *SInstance) IsEmulated() bool { + return false +} + +func (instance *SInstance) GetInstanceType() string { + if len(instance.InstanceOfferingUUID) > 0 { + offer, err := instance.host.zone.region.GetInstanceOffering(instance.InstanceOfferingUUID) + if err == nil { + return offer.Name + } + } + return instance.Type +} + +func (instance *SInstance) GetIDisks() ([]cloudprovider.ICloudDisk, error) { + idisks := []cloudprovider.ICloudDisk{} + rootDisk, err := instance.host.zone.region.GetDiskWithStorage(instance.RootVolumeUUID) + if err != nil { + return nil, err + } + idisks = append(idisks, rootDisk) + for i := 0; i < len(instance.AllVolumes); i++ { + if instance.AllVolumes[i].UUID != instance.RootVolumeUUID { + dataDisk, err := instance.host.zone.region.GetDiskWithStorage(instance.AllVolumes[i].UUID) + if err != nil { + return nil, err + } + idisks = append(idisks, dataDisk) + } + } + return idisks, nil +} + +func (instance *SInstance) GetINics() ([]cloudprovider.ICloudNic, error) { + iNics := []cloudprovider.ICloudNic{} + for i := 0; i < len(instance.VMNics); i++ { + instance.VMNics[i].instance = instance + iNics = append(iNics, &instance.VMNics[i]) + } + return iNics, nil +} + +func (instance *SInstance) GetVcpuCount() int { + return instance.CPUNum +} + +func (instance *SInstance) GetVmemSizeMB() int { + return instance.MemorySize / 1024 / 1024 +} + +func (instance *SInstance) GetBootOrder() string { + return "dcn" +} + +func (instance *SInstance) GetVga() string { + return "std" +} + +func (instance *SInstance) GetVdi() string { + return "vnc" +} + +func (instance *SInstance) GetOSType() string { + return osprofile.NormalizeOSType(instance.Platform) +} + +func (instance *SInstance) GetOSName() string { + return instance.Platform +} + +func (instance *SInstance) GetBios() string { + return "BIOS" +} + +func (instance *SInstance) GetMachine() string { + return "pc" +} + +func (instance *SInstance) GetStatus() string { + switch instance.State { + case "Stopped": + return api.VM_READY + case "Running": + return api.VM_RUNNING + case "Destroyed": + return api.VM_DEALLOCATED + default: + log.Errorf("Unknown instance %s status %s", instance.Name, instance.State) + return api.VM_UNKNOWN + } +} + +func (instance *SInstance) Refresh() error { + new, err := instance.host.zone.region.GetInstance(instance.UUID) + if err != nil { + return err + } + return jsonutils.Update(instance, new) +} + +func (instance *SInstance) GetHypervisor() string { + return api.HYPERVISOR_ZSTACK +} + +func (instance *SInstance) StartVM(ctx context.Context) error { + return cloudprovider.ErrNotImplemented +} + +func (instance *SInstance) StopVM(ctx context.Context, isForce bool) error { + return cloudprovider.ErrNotImplemented +} + +func (instance *SInstance) GetVNCInfo() (jsonutils.JSONObject, error) { + info, err := instance.host.zone.region.GetInstanceConsoleInfo(instance.UUID) + if err != nil { + return nil, err + } + authURL, _ := url.Parse(instance.host.zone.region.client.authURL) + return jsonutils.Marshal(map[string]string{ + "url": fmt.Sprintf("%s://%s:5000/thirdparty/vnc_auto.html?host=%s&port=%d&token=%s&title=%s", info.Scheme, authURL.Host, info.Hostname, info.Port, info.Token, instance.Name), + "protocol": "zstack", + "instance_id": instance.UUID, + }), nil +} + +func (instance *SInstance) UpdateVM(ctx context.Context, name string) error { + return cloudprovider.ErrNotImplemented +} + +func (instance *SInstance) DeployVM(ctx context.Context, name string, password string, publicKey string, deleteKeypair bool, description string) error { + return cloudprovider.ErrNotImplemented +} + +func (instance *SInstance) RebuildRoot(ctx context.Context, imageId string, passwd string, publicKey string, sysSizeGB int) (string, error) { + return "", cloudprovider.ErrNotImplemented +} + +func (instance *SInstance) ChangeConfig(ctx context.Context, ncpu int, vmem int) error { + return cloudprovider.ErrNotImplemented +} + +func (instance *SInstance) ChangeConfig2(ctx context.Context, instanceType string) error { + return cloudprovider.ErrNotImplemented +} + +func (instance *SInstance) AttachDisk(ctx context.Context, diskId string) error { + return cloudprovider.ErrNotImplemented +} + +func (instance *SInstance) DetachDisk(ctx context.Context, diskId string) error { + return cloudprovider.ErrNotImplemented +} + +func (instance *SInstance) DeleteVM(ctx context.Context) error { + return cloudprovider.ErrNotImplemented +} + +func (instance *SInstance) GetIEIP() (cloudprovider.ICloudEIP, error) { + eips, err := instance.host.zone.region.GetEips("", instance.UUID) + if err != nil { + return nil, err + } + if len(eips) == 0 { + return nil, cloudprovider.ErrNotFound + } + if len(eips) == 1 { + return &eips[0], nil + } + return nil, cloudprovider.ErrDuplicateId +} + +func (instance *SInstance) AssignSecurityGroup(secgroupId string) error { + return cloudprovider.ErrNotImplemented +} + +func (instance *SInstance) SetSecurityGroups(secgroupIds []string) error { + return cloudprovider.ErrNotImplemented +} + +func (instance *SInstance) GetBillingType() string { + return "" +} + +func (instance *SInstance) GetCreatedAt() time.Time { + return instance.CreateDate +} + +func (instance *SInstance) GetExpiredAt() time.Time { + return time.Time{} +} + +func (instance *SInstance) UpdateUserData(userData string) error { + return cloudprovider.ErrNotImplemented +} + +func (instance *SInstance) CreateDisk(ctx context.Context, sizeMb int, uuid string, driver string) error { + return cloudprovider.ErrNotImplemented +} + +func (instance *SInstance) Renew(bc billing.SBillingCycle) error { + return cloudprovider.ErrNotImplemented +} + +func (instance *SInstance) GetProjectId() string { + return "" +} + +func (instance *SInstance) GetError() error { + return nil +} + +type SConsoleInfo struct { + Scheme string `json:"scheme"` + Hostname string `json:"hostname"` + Port int `json:"port"` + Token string `json:"token"` +} + +func (region *SRegion) GetInstanceConsoleInfo(instnaceId string) (*SConsoleInfo, error) { + params := map[string]interface{}{ + "params": map[string]string{ + "vmInstanceUuid": instnaceId, + }, + } + resp, err := region.client.post("consoles", jsonutils.Marshal(params)) + if err != nil { + return nil, err + } + info := &SConsoleInfo{} + err = resp.Unmarshal(info, "inventory") + if err != nil { + return nil, err + } + return info, nil +} + +func (region *SRegion) GetInstanceConsolePassword(instnaceId string) (string, error) { + resp, err := region.client.get("vm-instances", instnaceId, "console-passwords") + if err != nil { + return "", err + } + if resp.Contains("consolePassword") { + return resp.GetString("consolePassword") + } + return "", nil +} diff --git a/pkg/util/zstack/instancenic.go b/pkg/util/zstack/instancenic.go new file mode 100644 index 0000000000..ba2e103617 --- /dev/null +++ b/pkg/util/zstack/instancenic.go @@ -0,0 +1,68 @@ +package zstack + +import ( + "yunion.io/x/pkg/util/netutils" + + "yunion.io/x/jsonutils" + + "yunion.io/x/log" + "yunion.io/x/onecloud/pkg/cloudprovider" +) + +type SInstanceNic struct { + instance *SInstance + + UUID string `json:"uuid"` + VMInstanceUUID string `json:"vmInstanceUuid"` + L3NetworkUUID string `json:"l3NetworkUuid"` + IP string `json:"ip"` + Mac string `json:"mac"` + HypervisorType string `json:"hypervisorType"` + IPVersion int `json:"ipVersion"` + UsedIps []string `json:"usedIps"` + InternalName string `json:"internalName"` + DeviceID int `json:"deviceId"` + ZStackTime +} + +func (nic *SInstanceNic) GetIP() string { + return nic.IP +} + +func (nic *SInstanceNic) GetMAC() string { + return nic.Mac +} + +func (nic *SInstanceNic) GetDriver() string { + return "virtio" +} + +func (nic *SInstanceNic) GetINetwork() cloudprovider.ICloudNetwork { + networks, err := nic.instance.host.zone.region.GetNetworks(nic.instance.host.zone.UUID, "", nic.L3NetworkUUID, "") + if err != nil { + log.Errorf("failed to found networks for nic %v error: %v", jsonutils.Marshal(nic).String(), err) + return nil + } + ip, err := netutils.NewIPV4Addr(nic.IP) + if err != nil { + log.Errorf("Invalid ip address %s error: %v", nic.IP, err) + return nil + } + for i := 0; i < len(networks); i++ { + if networks[i].GetIPRange().Contains(ip) { + l3Network, err := nic.instance.host.zone.region.GetL3Network(nic.instance.host.zone.UUID, "", networks[i].L3NetworkUUID) + if err != nil { + log.Errorf("failed to found l3Network for network %v error: %v", jsonutils.Marshal(networks[i]).String(), err) + return nil + } + wire, err := nic.instance.host.zone.region.GetWire(l3Network.L2NetworkUUID) + if err != nil { + log.Errorf("failed to found wire for l3Network %v error: %v", jsonutils.Marshal(l3Network).String(), err) + return nil + } + networks[i].wire = wire + return &networks[i] + } + } + return nil +} diff --git a/pkg/util/zstack/network.go b/pkg/util/zstack/network.go new file mode 100644 index 0000000000..cefaaedd09 --- /dev/null +++ b/pkg/util/zstack/network.go @@ -0,0 +1,186 @@ +package zstack + +import ( + "yunion.io/x/jsonutils" + "yunion.io/x/onecloud/pkg/cloudprovider" + "yunion.io/x/pkg/util/netutils" + + api "yunion.io/x/onecloud/pkg/apis/compute" +) + +type SNetwork struct { + wire *SWire + + ZStackBasic + L3NetworkUUID string `json:"l3NetworkUuid"` + StartIP string `json:"startIp"` + EndIP string `json:"endIp"` + Netmask string `json:"netmask"` + Gateway string `json:"gateway"` + NetworkCIDR string `json:"networkCidr"` + IPVersion int `json:"ipVersion"` + PrefixLen int `json:"prefixLen"` + ZStackTime +} + +type SL3Network struct { + ZStackBasic + Type string `json:"type"` + ZoneUUID string `json:"zoneUuid"` + L2NetworkUUID string `json:"l2NetworkUuid"` + State string `json:"state"` + System bool `json:"system"` + Category bool `json:"category"` + IPVersion int `json:"ipVersion"` + DNS []string `json:"dns"` + Networks []SNetwork `json:"ipRanges"` + ZStackTime +} + +func (region *SRegion) GetNetwork(zoneId, wireId, l3Id, networkId string) (*SNetwork, error) { + networks, err := region.GetNetworks(zoneId, wireId, l3Id, networkId) + if err != nil { + return nil, err + } + if len(networks) == 1 { + if networks[0].UUID == networkId { + return &networks[0], nil + } + return nil, cloudprovider.ErrNotFound + } + if len(networks) == 0 { + return nil, cloudprovider.ErrNotFound + } + return nil, cloudprovider.ErrDuplicateId +} + +func (region *SRegion) GetL3Network(zoneId string, wireId string, l3Id string) (*SL3Network, error) { + l3Networks, err := region.GetL3Networks(zoneId, wireId, l3Id) + if err != nil { + return nil, err + } + if len(l3Networks) == 1 { + if l3Networks[0].UUID == l3Id { + return &l3Networks[0], nil + } + return nil, cloudprovider.ErrNotFound + } + if len(l3Networks) == 0 { + return nil, cloudprovider.ErrNotFound + } + return nil, cloudprovider.ErrDuplicateId +} + +func (region *SRegion) GetL3Networks(zoneId string, wireId string, l3Id string) ([]SL3Network, error) { + l3Networks := []SL3Network{} + params := []string{} + if len(zoneId) > 0 { + params = append(params, "q=zone.uuid="+zoneId) + } + if len(wireId) > 0 { + params = append(params, "q=l2NetworkUuid="+wireId) + } + if len(l3Id) > 0 { + params = append(params, "q=uuid="+l3Id) + } + return l3Networks, region.client.listAll("l3-networks", params, &l3Networks) +} + +func (region *SRegion) GetNetworks(zoneId string, wireId string, l3Id string, networkId string) ([]SNetwork, error) { + l3Networks, err := region.GetL3Networks(zoneId, wireId, l3Id) + if err != nil { + return nil, err + } + networks := []SNetwork{} + for i := 0; i < len(l3Networks); i++ { + for j := 0; j < len(l3Networks[i].Networks); j++ { + if len(networkId) == 0 || l3Networks[i].Networks[j].UUID == networkId { + networks = append(networks, l3Networks[i].Networks[j]) + } + } + } + return networks, nil +} + +func (network *SNetwork) GetMetadata() *jsonutils.JSONDict { + return nil +} + +func (network *SNetwork) GetId() string { + return network.UUID +} + +func (network *SNetwork) GetName() string { + return network.Name +} + +func (network *SNetwork) GetGlobalId() string { + return network.UUID +} + +func (network *SNetwork) IsEmulated() bool { + return false +} + +func (network *SNetwork) GetStatus() string { + return api.NETWORK_STATUS_AVAILABLE +} + +func (network *SNetwork) Delete() error { + return network.wire.vpc.region.DeleteNetwork(network.UUID) +} + +func (region *SRegion) DeleteNetwork(networkId string) error { + return cloudprovider.ErrNotImplemented +} + +func (network *SNetwork) GetIWire() cloudprovider.ICloudWire { + return network.wire +} + +func (network *SNetwork) GetAllocTimeoutSeconds() int { + return 120 // 2 minutes +} + +func (network *SNetwork) GetGateway() string { + return network.Gateway +} + +func (network *SNetwork) GetIpStart() string { + return network.StartIP +} + +func (network *SNetwork) GetIpEnd() string { + return network.EndIP +} + +func (network *SNetwork) GetIPRange() netutils.IPV4AddrRange { + start, _ := netutils.NewIPV4Addr(network.GetIpStart()) + end, _ := netutils.NewIPV4Addr(network.GetIpEnd()) + return netutils.NewIPV4AddrRange(start, end) +} + +func (network *SNetwork) GetIpMask() int8 { + return int8(network.PrefixLen) +} + +func (network *SNetwork) GetIsPublic() bool { + // return network.IsDefault + return true +} + +func (network *SNetwork) GetServerType() string { + return api.NETWORK_TYPE_GUEST +} + +func (network *SNetwork) Refresh() error { + new, err := network.wire.vpc.region.GetNetwork("", network.wire.UUID, network.L3NetworkUUID, network.UUID) + if err != nil { + return err + } + return jsonutils.Update(network, new) +} + +func (network *SNetwork) GetProjectId() string { + return "" +} diff --git a/pkg/util/zstack/offering.go b/pkg/util/zstack/offering.go new file mode 100644 index 0000000000..f54e5ffdba --- /dev/null +++ b/pkg/util/zstack/offering.go @@ -0,0 +1,178 @@ +package zstack + +import ( + "yunion.io/x/jsonutils" + "yunion.io/x/onecloud/pkg/cloudprovider" + + api "yunion.io/x/onecloud/pkg/apis/compute" +) + +type SInstanceOffering struct { + region *SRegion + + ZStackBasic + MemorySize int `json:"memorySize"` + CPUNum int `json:"cpuNum"` + CPUSpeed int `json:"cpuSpeed"` + Type string `json:"type"` + AllocatorStrategy string `json:"allocatorStrategy"` + State string `json:"state"` + + ZStackTime +} + +func (region *SRegion) GetInstanceOffering(offerId string) (*SInstanceOffering, error) { + offerings, err := region.GetInstanceOfferings(offerId) + if err != nil { + return nil, err + } + if len(offerings) == 1 { + if offerings[0].UUID == offerId { + return &offerings[0], nil + } + return nil, cloudprovider.ErrNotFound + } + if len(offerings) == 0 { + return nil, cloudprovider.ErrNotFound + } + return nil, cloudprovider.ErrDuplicateId +} + +func (region *SRegion) GetInstanceOfferings(offerId string) ([]SInstanceOffering, error) { + offerings := []SInstanceOffering{} + params := []string{"q=type=UserVM"} + if len(offerId) > 0 { + params = append(params, "q=uuid="+offerId) + } + if err := region.client.listAll("instance-offerings", params, &offerings); err != nil { + return nil, err + } + for i := 0; i < len(offerings); i++ { + offerings[i].region = region + } + return offerings, nil +} + +func (offering *SInstanceOffering) GetMetadata() *jsonutils.JSONDict { + return nil +} + +func (offering *SInstanceOffering) IsEmulated() bool { + return false +} + +func (offering *SInstanceOffering) Refresh() error { + new, err := offering.region.GetInstanceOffering(offering.UUID) + if err != nil { + return err + } + return jsonutils.Update(offering, new) +} + +func (offering *SInstanceOffering) GetName() string { + return offering.Name +} + +func (offering *SInstanceOffering) GetStatus() string { + switch offering.State { + case "Enabled": + return api.SkuStatusAvailable + } + return api.SkuStatusSoldout +} + +func (offering *SInstanceOffering) GetId() string { + return offering.UUID +} + +func (offering *SInstanceOffering) GetGlobalId() string { + return offering.UUID +} + +func (offering *SInstanceOffering) GetInstanceTypeFamily() string { + return offering.AllocatorStrategy +} + +func (offering *SInstanceOffering) GetInstanceTypeCategory() string { + return offering.AllocatorStrategy +} + +func (offering *SInstanceOffering) GetPrepaidStatus() string { + return api.SkuStatusSoldout +} + +func (offering *SInstanceOffering) GetPostpaidStatus() string { + return api.SkuStatusAvailable +} + +func (offering *SInstanceOffering) GetCpuCoreCount() int { + return offering.CPUNum +} + +func (offering *SInstanceOffering) GetMemorySizeMB() int { + return offering.MemorySize / 1024 / 1024 +} + +func (offering *SInstanceOffering) GetOsName() string { + return "Any" +} + +func (offering *SInstanceOffering) GetSysDiskResizable() bool { + return true +} + +func (offering *SInstanceOffering) GetSysDiskType() string { + return "" +} + +func (offering *SInstanceOffering) GetSysDiskMinSizeGB() int { + return 0 +} + +func (offering *SInstanceOffering) GetSysDiskMaxSizeGB() int { + return 0 +} + +func (offering *SInstanceOffering) GetAttachedDiskType() string { + return "" +} + +func (offering *SInstanceOffering) GetAttachedDiskSizeGB() int { + return 0 +} + +func (offering *SInstanceOffering) GetAttachedDiskCount() int { + return 6 +} + +func (offering *SInstanceOffering) GetDataDiskTypes() string { + return "" +} + +func (offering *SInstanceOffering) GetDataDiskMaxCount() int { + return 6 +} + +func (offering *SInstanceOffering) GetNicType() string { + return "vpc" +} + +func (offering *SInstanceOffering) GetNicMaxCount() int { + return 1 +} + +func (offering *SInstanceOffering) GetGpuAttachable() bool { + return false +} + +func (offering *SInstanceOffering) GetGpuSpec() string { + return "" +} + +func (offering *SInstanceOffering) GetGpuCount() int { + return 0 +} + +func (offering *SInstanceOffering) GetGpuMaxCount() int { + return 0 +} diff --git a/pkg/util/zstack/provider/doc.go b/pkg/util/zstack/provider/doc.go new file mode 100644 index 0000000000..8a52516f3c --- /dev/null +++ b/pkg/util/zstack/provider/doc.go @@ -0,0 +1 @@ +package provider // import "yunion.io/x/onecloud/pkg/util/zstack/provider" diff --git a/pkg/util/zstack/provider/provider.go b/pkg/util/zstack/provider/provider.go index b44dfcf77c..55c66a170b 100644 --- a/pkg/util/zstack/provider/provider.go +++ b/pkg/util/zstack/provider/provider.go @@ -16,8 +16,8 @@ package provider import ( "context" - "fmt" - "strings" + + "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/jsonutils" @@ -60,23 +60,40 @@ func (self *SZStackProviderFactory) NeedSyncSkuFromCloud() bool { } func (self *SZStackProviderFactory) ValidateCreateCloudaccountData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) error { + username, _ := data.GetString("username") + if len(username) == 0 { + return httperrors.NewMissingParameterError("username") + } + password, _ := data.GetString("password") + if len(password) == 0 { + return httperrors.NewMissingParameterError("password") + } + authURL, _ := data.GetString("auth_url") + if len(authURL) == 0 { + return httperrors.NewMissingParameterError("auth_url") + } + data.Set("account", jsonutils.NewString(username)) + data.Set("secret", jsonutils.NewString("password")) + data.Set("access_url", jsonutils.NewString(authURL)) return nil } func (self *SZStackProviderFactory) ValidateUpdateCloudaccountCredential(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject, cloudaccount string) (*cloudprovider.SCloudaccount, error) { - account := &cloudprovider.SCloudaccount{} + if username, _ := data.GetString("username"); len(username) > 0 { + cloudaccount = username + } + password, _ := data.GetString("password") + if len(password) > 0 { + return nil, httperrors.NewMissingParameterError("password") + } + account := &cloudprovider.SCloudaccount{ + Account: cloudaccount, + Secret: password, + } return account, nil } -func (self *SZStackProviderFactory) GetProvider(providerId, providerName, url, account, password string) (cloudprovider.ICloudProvider, error) { - accountInfo := strings.Split(account, "/") - if len(accountInfo) < 2 { - return nil, fmt.Errorf("Missing username or project name %s", account) - } - project, username, endpointType := accountInfo[0], accountInfo[1], "internal" - if len(accountInfo) == 3 { - endpointType = accountInfo[2] - } +func (self *SZStackProviderFactory) GetProvider(providerId, providerName, url, username, password string) (cloudprovider.ICloudProvider, error) { client, err := zstack.NewZStackClient(providerId, providerName, url, username, password, false) if err != nil { return nil, err diff --git a/pkg/util/zstack/region.go b/pkg/util/zstack/region.go index 67372c7d07..15cf7ac383 100644 --- a/pkg/util/zstack/region.go +++ b/pkg/util/zstack/region.go @@ -6,23 +6,20 @@ import ( "yunion.io/x/jsonutils" "yunion.io/x/log" "yunion.io/x/onecloud/pkg/cloudprovider" - "yunion.io/x/onecloud/pkg/compute/models" "yunion.io/x/pkg/util/secrules" + + api "yunion.io/x/onecloud/pkg/apis/compute" ) type SRegion struct { client *SZStackClient - Name string - UUID string - Description string - Type string - State string + Name string izones []cloudprovider.ICloudZone ivpcs []cloudprovider.ICloudVpc - // storageCache *SStoragecache + storageCache *SStoragecache } func (region *SRegion) GetClient() *SZStackClient { @@ -58,7 +55,7 @@ func (region *SRegion) GetGeographicInfo() cloudprovider.SGeographicInfo { } func (region *SRegion) GetStatus() string { - return models.CLOUD_REGION_STATUS_INSERVER + return api.CLOUD_REGION_STATUS_INSERVER } func (region *SRegion) Refresh() error { @@ -67,31 +64,57 @@ func (region *SRegion) Refresh() error { } func (region *SRegion) GetIHostById(id string) (cloudprovider.ICloudHost, error) { - return nil, cloudprovider.ErrNotImplemented + return region.GetHost("", id) } func (region *SRegion) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) { - return nil, cloudprovider.ErrNotImplemented + return region.GetStorageWithZone(id) } func (region *SRegion) GetIHosts() ([]cloudprovider.ICloudHost, error) { - return nil, cloudprovider.ErrNotImplemented + hosts, err := region.GetHosts("", "") + if err != nil { + return nil, err + } + ihosts := []cloudprovider.ICloudHost{} + for i := 0; i < len(hosts); i++ { + ihosts = append(ihosts, &hosts[i]) + } + return ihosts, nil } func (region *SRegion) GetIStorages() ([]cloudprovider.ICloudStorage, error) { - return nil, cloudprovider.ErrNotImplemented + storages, err := region.GetStorages("", "", "") + if err != nil { + return nil, err + } + istorages := []cloudprovider.ICloudStorage{} + for i := 0; i < len(storages); i++ { + istorages = append(istorages, &storages[i]) + } + return istorages, nil } func (region *SRegion) GetIStoragecacheById(id string) (cloudprovider.ICloudStoragecache, error) { - return nil, cloudprovider.ErrNotImplemented + caches, err := region.GetIStoragecaches() + if err != nil { + return nil, err + } + for i := 0; i < len(caches); i++ { + if caches[i].GetGlobalId() == id { + return caches[i], nil + } + } + return nil, cloudprovider.ErrNotFound } func (region *SRegion) GetIStoragecaches() ([]cloudprovider.ICloudStoragecache, error) { - return nil, cloudprovider.ErrNotImplemented + region.storageCache = &SStoragecache{region: region} + return []cloudprovider.ICloudStoragecache{region.storageCache}, nil } -func (region *SRegion) GetIVpcById(id string) (cloudprovider.ICloudVpc, error) { - return nil, cloudprovider.ErrNotImplemented +func (region *SRegion) GetIVpcById(vpcId string) (cloudprovider.ICloudVpc, error) { + return &SVpc{region: region}, nil } func (region *SRegion) GetIZoneById(id string) (cloudprovider.ICloudZone, error) { @@ -107,51 +130,56 @@ func (region *SRegion) GetIZoneById(id string) (cloudprovider.ICloudZone, error) return nil, cloudprovider.ErrNotFound } +func (region *SRegion) GetZone(zoneId string) (*SZone, error) { + zones, err := region.GetZones(zoneId) + if err != nil { + return nil, err + } + if len(zones) == 1 { + if zones[0].UUID == zoneId { + return &zones[0], nil + } + return nil, cloudprovider.ErrNotFound + } + if len(zones) == 0 { + return nil, cloudprovider.ErrNotFound + } + return nil, cloudprovider.ErrDuplicateId +} + +func (region *SRegion) GetZones(zoneId string) ([]SZone, error) { + zones := []SZone{} + params := []string{} + if len(zoneId) > 0 { + params = append(params, "q=uuid="+zoneId) + } + err := region.client.listAll("zones", params, &zones) + if err != nil { + return nil, err + } + for i := 0; i < len(zones); i++ { + zones[i].region = region + } + return zones, nil +} + func (region *SRegion) fetchZones() { if region.izones == nil || len(region.izones) == 0 { - zones := []SZone{} - if err := region.client.listAll("zones", nil, &zones); err != nil { - log.Errorf("failed to list zones error: %v", err) + zones, err := region.GetZones("") + if err != nil { + log.Errorf("failed to get zones error: %v", err) return } region.izones = []cloudprovider.ICloudZone{} for i := 0; i < len(zones); i++ { - zones[i].region = region region.izones = append(region.izones, &zones[i]) } } } -func (region *SRegion) fetchIVpc() error { - // vpcs, err := region.getVpcs() - // if err != nil { - // return err - // } - // region.ivpcs = []cloudprovider.ICloudVpc{} - // for i := 0; i < len(vpcs); i++ { - // if vpcs[i].Location == region.Name { - // vpcs[i].region = region - // region.ivpcs = append(region.ivpcs, &vpcs[i]) - // } - // } - // return nil - return nil -} - func (region *SRegion) fetchInfrastructure() error { region.fetchZones() - if err := region.fetchIVpc(); err != nil { - return err - } - // for i := 0; i < len(region.ivpcs); i++ { - // for j := 0; j < len(region.izones); j++ { - // zone := region.izones[j].(*SZone) - // vpc := region.ivpcs[i].(*SVpc) - // wire := SWire{zone: zone, vpc: vpc} - // zone.addWire(&wire) - // vpc.addWire(&wire) - // } - // } + region.GetIVpcs() return nil } @@ -164,12 +192,17 @@ func (region *SRegion) GetIZones() ([]cloudprovider.ICloudZone, error) { return region.izones, nil } +func (region *SRegion) GetVpc() *SVpc { + return &SVpc{region: region} +} + func (region *SRegion) GetIVpcs() ([]cloudprovider.ICloudVpc, error) { - return nil, cloudprovider.ErrNotImplemented + region.ivpcs = []cloudprovider.ICloudVpc{region.GetVpc()} + return region.ivpcs, nil } func (region *SRegion) CreateIVpc(name string, desc string, cidr string) (cloudprovider.ICloudVpc, error) { - return nil, cloudprovider.ErrNotImplemented + return nil, cloudprovider.ErrNotSupported } func (region *SRegion) CreateEIP(name string, bwMbps int, chargeType string, bgpType string) (cloudprovider.ICloudEIP, error) { @@ -177,7 +210,7 @@ func (region *SRegion) CreateEIP(name string, bwMbps int, chargeType string, bgp } func (region *SRegion) GetIEipById(eipId string) (cloudprovider.ICloudEIP, error) { - return nil, cloudprovider.ErrNotSupported + return region.GetEip(eipId) } func (region *SRegion) GetILoadBalancers() ([]cloudprovider.ICloudLoadbalancer, error) { @@ -221,21 +254,46 @@ func (region *SRegion) DeleteSecurityGroup(vpcId, secGrpId string) error { } func (region *SRegion) GetIEips() ([]cloudprovider.ICloudEIP, error) { - return nil, cloudprovider.ErrNotImplemented + eips, err := region.GetEips("", "") + if err != nil { + return nil, err + } + ieips := []cloudprovider.ICloudEIP{} + for i := 0; i < len(eips); i++ { + ieips = append(ieips, &eips[i]) + } + return ieips, nil } -func (self *SRegion) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) { - return nil, cloudprovider.ErrNotImplemented +func (region *SRegion) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) { + snapshots, err := region.GetSnapshots("", "") + if err != nil { + return nil, err + } + isnapshots := []cloudprovider.ICloudSnapshot{} + for i := 0; i < len(snapshots); i++ { + snapshots[i].region = region + isnapshots = append(isnapshots, &snapshots[i]) + } + return isnapshots, nil } -func (self *SRegion) GetISnapshotById(snapshotId string) (cloudprovider.ICloudSnapshot, error) { - return nil, cloudprovider.ErrNotImplemented +func (region *SRegion) GetISnapshotById(snapshotId string) (cloudprovider.ICloudSnapshot, error) { + return region.GetSnapshot(snapshotId) } func (region *SRegion) GetSkus(zoneId string) ([]cloudprovider.ICloudSku, error) { - return nil, cloudprovider.ErrNotImplemented + offerings, err := region.GetInstanceOfferings("") + if err != nil { + return nil, err + } + iskus := []cloudprovider.ICloudSku{} + for i := 0; i < len(offerings); i++ { + iskus = append(iskus, &offerings[i]) + } + return iskus, nil } -func (self *SRegion) SyncSecurityGroup(secgroupId string, vpcId string, name string, desc string, rules []secrules.SecurityRule) (string, error) { +func (region *SRegion) SyncSecurityGroup(secgroupId string, vpcId string, name string, desc string, rules []secrules.SecurityRule) (string, error) { return "", cloudprovider.ErrNotImplemented } diff --git a/pkg/util/zstack/securitygroup.go b/pkg/util/zstack/securitygroup.go new file mode 100644 index 0000000000..ca0137642b --- /dev/null +++ b/pkg/util/zstack/securitygroup.go @@ -0,0 +1,157 @@ +package zstack + +import ( + "net" + "strings" + + "yunion.io/x/onecloud/pkg/cloudprovider" + + "yunion.io/x/jsonutils" + api "yunion.io/x/onecloud/pkg/apis/compute" + "yunion.io/x/pkg/util/secrules" +) + +type SSecurityGroupRule struct { + ZStackBasic + SecurityGroupUUID string `json:"securityGroupUuid"` + Type string `json:"type"` + IPVersion int `json:"ipVersion"` + StartPort int `json:"startPort"` + EndPort int `json:"endPort"` + Protocol string `json:"protocol"` + State string `json:"state"` + AllowedCIDR string `json:"allowedCidr"` + RemoteSecurityGroupUUID string `json:"remoteSecurityGroupUuid"` + ZStackTime +} + +type SSecurityGroup struct { + region *SRegion + + ZStackBasic + State string `json:"state"` + IPVersion int `json:"ipVersion"` + ZStackTime + InternalID int `json:"internalId"` + Rules []SSecurityGroupRule `json:"rules"` + AttachedL3NetworkUUIDs []string `json:"attachedL3NetworkUuids"` +} + +func (region *SRegion) GetSecurityGroup(secgroupId string) (*SSecurityGroup, error) { + secgroups, err := region.GetSecurityGroups(secgroupId, "") + if err != nil { + return nil, err + } + if len(secgroups) == 1 { + if secgroups[0].UUID == secgroupId { + return &secgroups[0], nil + } + return nil, cloudprovider.ErrNotFound + } + if len(secgroups) == 0 { + return nil, cloudprovider.ErrNotFound + } + return nil, cloudprovider.ErrDuplicateId +} + +func (region *SRegion) GetSecurityGroups(secgroupId string, instanceId string) ([]SSecurityGroup, error) { + secgroups := []SSecurityGroup{} + params := []string{} + if len(secgroupId) > 0 { + params = append(params, "q=uuid="+secgroupId) + } + if len(instanceId) > 0 { + params = append(params, "q=vmNic.vmInstanceUuid="+instanceId) + } + err := region.client.listAll("security-groups", params, &secgroups) + if err != nil { + return nil, err + } + for i := 0; i < len(secgroups); i++ { + secgroups[i].region = region + } + return secgroups, nil +} + +func (self *SSecurityGroup) GetVpcId() string { + return api.NORMAL_VPC_ID +} + +func (self *SSecurityGroup) GetMetadata() *jsonutils.JSONDict { + data := jsonutils.NewDict() + return data +} + +func (self *SSecurityGroup) GetId() string { + return self.UUID +} + +func (self *SSecurityGroup) GetGlobalId() string { + return self.UUID +} + +func (self *SSecurityGroup) GetDescription() string { + return self.Description +} + +func (self *SSecurityGroup) GetRules() ([]secrules.SecurityRule, error) { + rules := []secrules.SecurityRule{} + priority := 100 + outRuleCount := 0 + for i := 0; i < len(self.Rules); i++ { + if self.Rules[i].IPVersion == 4 { + rule := secrules.SecurityRule{ + Direction: secrules.DIR_IN, + Action: secrules.SecurityRuleAllow, + Priority: priority, + Protocol: secrules.PROTO_ANY, + PortStart: self.Rules[i].StartPort, + PortEnd: self.Rules[i].EndPort, + } + _, ipNet, err := net.ParseCIDR(self.Rules[i].AllowedCIDR) + if err != nil { + return nil, err + } + rule.IPNet = ipNet + if self.Rules[i].Type == "Egress" { + rule.Direction = secrules.DIR_OUT + outRuleCount++ + } + if self.Rules[i].Protocol != "ALL" { + rule.Protocol = strings.ToLower(self.Rules[i].Protocol) + } + rules = append(rules, rule) + priority-- + } + } + if outRuleCount != 0 { + rule := secrules.MustParseSecurityRule("out:deny any") + rule.Priority = 1 + rules = append(rules, *rule) + } + return rules, nil +} + +func (self *SSecurityGroup) GetName() string { + return self.Name +} + +func (self *SSecurityGroup) GetStatus() string { + return "" +} + +func (self *SSecurityGroup) IsEmulated() bool { + return false +} + +func (self *SSecurityGroup) Refresh() error { + new, err := self.region.GetSecurityGroup(self.UUID) + if err != nil { + return err + } + return jsonutils.Update(self, new) +} + +func (self *SSecurityGroup) GetProjectId() string { + return "" +} diff --git a/pkg/util/zstack/shell/cluster.go b/pkg/util/zstack/shell/cluster.go new file mode 100644 index 0000000000..5b13cb05b1 --- /dev/null +++ b/pkg/util/zstack/shell/cluster.go @@ -0,0 +1,21 @@ +package shell + +import ( + "yunion.io/x/onecloud/pkg/util/shellutils" + "yunion.io/x/onecloud/pkg/util/zstack" +) + +func init() { + type ClusterListOptions struct { + StorageId string + DiskId string + } + shellutils.R(&ClusterListOptions{}, "cluster-list", "List clusters", func(cli *zstack.SRegion, args *ClusterListOptions) error { + clusters, err := cli.GetClusters() + if err != nil { + return err + } + printList(clusters, len(clusters), 0, 0, []string{}) + return nil + }) +} diff --git a/pkg/util/zstack/shell/disk.go b/pkg/util/zstack/shell/disk.go new file mode 100644 index 0000000000..d5d1273b57 --- /dev/null +++ b/pkg/util/zstack/shell/disk.go @@ -0,0 +1,21 @@ +package shell + +import ( + "yunion.io/x/onecloud/pkg/util/shellutils" + "yunion.io/x/onecloud/pkg/util/zstack" +) + +func init() { + type DiskListOptions struct { + StorageId string + DiskId string + } + shellutils.R(&DiskListOptions{}, "disk-list", "List disks", func(cli *zstack.SRegion, args *DiskListOptions) error { + disks, err := cli.GetDisks(args.StorageId, args.DiskId) + if err != nil { + return err + } + printList(disks, len(disks), 0, 0, []string{}) + return nil + }) +} diff --git a/pkg/util/zstack/shell/doc.go b/pkg/util/zstack/shell/doc.go new file mode 100644 index 0000000000..cd762b7aeb --- /dev/null +++ b/pkg/util/zstack/shell/doc.go @@ -0,0 +1 @@ +package shell // import "yunion.io/x/onecloud/pkg/util/zstack/shell" diff --git a/pkg/util/zstack/shell/eip.go b/pkg/util/zstack/shell/eip.go new file mode 100644 index 0000000000..d6d0cde148 --- /dev/null +++ b/pkg/util/zstack/shell/eip.go @@ -0,0 +1,22 @@ +package shell + +import ( + "yunion.io/x/onecloud/pkg/util/shellutils" + "yunion.io/x/onecloud/pkg/util/zstack" +) + +func init() { + type EipListOptions struct { + EipId string + InstanceId string + } + shellutils.R(&EipListOptions{}, "eip-list", "List eips", func(cli *zstack.SRegion, args *EipListOptions) error { + eips, err := cli.GetEips(args.EipId, args.InstanceId) + if err != nil { + return err + } + printList(eips, 0, 0, 0, []string{}) + return nil + }) + +} diff --git a/pkg/util/zstack/shell/host.go b/pkg/util/zstack/shell/host.go index 967d5cef9d..83d6344ba0 100644 --- a/pkg/util/zstack/shell/host.go +++ b/pkg/util/zstack/shell/host.go @@ -7,14 +7,11 @@ import ( func init() { type HostListOptions struct { - ZONE string + ZoneId string + HostId string } shellutils.R(&HostListOptions{}, "host-list", "List hosts", func(cli *zstack.SRegion, args *HostListOptions) error { - zone, err := cli.GetIZoneById(args.ZONE) - if err != nil { - return err - } - hosts, err := zone.GetIHosts() + hosts, err := cli.GetHosts(args.ZoneId, args.HostId) if err != nil { return err } diff --git a/pkg/util/zstack/shell/image.go b/pkg/util/zstack/shell/image.go new file mode 100644 index 0000000000..f48baa0d54 --- /dev/null +++ b/pkg/util/zstack/shell/image.go @@ -0,0 +1,21 @@ +package shell + +import ( + "yunion.io/x/onecloud/pkg/util/shellutils" + "yunion.io/x/onecloud/pkg/util/zstack" +) + +func init() { + type ImageListOptions struct { + ImageId string + } + shellutils.R(&ImageListOptions{}, "image-list", "List images", func(cli *zstack.SRegion, args *ImageListOptions) error { + images, err := cli.GetImages(args.ImageId) + if err != nil { + return err + } + printList(images, 0, 0, 0, []string{}) + return nil + }) + +} diff --git a/pkg/util/zstack/shell/instance.go b/pkg/util/zstack/shell/instance.go new file mode 100644 index 0000000000..6ea83a42e3 --- /dev/null +++ b/pkg/util/zstack/shell/instance.go @@ -0,0 +1,47 @@ +package shell + +import ( + "fmt" + + "yunion.io/x/onecloud/pkg/util/shellutils" + "yunion.io/x/onecloud/pkg/util/zstack" +) + +func init() { + type InstanceListOptions struct { + HostId string + InstanceId string + NicId string + } + shellutils.R(&InstanceListOptions{}, "instance-list", "List instances", func(cli *zstack.SRegion, args *InstanceListOptions) error { + instances, err := cli.GetInstances(args.HostId, args.InstanceId, args.NicId) + if err != nil { + return err + } + printList(instances, len(instances), 0, 0, []string{}) + return nil + }) + + type InstanceOperation struct { + ID string + } + + shellutils.R(&InstanceOperation{}, "instance-console-password", "Show instance console password", func(cli *zstack.SRegion, args *InstanceOperation) error { + password, err := cli.GetInstanceConsolePassword(args.ID) + if err != nil { + return err + } + fmt.Println(password) + return nil + }) + + shellutils.R(&InstanceOperation{}, "instance-console-info", "Show instance console info", func(cli *zstack.SRegion, args *InstanceOperation) error { + info, err := cli.GetInstanceConsoleInfo(args.ID) + if err != nil { + return err + } + printObject(info) + return nil + }) + +} diff --git a/pkg/util/zstack/shell/network.go b/pkg/util/zstack/shell/network.go new file mode 100644 index 0000000000..8afde8b702 --- /dev/null +++ b/pkg/util/zstack/shell/network.go @@ -0,0 +1,23 @@ +package shell + +import ( + "yunion.io/x/onecloud/pkg/util/shellutils" + "yunion.io/x/onecloud/pkg/util/zstack" +) + +func init() { + type NetworkListOptions struct { + ZoneId string + WireId string + VpcId string + NetworkId string + } + shellutils.R(&NetworkListOptions{}, "network-list", "List networks", func(cli *zstack.SRegion, args *NetworkListOptions) error { + networks, err := cli.GetNetworks(args.ZoneId, args.WireId, args.VpcId, args.NetworkId) + if err != nil { + return err + } + printList(networks, len(networks), 0, 0, []string{}) + return nil + }) +} diff --git a/pkg/util/zstack/shell/offering.go b/pkg/util/zstack/shell/offering.go new file mode 100644 index 0000000000..b2df1290a7 --- /dev/null +++ b/pkg/util/zstack/shell/offering.go @@ -0,0 +1,20 @@ +package shell + +import ( + "yunion.io/x/onecloud/pkg/util/shellutils" + "yunion.io/x/onecloud/pkg/util/zstack" +) + +func init() { + type OfferingListOptions struct { + OfferId string + } + shellutils.R(&OfferingListOptions{}, "offering-list", "List instance offerings", func(cli *zstack.SRegion, args *OfferingListOptions) error { + offerings, err := cli.GetInstanceOfferings(args.OfferId) + if err != nil { + return err + } + printList(offerings, len(offerings), 0, 0, []string{}) + return nil + }) +} diff --git a/pkg/util/zstack/shell/securitygroup.go b/pkg/util/zstack/shell/securitygroup.go new file mode 100644 index 0000000000..45ddca51e9 --- /dev/null +++ b/pkg/util/zstack/shell/securitygroup.go @@ -0,0 +1,21 @@ +package shell + +import ( + "yunion.io/x/onecloud/pkg/util/shellutils" + "yunion.io/x/onecloud/pkg/util/zstack" +) + +func init() { + type SecurityGroupListOptions struct { + SecgroupId string + InstanceId string + } + shellutils.R(&SecurityGroupListOptions{}, "security-group-list", "List secgroups", func(cli *zstack.SRegion, args *SecurityGroupListOptions) error { + secgroups, err := cli.GetSecurityGroups(args.SecgroupId, args.InstanceId) + if err != nil { + return err + } + printList(secgroups, len(secgroups), 0, 0, []string{}) + return nil + }) +} diff --git a/pkg/util/zstack/shell/snapshot.go b/pkg/util/zstack/shell/snapshot.go new file mode 100644 index 0000000000..e41235d43b --- /dev/null +++ b/pkg/util/zstack/shell/snapshot.go @@ -0,0 +1,21 @@ +package shell + +import ( + "yunion.io/x/onecloud/pkg/util/shellutils" + "yunion.io/x/onecloud/pkg/util/zstack" +) + +func init() { + type SnapshotListOptions struct { + SnapshotId string + DiskId string + } + shellutils.R(&SnapshotListOptions{}, "snapshot-list", "List snapshots", func(cli *zstack.SRegion, args *SnapshotListOptions) error { + snapshots, err := cli.GetSnapshots(args.SnapshotId, args.DiskId) + if err != nil { + return err + } + printList(snapshots, len(snapshots), 0, 0, []string{}) + return nil + }) +} diff --git a/pkg/util/zstack/shell/storage.go b/pkg/util/zstack/shell/storage.go index 28e5b0e86f..d79a5024a7 100644 --- a/pkg/util/zstack/shell/storage.go +++ b/pkg/util/zstack/shell/storage.go @@ -1,36 +1,34 @@ package shell import ( - "yunion.io/x/onecloud/pkg/cloudprovider" "yunion.io/x/onecloud/pkg/util/shellutils" "yunion.io/x/onecloud/pkg/util/zstack" ) func init() { type StorageListOptions struct { - ZONE string - Host string + ZoneId string + ClusterId string + Id string } shellutils.R(&StorageListOptions{}, "storage-list", "List storages", func(cli *zstack.SRegion, args *StorageListOptions) error { - zone, err := cli.GetIZoneById(args.ZONE) + storages, err := cli.GetStorages(args.ZoneId, args.ClusterId, args.Id) if err != nil { return err } - var storages []cloudprovider.ICloudStorage - if len(args.Host) > 0 { - host, err := zone.GetIHostById(args.Host) - if err != nil { - return err - } - storages, err = host.GetIStorages() - if err != nil { - return err - } - } else { - storages, err = zone.GetIStorages() - if err != nil { - return err - } + printList(storages, 0, 0, 0, []string{}) + return nil + }) + + type LocalStorageOptions struct { + STORAGE_ID string + HostId string + } + + shellutils.R(&LocalStorageOptions{}, "local-storage-show", "Show local storages", func(cli *zstack.SRegion, args *LocalStorageOptions) error { + storages, err := cli.GetLocalStorage(args.STORAGE_ID, args.HostId) + if err != nil { + return err } printList(storages, 0, 0, 0, []string{}) return nil diff --git a/pkg/util/zstack/shell/wire.go b/pkg/util/zstack/shell/wire.go new file mode 100644 index 0000000000..9ac1f78c8a --- /dev/null +++ b/pkg/util/zstack/shell/wire.go @@ -0,0 +1,22 @@ +package shell + +import ( + "yunion.io/x/onecloud/pkg/util/shellutils" + "yunion.io/x/onecloud/pkg/util/zstack" +) + +func init() { + type WireListOptions struct { + ZoneId string + WireId string + ClusterId string + } + shellutils.R(&WireListOptions{}, "wire-list", "List wires", func(cli *zstack.SRegion, args *WireListOptions) error { + wires, err := cli.GetWires(args.ZoneId, args.WireId, args.ClusterId) + if err != nil { + return err + } + printList(wires, len(wires), 0, 0, []string{}) + return nil + }) +} diff --git a/pkg/util/zstack/shell/zone.go b/pkg/util/zstack/shell/zone.go index 6e503ef174..d9142c33a4 100644 --- a/pkg/util/zstack/shell/zone.go +++ b/pkg/util/zstack/shell/zone.go @@ -7,15 +7,13 @@ import ( func init() { type ZoneListOptions struct { - Limit int `help:"page size"` - Offset int `help:"page offset"` } shellutils.R(&ZoneListOptions{}, "zone-list", "List zones", func(cli *zstack.SRegion, args *ZoneListOptions) error { zones, err := cli.GetIZones() if err != nil { return err } - printList(zones, len(zones), args.Offset, args.Limit, []string{}) + printList(zones, len(zones), 0, 0, []string{}) return nil }) } diff --git a/pkg/util/zstack/snapshot.go b/pkg/util/zstack/snapshot.go new file mode 100644 index 0000000000..9fc40b72c5 --- /dev/null +++ b/pkg/util/zstack/snapshot.go @@ -0,0 +1,126 @@ +package zstack + +import ( + "yunion.io/x/jsonutils" + "yunion.io/x/log" + "yunion.io/x/onecloud/pkg/cloudprovider" + + api "yunion.io/x/onecloud/pkg/apis/compute" +) + +type SSnapshot struct { + region *SRegion + + ZStackBasic + PrimaryStorageUUID string `json:"primaryStorageUuid"` + VolumeUUID string `json:"volumeUuid"` + VolumeType string `json:"volumeType"` + Format string `json:"format"` + Latest bool `json:"latest"` + Size int `json:"size"` + State string `json:"state"` + Status string `json:"status"` +} + +func (snapshot *SSnapshot) GetId() string { + return snapshot.UUID +} + +func (snapshot *SSnapshot) GetName() string { + return snapshot.Name +} + +func (snapshot *SSnapshot) GetStatus() string { + switch snapshot.Status { + case "Ready": + return api.SNAPSHOT_READY + default: + log.Errorf("unknown snapshot %s(%s) status %s", snapshot.Name, snapshot.UUID, snapshot.Status) + return api.SNAPSHOT_UNKNOWN + } +} + +func (snapshot *SSnapshot) GetSize() int32 { + return int32(snapshot.Size / 1024 / 1024) +} + +func (snapshot *SSnapshot) GetDiskId() string { + return snapshot.VolumeUUID +} + +func (snapshot *SSnapshot) GetDiskType() string { + switch snapshot.VolumeType { + case "Root": + return api.DISK_TYPE_SYS + default: + return api.DISK_TYPE_DATA + } +} + +func (snapshot *SSnapshot) Refresh() error { + new, err := snapshot.region.GetSnapshot(snapshot.UUID) + if err != nil { + return err + } + return jsonutils.Update(snapshot, new) +} + +func (snapshot *SSnapshot) GetGlobalId() string { + return snapshot.UUID +} + +func (snapshot *SSnapshot) IsEmulated() bool { + return false +} + +func (region *SRegion) GetSnapshot(snapshotId string) (*SSnapshot, error) { + snapshots, err := region.GetSnapshots(snapshotId, "") + if err != nil { + return nil, err + } + if len(snapshots) == 1 { + if snapshots[0].UUID == snapshotId { + return &snapshots[0], nil + } + return nil, cloudprovider.ErrNotFound + } + if len(snapshots) == 0 { + return nil, cloudprovider.ErrNotFound + } + return nil, cloudprovider.ErrDuplicateId +} + +func (region *SRegion) GetSnapshots(snapshotId string, diskId string) ([]SSnapshot, error) { + snapshots := []SSnapshot{} + params := []string{} + if len(snapshotId) > 0 { + params = append(params, "q=uuid="+snapshotId) + } + if len(diskId) > 0 { + params = append(params, "q=volumeUuid="+diskId) + } + if err := region.client.listAll("volume-snapshots", params, &snapshots); err != nil { + return nil, err + } + for i := 0; i < len(snapshots); i++ { + snapshots[i].region = region + } + return snapshots, nil +} + +func (snapshot *SSnapshot) Delete() error { + return snapshot.region.DeleteSnapshot(snapshot.UUID) +} + +func (snapshot *SSnapshot) GetMetadata() *jsonutils.JSONDict { + return nil +} + +func (region *SRegion) DeleteSnapshot(snapshotId string) error { + _, err := region.client.delete("volume-snapshots", snapshotId, "Enforcing") + return err +} + +func (snapshot *SSnapshot) GetProjectId() string { + return "" +} diff --git a/pkg/util/zstack/storage.go b/pkg/util/zstack/storage.go index ab7c59bea4..a27900dce5 100644 --- a/pkg/util/zstack/storage.go +++ b/pkg/util/zstack/storage.go @@ -1,12 +1,11 @@ package zstack import ( - "fmt" - "yunion.io/x/jsonutils" "yunion.io/x/log" "yunion.io/x/onecloud/pkg/cloudprovider" - "yunion.io/x/onecloud/pkg/compute/models" + + api "yunion.io/x/onecloud/pkg/apis/compute" ) type TStorageType string @@ -20,14 +19,12 @@ const ( type SStorage struct { zone *SZone - Name string - UUID string - + ZStackBasic VCenterUUID string `json:"VCenterUuid"` Datastore string `json:"datastore"` ZoneUUID string `json:"zoneUuid"` URL string `json:"url"` - TotalCapacity int `json:"totalCapacity"` + TotalCapacity int64 `json:"totalCapacity"` AvailableCapacity int `json:"availableCapacity"` TotalPhysicalCapacity int `json:"totalPhysicalCapacity"` AvailablePhysicalCapacity int `json:"availablePhysicalCapacity"` @@ -36,9 +33,7 @@ type SStorage struct { Status string `json:"status"` MountPath string `json:"mountPath"` AttachedClusterUUIDs []string `json:"attachedClusterUuids"` - - //CreateDate time.Time `json:"createDate"` - //LastOpDate time.Time `json:"lastOpDate"` + ZStackTime } func (storage *SStorage) GetMetadata() *jsonutils.JSONDict { @@ -79,15 +74,15 @@ func (storage *SStorage) GetIDisks() ([]cloudprovider.ICloudDisk, error) { } func (storage *SStorage) GetStorageType() string { - return fmt.Sprintf("ZStack/%s", storage.Type) + return string(storage.Type) } func (storage *SStorage) GetMediumType() string { - return models.DISK_TYPE_ROTATE + return api.DISK_TYPE_ROTATE } -func (storage *SStorage) GetCapacityMB() int { - return storage.TotalCapacity / 1024 +func (storage *SStorage) GetCapacityMB() int64 { + return storage.TotalCapacity / 1024 / 1024 } func (storage *SStorage) GetStorageConf() jsonutils.JSONObject { @@ -101,9 +96,9 @@ func (storage *SStorage) GetManagerId() string { func (storage *SStorage) GetStatus() string { if storage.Status == "Connected" { - return models.STORAGE_ONLINE + return api.STORAGE_ONLINE } - return models.STORAGE_OFFLINE + return api.STORAGE_OFFLINE } func (storage *SStorage) Refresh() error { @@ -116,8 +111,8 @@ func (storage *SStorage) GetEnabled() bool { } func (storage *SStorage) GetIStoragecache() cloudprovider.ICloudStoragecache { - return nil - //return storage.zone.region.getStoragecache() + storage.zone.region.GetIStoragecaches() + return storage.zone.region.storageCache } func (storage *SStorage) CreateIDisk(name string, sizeGb int, desc string) (cloudprovider.ICloudDisk, error) { @@ -136,14 +131,22 @@ func (storage *SStorage) CreateIDisk(name string, sizeGb int, desc string) (clou return nil, cloudprovider.ErrNotImplemented } -func (storage *SStorage) GetIDiskById(idStr string) (cloudprovider.ICloudDisk, error) { - return nil, cloudprovider.ErrNotImplemented - // if disk, err := storage.zone.region.getDisk(idStr); err != nil { - // return nil, err - // } else { - // disk.storage = storage - // return disk, nil - // } +func (storage *SStorage) GetIDiskById(diskId string) (cloudprovider.ICloudDisk, error) { + disks, err := storage.zone.region.GetDisks(storage.UUID, diskId) + if err != nil { + return nil, err + } + if len(disks) == 1 { + if disks[0].UUID == diskId { + disks[0].storage = storage + return &disks[0], nil + } + return nil, cloudprovider.ErrNotFound + } + if len(disks) == 0 { + return nil, cloudprovider.ErrNotFound + } + return nil, cloudprovider.ErrDuplicateId } func (storage *SStorage) GetMountPoint() string { diff --git a/pkg/util/zstack/storagecache.go b/pkg/util/zstack/storagecache.go new file mode 100644 index 0000000000..64a07ddfaf --- /dev/null +++ b/pkg/util/zstack/storagecache.go @@ -0,0 +1,84 @@ +package zstack + +import ( + "context" + "fmt" + + "yunion.io/x/jsonutils" + "yunion.io/x/onecloud/pkg/cloudprovider" + "yunion.io/x/onecloud/pkg/mcclient" +) + +type SStoragecache struct { + region *SRegion +} + +func (scache *SStoragecache) GetMetadata() *jsonutils.JSONDict { + return nil +} + +func (scache *SStoragecache) GetId() string { + return fmt.Sprintf("%s-%s", scache.region.client.providerID, scache.region.GetId()) +} + +func (scache *SStoragecache) GetName() string { + return fmt.Sprintf("%s-%s", scache.region.client.providerName, scache.region.GetId()) +} + +func (scache *SStoragecache) GetStatus() string { + return "available" +} + +func (scache *SStoragecache) Refresh() error { + return nil +} + +func (scache *SStoragecache) GetGlobalId() string { + return fmt.Sprintf("%s-%s", scache.region.client.providerID, scache.region.GetGlobalId()) +} + +func (scache *SStoragecache) IsEmulated() bool { + return false +} + +func (scache *SStoragecache) GetManagerId() string { + return scache.region.client.providerID +} + +func (scache *SStoragecache) GetIImages() ([]cloudprovider.ICloudImage, error) { + images, err := scache.region.GetImages("") + if err != nil { + return nil, err + } + iImages := []cloudprovider.ICloudImage{} + for i := 0; i < len(images); i++ { + images[i].storageCache = scache + iImages = append(iImages, &images[i]) + } + return iImages, nil +} + +func (scache *SStoragecache) GetIImageById(extId string) (cloudprovider.ICloudImage, error) { + image, err := scache.region.GetImage(extId) + if err != nil { + return nil, err + } + image.storageCache = scache + return image, nil +} + +func (scache *SStoragecache) GetPath() string { + return "" +} + +func (scache *SStoragecache) UploadImage(ctx context.Context, userCred mcclient.TokenCredential, imageId string, osArch, osType, osDist, osVersion string, extId string, isForce bool) (string, error) { + return "", cloudprovider.ErrNotImplemented +} + +func (scache *SStoragecache) CreateIImage(snapshoutId, imageName, osType, imageDesc string) (cloudprovider.ICloudImage, error) { + return nil, cloudprovider.ErrNotImplemented +} + +func (scache *SStoragecache) DownloadImage(userCred mcclient.TokenCredential, imageId string, extId string, path string) (jsonutils.JSONObject, error) { + return nil, cloudprovider.ErrNotImplemented +} diff --git a/pkg/util/zstack/vpc.go b/pkg/util/zstack/vpc.go new file mode 100644 index 0000000000..84e99f6094 --- /dev/null +++ b/pkg/util/zstack/vpc.go @@ -0,0 +1,104 @@ +package zstack + +import ( + "fmt" + + "yunion.io/x/jsonutils" + "yunion.io/x/onecloud/pkg/cloudprovider" + + api "yunion.io/x/onecloud/pkg/apis/compute" +) + +type SVpc struct { + region *SRegion + + iwires []cloudprovider.ICloudWire +} + +func (vpc *SVpc) GetMetadata() *jsonutils.JSONDict { + return nil +} + +func (vpc *SVpc) GetId() string { + return fmt.Sprintf("%s/vpc", vpc.region.GetGlobalId()) +} + +func (vpc *SVpc) GetName() string { + return "ZStackVPC" +} + +func (vpc *SVpc) GetGlobalId() string { + return vpc.GetId() +} + +func (vpc *SVpc) IsEmulated() bool { + return true +} + +func (vpc *SVpc) GetIsDefault() bool { + return true +} + +func (vpc *SVpc) GetCidrBlock() string { + return "" +} + +func (vpc *SVpc) GetStatus() string { + return api.VPC_STATUS_AVAILABLE +} + +func (vpc *SVpc) Refresh() error { + return nil +} + +func (vpc *SVpc) GetRegion() cloudprovider.ICloudRegion { + return vpc.region +} + +func (vpc *SVpc) GetIWires() ([]cloudprovider.ICloudWire, error) { + if vpc.iwires == nil || len(vpc.iwires) == 0 { + vpc.iwires = []cloudprovider.ICloudWire{} + wires, err := vpc.region.GetWires("", "", "") + if err != nil { + return nil, err + } + for i := 0; i < len(wires); i++ { + wires[i].vpc = vpc + vpc.iwires = append(vpc.iwires, &wires[i]) + } + } + return vpc.iwires, nil +} + +func (vpc *SVpc) GetIWireById(wireId string) (cloudprovider.ICloudWire, error) { + wire, err := vpc.region.GetWire(wireId) + if err != nil { + return nil, err + } + wire.vpc = vpc + return wire, nil +} + +func (vpc *SVpc) GetISecurityGroups() ([]cloudprovider.ICloudSecurityGroup, error) { + secgroups, err := vpc.region.GetSecurityGroups("", "") + if err != nil { + return nil, err + } + isecgroups := []cloudprovider.ICloudSecurityGroup{} + for i := 0; i < len(secgroups); i++ { + isecgroups = append(isecgroups, &secgroups[i]) + } + return isecgroups, nil +} + +func (vpc *SVpc) GetIRouteTables() ([]cloudprovider.ICloudRouteTable, error) { + return nil, cloudprovider.ErrNotSupported +} + +func (vpc *SVpc) GetManagerId() string { + return vpc.region.client.providerID +} + +func (vpc *SVpc) Delete() error { + return nil +} diff --git a/pkg/util/zstack/wire.go b/pkg/util/zstack/wire.go new file mode 100644 index 0000000000..4d55fe7902 --- /dev/null +++ b/pkg/util/zstack/wire.go @@ -0,0 +1,129 @@ +package zstack + +import ( + "strings" + + "yunion.io/x/jsonutils" + "yunion.io/x/onecloud/pkg/cloudprovider" +) + +type SWire struct { + vpc *SVpc + + inetworks []cloudprovider.ICloudNetwork + + ZStackBasic + Vlan int `json:"vlan"` + ZoneUUID string `json:"zoneUuid"` + PhysicalInterface string `json:"physicalInterface"` + Type string `json:"type"` + ZStackTime + AttachedClusterUUIDs []string `json:"attachedClusterUuids"` +} + +func (region *SRegion) GetWire(wireId string) (*SWire, error) { + wires, err := region.GetWires("", wireId, "") + if err != nil { + return nil, err + } + if len(wires) == 1 { + if wires[0].UUID == wireId { + return &wires[0], nil + } + return nil, cloudprovider.ErrNotFound + } + if len(wires) == 0 { + return nil, cloudprovider.ErrNotFound + } + return nil, cloudprovider.ErrDuplicateId +} + +func (region *SRegion) GetWires(zoneId string, wireId string, clusterId string) ([]SWire, error) { + wires := []SWire{} + clusterIds, err := region.GetClusterIds() + if err != nil { + return nil, err + } + params := []string{"q=attachedClusterUuids?=" + strings.Join(clusterIds, ",")} + if len(clusterId) > 0 { + params = []string{"q=attachedClusterUuids?=" + clusterId} + } + if len(zoneId) > 0 { + params = append(params, "q=zone.uuid="+zoneId) + } + if len(wireId) > 0 { + params = append(params, "q=uuid="+wireId) + } + err = region.client.listAll("l2-networks", params, &wires) + if err != nil { + return nil, err + } + for i := 0; i < len(wires); i++ { + wires[i].vpc = region.GetVpc() + } + return wires, nil +} + +func (wire *SWire) GetMetadata() *jsonutils.JSONDict { + return nil +} + +func (wire *SWire) GetId() string { + return wire.UUID +} + +func (wire *SWire) GetName() string { + return wire.Name +} + +func (wire *SWire) IsEmulated() bool { + return false +} + +func (wire *SWire) GetStatus() string { + return "available" +} + +func (wire *SWire) Refresh() error { + return nil +} + +func (wire *SWire) GetGlobalId() string { + return wire.UUID +} + +func (wire *SWire) GetIVpc() cloudprovider.ICloudVpc { + return nil +} + +func (wire *SWire) GetIZone() cloudprovider.ICloudZone { + zone, _ := wire.vpc.region.GetZone(wire.ZoneUUID) + return zone +} + +func (wire *SWire) GetINetworks() ([]cloudprovider.ICloudNetwork, error) { + if wire.inetworks == nil || len(wire.inetworks) == 0 { + networks, err := wire.vpc.region.GetNetworks(wire.ZoneUUID, wire.UUID, "", "") + if err != nil { + return nil, err + } + wire.inetworks = []cloudprovider.ICloudNetwork{} + for i := 0; i < len(networks); i++ { + networks[i].wire = wire + wire.inetworks = append(wire.inetworks, &networks[i]) + } + } + return wire.inetworks, nil +} + +func (wire *SWire) GetBandwidth() int { + return 10000 +} + +func (wire *SWire) CreateINetwork(name string, cidr string, desc string) (cloudprovider.ICloudNetwork, error) { + return nil, cloudprovider.ErrNotImplemented +} + +func (wire *SWire) GetINetworkById(netid string) (cloudprovider.ICloudNetwork, error) { + return nil, cloudprovider.ErrNotImplemented +} diff --git a/pkg/util/zstack/zone.go b/pkg/util/zstack/zone.go index 4dc3bdc173..234d09865b 100644 --- a/pkg/util/zstack/zone.go +++ b/pkg/util/zstack/zone.go @@ -2,23 +2,22 @@ package zstack import ( "yunion.io/x/jsonutils" + "yunion.io/x/log" "yunion.io/x/onecloud/pkg/cloudprovider" - "yunion.io/x/onecloud/pkg/compute/models" + + api "yunion.io/x/onecloud/pkg/apis/compute" ) type SZone struct { region *SRegion - Name string - UUID string - Description string - Type string - State string + ZStackBasic + Type string + State string iwires []cloudprovider.ICloudWire istorages []cloudprovider.ICloudStorage - //storageTypes []string ihosts []cloudprovider.ICloudHost } @@ -44,9 +43,9 @@ func (zone *SZone) IsEmulated() bool { func (zone *SZone) GetStatus() string { if zone.State == "Enabled" { - return models.ZONE_ENABLE + return api.ZONE_ENABLE } - return models.ZONE_DISABLE + return api.ZONE_DISABLE } func (zone *SZone) Refresh() error { @@ -58,29 +57,63 @@ func (zone *SZone) GetIRegion() cloudprovider.ICloudRegion { return zone.region } -func (zone *SZone) getStorages(clusterUUID string) ([]SStorage, error) { - storages := []SStorage{} - params := []string{"q=zone.uuid=" + zone.UUID} - if len(clusterUUID) > 0 { - params = append(params, "q=cluster.uuid="+clusterUUID) +func (region *SRegion) GetStorageWithZone(storageId string) (*SStorage, error) { + storage, err := region.GetStorage(storageId) + if err != nil { + log.Errorf("failed to found storage %s error: %v", storageId, err) + return nil, err } - err := zone.region.client.listAll("primary-storage", params, &storages) + zone, err := region.GetZone(storage.ZoneUUID) if err != nil { return nil, err } - for i := 0; i < len(storages); i++ { - storages[i].zone = zone - } - return storages, nil + storage.zone = zone + return storage, nil } -func (zone *SZone) fetchStorages(clusterUUID string) error { - storages, err := zone.getStorages("") +func (region *SRegion) GetStorage(storageId string) (*SStorage, error) { + storages, err := region.GetStorages("", "", storageId) + if err != nil { + return nil, err + } + if len(storages) == 1 { + if storages[0].UUID == storageId { + return &storages[0], nil + } + return nil, cloudprovider.ErrNotFound + } + if len(storages) == 0 { + return nil, cloudprovider.ErrNotFound + } + return nil, cloudprovider.ErrDuplicateId +} + +func (region *SRegion) GetStorages(zoneId, clusterId, storageId string) ([]SStorage, error) { + storages := []SStorage{} + params := []string{} + if len(zoneId) > 0 { + params = append(params, "q=zone.uuid="+zoneId) + } + if len(clusterId) > 0 { + params = append(params, "q=cluster.uuid="+clusterId) + } + if SkipEsxi { + params = append(params, "q=type!=VCenter") + } + if len(storageId) > 0 { + params = append(params, "q=uuid="+storageId) + } + return storages, region.client.listAll("primary-storage", params, &storages) +} + +func (zone *SZone) fetchStorages(clusterId string) error { + storages, err := zone.region.GetStorages(zone.UUID, clusterId, "") if err != nil { return err } zone.istorages = []cloudprovider.ICloudStorage{} for i := 0; i < len(storages); i++ { + storages[i].zone = zone zone.istorages = append(zone.istorages, &storages[i]) } return nil @@ -93,32 +126,67 @@ func (zone *SZone) GetIStorages() ([]cloudprovider.ICloudStorage, error) { return zone.istorages, nil } -func (zone *SZone) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) { - return nil, cloudprovider.ErrNotFound -} - -func (zone *SZone) GetIHostById(id string) (cloudprovider.ICloudHost, error) { - hosts := []SHost{} - params := []string{"q=uuid=" + id, "q=zone.uuid=" + zone.UUID} - err := zone.region.client.listAll("hosts", params, &hosts) +func (zone *SZone) GetIStorageById(storageId string) (cloudprovider.ICloudStorage, error) { + storages, err := zone.region.GetStorages(zone.UUID, "", storageId) if err != nil { return nil, err } - count := len(hosts) - switch count { - case 0: + if len(storages) == 1 { + if storages[0].UUID == storageId { + storages[0].zone = zone + return &storages[0], nil + } return nil, cloudprovider.ErrNotFound - case 1: - hosts[0].zone = zone - return &hosts[0], nil - default: - return nil, cloudprovider.ErrDuplicateId } + if len(storages) == 0 { + return nil, cloudprovider.ErrNotFound + } + return nil, cloudprovider.ErrDuplicateId +} + +func (region *SRegion) GetHosts(zoneId string, hostId string) ([]SHost, error) { + hosts := []SHost{} + params := []string{} + if len(zoneId) > 0 { + params = append(params, "q=zone.uuid="+zoneId) + } + if len(hostId) > 0 { + params = append(params, "q=uuid="+hostId) + } + if SkipEsxi { + params = append(params, "q=hypervisorType!=ESX") + } + return hosts, region.client.listAll("hosts", params, &hosts) +} + +func (region *SRegion) GetHost(zoneId string, hostId string) (*SHost, error) { + hosts, err := region.GetHosts(zoneId, hostId) + if err != nil { + return nil, err + } + if len(hosts) == 1 { + if hosts[0].UUID == hostId { + return &hosts[0], nil + } + return nil, cloudprovider.ErrNotFound + } + if len(hosts) == 0 { + return nil, cloudprovider.ErrNotFound + } + return nil, cloudprovider.ErrDuplicateId +} + +func (zone *SZone) GetIHostById(hostId string) (cloudprovider.ICloudHost, error) { + host, err := zone.region.GetHost(zone.UUID, hostId) + if err != nil { + return nil, err + } + host.zone = zone + return host, nil } func (zone *SZone) fetchHosts() error { - hosts := []SHost{} - err := zone.region.client.listAll("hosts", []string{"q=zoneUuid=" + zone.UUID}, &hosts) + hosts, err := zone.region.GetHosts(zone.UUID, "") if err != nil { return err } @@ -138,5 +206,15 @@ func (zone *SZone) GetIHosts() ([]cloudprovider.ICloudHost, error) { } func (zone *SZone) GetIWires() ([]cloudprovider.ICloudWire, error) { + if zone.iwires == nil || len(zone.iwires) == 0 { + wires, err := zone.region.GetWires(zone.UUID, "", "") + if err != nil { + return nil, err + } + zone.iwires = []cloudprovider.ICloudWire{} + for i := 0; i < len(wires); i++ { + zone.iwires = append(zone.iwires, &wires[i]) + } + } return zone.iwires, nil } diff --git a/pkg/util/zstack/zstack.go b/pkg/util/zstack/zstack.go index b64e22d820..23e7afbd8c 100644 --- a/pkg/util/zstack/zstack.go +++ b/pkg/util/zstack/zstack.go @@ -6,8 +6,10 @@ import ( "fmt" "net/http" "strings" + "time" "yunion.io/x/jsonutils" + "yunion.io/x/log" api "yunion.io/x/onecloud/pkg/apis/compute" "yunion.io/x/onecloud/pkg/cloudprovider" "yunion.io/x/onecloud/pkg/util/httputils" @@ -19,6 +21,10 @@ const ( ZSTACK_API_VERSION = "v1" ) +var ( + SkipEsxi bool = true +) + type SZStackClient struct { providerID string providerName string @@ -30,7 +36,7 @@ type SZStackClient struct { iregions []cloudprovider.ICloudRegion - Debug bool + debug bool } func NewZStackClient(providerID string, providerName string, authURL string, username string, password string, isDebug bool) (*SZStackClient, error) { @@ -40,7 +46,7 @@ func NewZStackClient(providerID string, providerName string, authURL string, use authURL: authURL, username: username, password: password, - Debug: isDebug, + debug: isDebug, } if err := cli.connect(); err != nil { return nil, err @@ -49,21 +55,27 @@ func NewZStackClient(providerID string, providerName string, authURL string, use return cli, nil } -// func (cli *SZStackClient) fetchRegions() error { -// if err := cli.connect(); err != nil { -// return err -// } +func (cli *SZStackClient) GetSubAccounts() ([]cloudprovider.SSubAccount, error) { + subAccount := cloudprovider.SSubAccount{ + Account: cli.username, + Name: cli.providerName, + HealthStatus: api.CLOUD_PROVIDER_HEALTH_NORMAL, + } + return []cloudprovider.SSubAccount{subAccount}, nil +} -// regions := []SRegion{} -// if err := cli.list("/zstack/v1/zones", ®ions); err != nil { -// return err -// } -// for i := 0; i < len(regions); i++ { -// regions[i].client = cli -// cli.iregions = append(cli.iregions, ®ions[i]) -// } -// return nil -// } +func (cli *SZStackClient) GetIRegions() []cloudprovider.ICloudRegion { + return cli.iregions +} + +func (cli *SZStackClient) GetIRegionById(id string) (cloudprovider.ICloudRegion, error) { + for i := 0; i < len(cli.iregions); i++ { + if cli.iregions[i].GetGlobalId() == id { + return cli.iregions[i], nil + } + } + return nil, cloudprovider.ErrNotFound +} func (cli *SZStackClient) getRequestURL(resource string, params []string) string { return cli.authURL + fmt.Sprintf("/zstack/%s/%s", ZSTACK_API_VERSION, resource) + "?" + strings.Join(params, "&") @@ -80,7 +92,7 @@ func (cli *SZStackClient) connect() error { "password": fmt.Sprintf("%x", sha512.Sum512([]byte(cli.password))), }, }) - _, resp, err := httputils.JSONRequest(client, context.Background(), "PUT", authURL, header, body, cli.Debug) + _, resp, err := httputils.JSONRequest(client, context.Background(), "PUT", authURL, header, body, cli.debug) if err != nil { return err } @@ -124,7 +136,99 @@ func (cli *SZStackClient) _list(resource string, start int, limit int, params [] } params = append(params, fmt.Sprintf("limit=%d", limit)) requestURL := cli.getRequestURL(resource, params) - _, resp, err := httputils.JSONRequest(client, context.Background(), "GET", requestURL, header, nil, cli.Debug) + _, resp, err := httputils.JSONRequest(client, context.Background(), "GET", requestURL, header, nil, cli.debug) + return resp, err +} + +func (cli *SZStackClient) getDeleteURL(resource, resourceId, deleteMode string) string { + return cli.authURL + fmt.Sprintf("/zstack/%s/%s/%s?deleteMode=%s", ZSTACK_API_VERSION, resource, resourceId, deleteMode) +} + +func (cli *SZStackClient) delete(resource, resourceId, deleteMode string) (jsonutils.JSONObject, error) { + return cli._delete(resource, resourceId, deleteMode) +} + +func (cli *SZStackClient) _delete(resource, resourceId, deleteMode string) (jsonutils.JSONObject, error) { + client := httputils.GetDefaultClient() + header := http.Header{} + header.Add("Content-Type", "application/json") + header.Add("Authorization", "OAuth "+cli.sessionID) + requestURL := cli.getDeleteURL(resource, resourceId, deleteMode) + _, resp, err := httputils.JSONRequest(client, context.Background(), "DELETE", requestURL, header, nil, cli.debug) + return resp, err +} + +func (cli *SZStackClient) getURL(resource, resourceId, spec string) string { + return cli.authURL + fmt.Sprintf("/zstack/%s/%s/%s/%s", ZSTACK_API_VERSION, resource, resourceId, spec) +} + +func (cli *SZStackClient) getPostURL(resource string) string { + return cli.authURL + fmt.Sprintf("/zstack/%s/%s", ZSTACK_API_VERSION, resource) +} + +func (cli *SZStackClient) put(resource, resourceId string, params jsonutils.JSONObject) (jsonutils.JSONObject, error) { + return cli._put(resource, resourceId, params) +} + +func (cli *SZStackClient) _put(resource, resourceId string, params jsonutils.JSONObject) (jsonutils.JSONObject, error) { + client := httputils.GetDefaultClient() + header := http.Header{} + header.Add("Content-Type", "application/json") + header.Add("Authorization", "OAuth "+cli.sessionID) + requestURL := cli.getURL(resource, resourceId, "actions") + _, resp, err := httputils.JSONRequest(client, context.Background(), "PUT", requestURL, header, params, cli.debug) + return resp, err +} + +func (cli *SZStackClient) get(resource, resourceId string, spec string) (jsonutils.JSONObject, error) { + return cli._get(resource, resourceId, spec) +} + +func (cli *SZStackClient) _get(resource, resourceId string, spec string) (jsonutils.JSONObject, error) { + client := httputils.GetDefaultClient() + header := http.Header{} + header.Add("Content-Type", "application/json") + header.Add("Authorization", "OAuth "+cli.sessionID) + requestURL := cli.getURL(resource, resourceId, spec) + _, resp, err := httputils.JSONRequest(client, context.Background(), "GET", requestURL, header, nil, cli.debug) + return resp, err +} + +func (cli *SZStackClient) post(resource string, params jsonutils.JSONObject) (jsonutils.JSONObject, error) { + return cli._post(resource, params) +} + +func (cli *SZStackClient) _post(resource string, params jsonutils.JSONObject) (jsonutils.JSONObject, error) { + client := httputils.GetDefaultClient() + header := http.Header{} + header.Add("Content-Type", "application/json") + header.Add("Authorization", "OAuth "+cli.sessionID) + requestURL := cli.getPostURL(resource) + _, resp, err := httputils.JSONRequest(client, context.Background(), "POST", requestURL, header, params, cli.debug) + if err != nil { + return nil, err + } + if resp.Contains("location") { + startTime := time.Now() + timeout := time.Minute * 30 + location, _ := resp.GetString("location") + for { + _resp, err := httputils.Request(client, context.Background(), "GET", location, header, nil, cli.debug) + if err != nil { + return nil, err + } + _, resp, err = httputils.ParseJSONResponse(_resp, err, cli.debug) + if time.Now().Sub(startTime) > timeout { + return nil, fmt.Errorf("timeout for waitting post %s params: %s", requestURL, params.PrettyString()) + } + if _resp.StatusCode != 200 { + log.Debugf("wait for job %s %s complete", requestURL, params.String()) + time.Sleep(5 * time.Second) + continue + } + break + } + } return resp, err } @@ -153,3 +257,7 @@ func (cli *SZStackClient) GetRegions() []SRegion { } return regions } + +func (cli *SZStackClient) GetIProjects() ([]cloudprovider.ICloudProject, error) { + return nil, cloudprovider.ErrNotImplemented +} diff --git a/pkg/util/zstack/zstack_const.go b/pkg/util/zstack/zstack_const.go new file mode 100644 index 0000000000..27dbec2f53 --- /dev/null +++ b/pkg/util/zstack/zstack_const.go @@ -0,0 +1,14 @@ +package zstack + +import "time" + +type ZStackTime struct { + CreateDate time.Time `json:"createDate"` + LastOpDate time.Time `json:"lastOpDate"` +} + +type ZStackBasic struct { + UUID string `json:"uuid"` + Name string `json:"name"` + Description string `json:"description"` +} diff --git a/vendor/yunion.io/x/pkg/util/regutils/regutils.go b/vendor/yunion.io/x/pkg/util/regutils/regutils.go index 8597a56b5c..559bb44a6c 100644 --- a/vendor/yunion.io/x/pkg/util/regutils/regutils.go +++ b/vendor/yunion.io/x/pkg/util/regutils/regutils.go @@ -70,7 +70,7 @@ func init() { ISO_NO_SECOND_TIME_REG = regexp.MustCompile(`^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}Z$`) FULLISO_TIME_REG = regexp.MustCompile(`^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}Z$`) COMPACT_TIME_REG = regexp.MustCompile(`^\d{14}$`) - ZSTACK_TIME_REG = regexp.MustCompile(`^\w+ \d{1,2}, \d{4} \d{1,2}:\d{1,2}:\d{1,2} (AM|PM)$`) //ZStack time format "Apr 1, 2019 3:23:17 PM" + ZSTACK_TIME_REG = regexp.MustCompile(`^\w.+\d{1,2}, \d{4} \d{1,2}:\d{1,2}:\d{1,2} (AM|PM)$`) //ZStack time format "Apr 1, 2019 3:23:17 PM" MYSQL_TIME_REG = regexp.MustCompile(`^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$`) NORMAL_TIME_REG = regexp.MustCompile(`^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$`) FULLNORMAL_TIME_REG = regexp.MustCompile(`^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}$`) diff --git a/vendor/yunion.io/x/pkg/util/timeutils/timeutils.go b/vendor/yunion.io/x/pkg/util/timeutils/timeutils.go index 2eba33ade5..614d0231af 100644 --- a/vendor/yunion.io/x/pkg/util/timeutils/timeutils.go +++ b/vendor/yunion.io/x/pkg/util/timeutils/timeutils.go @@ -133,7 +133,7 @@ func ParseShortDate(str string) (time.Time, error) { } func ParseZStackDate(str string) (time.Time, error) { - return time.ParseInLocation(ZStackTimeFormat, str, time.Local) + return time.Parse(ZStackTimeFormat, str) } func ParseTimeStr(str string) (time.Time, error) {