mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
Merge pull request #4336 from ioito/hotfix/qx-openstack-optimized
fix: 优化支持openstack重装系统
This commit is contained in:
@@ -59,6 +59,7 @@ const (
|
||||
|
||||
// openstack
|
||||
STORAGE_OPENSTACK_ISCSI = "iscsi"
|
||||
STORAGE_OPENSTACK_NOVA = "nova"
|
||||
|
||||
// Ucloud storage type
|
||||
STORAGE_UCLOUD_CLOUD_NORMAL = "CLOUD_NORMAL" // 普通云盘
|
||||
|
||||
@@ -17,12 +17,18 @@ package guestdrivers
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/compute/options"
|
||||
@@ -71,7 +77,7 @@ func (self *SOpenStackGuestDriver) IsSupportEip() bool {
|
||||
}
|
||||
|
||||
func (self *SOpenStackGuestDriver) GetDefaultSysDiskBackend() string {
|
||||
return api.STORAGE_OPENSTACK_ISCSI
|
||||
return api.STORAGE_OPENSTACK_NOVA
|
||||
}
|
||||
|
||||
func (self *SOpenStackGuestDriver) GetMinimalSysDiskSizeGb() int {
|
||||
@@ -112,7 +118,7 @@ func (self *SOpenStackGuestDriver) IsNeedRestartForResetLoginInfo() bool {
|
||||
}
|
||||
|
||||
func (self *SOpenStackGuestDriver) IsRebuildRootSupportChangeImage() bool {
|
||||
return false
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SOpenStackGuestDriver) GetDeployStatus() ([]string, error) {
|
||||
@@ -142,6 +148,13 @@ func (self *SOpenStackGuestDriver) ValidateCreateData(ctx context.Context, userC
|
||||
if len(input.Eip) > 0 || input.EipBw > 0 {
|
||||
return nil, httperrors.NewUnsupportOperationError("%s not support create virtual machine with eip", self.GetHypervisor())
|
||||
}
|
||||
for i := 1; i < len(input.Disks); i++ {
|
||||
disk := input.Disks[i]
|
||||
if disk.Backend == api.STORAGE_OPENSTACK_NOVA {
|
||||
return nil, httperrors.NewUnsupportOperationError("data disk not support storage type %s", disk.Backend)
|
||||
}
|
||||
}
|
||||
|
||||
return input, nil
|
||||
}
|
||||
|
||||
@@ -149,6 +162,154 @@ func (self *SOpenStackGuestDriver) GetGuestInitialStateAfterCreate() string {
|
||||
return api.VM_RUNNING
|
||||
}
|
||||
|
||||
func (self *SOpenStackGuestDriver) attachDisks(ctx context.Context, ihost cloudprovider.ICloudHost, instanceId string, diskIds []string) {
|
||||
if len(diskIds) == 0 {
|
||||
return
|
||||
}
|
||||
iVM, err := ihost.GetIVMById(instanceId)
|
||||
if err != nil || iVM == nil {
|
||||
log.Errorf("cannot find vm %s", instanceId)
|
||||
return
|
||||
}
|
||||
for _, diskId := range diskIds {
|
||||
err = iVM.AttachDisk(ctx, diskId)
|
||||
if err != nil {
|
||||
log.Errorf("failed to attach disk %s", diskId)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (self *SOpenStackGuestDriver) RemoteDeployGuestForRebuildRoot(ctx context.Context, guest *models.SGuest, ihost cloudprovider.ICloudHost, task taskman.ITask, desc cloudprovider.SManagedVMCreateConfig) (jsonutils.JSONObject, error) {
|
||||
iVM, err := ihost.GetIVMById(guest.GetExternalId())
|
||||
if err != nil || iVM == nil {
|
||||
return nil, fmt.Errorf("cannot find vm %s(%s)", guest.Id, guest.Name)
|
||||
}
|
||||
|
||||
instanceId := iVM.GetGlobalId()
|
||||
|
||||
diskId, err := func() (string, error) {
|
||||
lockman.LockObject(ctx, guest)
|
||||
defer lockman.ReleaseObject(ctx, guest)
|
||||
|
||||
sysDisk, err := guest.GetSystemDisk()
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "guest.GetSystemDisk(")
|
||||
}
|
||||
storage := sysDisk.GetStorage()
|
||||
if storage.StorageType == api.STORAGE_OPENSTACK_NOVA { //不通过镜像创建磁盘的机器
|
||||
return iVM.RebuildRoot(ctx, desc.ExternalImageId, desc.Password, desc.PublicKey, desc.SysDisk.SizeGB)
|
||||
}
|
||||
|
||||
iDisks, err := iVM.GetIDisks()
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "iVM.GetIDisks")
|
||||
}
|
||||
|
||||
detachDisks := []string{}
|
||||
for i, iDisk := range iDisks {
|
||||
if i != 0 {
|
||||
err = iVM.DetachDisk(ctx, iDisk.GetGlobalId())
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "iVM.DetachDisk")
|
||||
}
|
||||
detachDisks = append(detachDisks, iDisk.GetGlobalId())
|
||||
}
|
||||
}
|
||||
defer self.attachDisks(ctx, ihost, instanceId, detachDisks)
|
||||
|
||||
eip, err := guest.GetEip()
|
||||
if err == nil && eip != nil {
|
||||
ieip, err := eip.GetIEip()
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "eip.GetIEip")
|
||||
}
|
||||
err = ieip.Dissociate()
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "ieip.Dissociate")
|
||||
}
|
||||
defer ieip.Associate(instanceId)
|
||||
}
|
||||
err = iVM.DeleteVM(ctx)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "iVM.DeleteVM")
|
||||
}
|
||||
err = cloudprovider.WaitDeleted(iVM, time.Second*5, time.Minute*10)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "WaitDeleted")
|
||||
}
|
||||
desc.DataDisks = []cloudprovider.SDiskInfo{}
|
||||
iVM, err = ihost.CreateVM(&desc)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "ihost.CreateVM")
|
||||
}
|
||||
|
||||
instanceId = iVM.GetGlobalId()
|
||||
db.SetExternalId(guest, task.GetUserCred(), instanceId)
|
||||
initialState := guest.GetDriver().GetGuestInitialStateAfterCreate()
|
||||
log.Debugf("VMrebuildRoot %s new instance, wait status %s ...", iVM.GetGlobalId(), initialState)
|
||||
cloudprovider.WaitStatus(iVM, initialState, time.Second*5, time.Second*1800)
|
||||
|
||||
iVM.StopVM(ctx, true)
|
||||
|
||||
iDisks, err = iVM.GetIDisks()
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "iVM.GetIDisks.AfterCreated")
|
||||
}
|
||||
|
||||
for _, iDisk := range iDisks {
|
||||
return iDisk.GetGlobalId(), nil
|
||||
}
|
||||
return "", fmt.Errorf("failed to found new instance system disk")
|
||||
}()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
initialState := guest.GetDriver().GetGuestInitialStateAfterRebuild()
|
||||
log.Debugf("VMrebuildRoot %s new diskID %s, wait status %s ...", iVM.GetGlobalId(), diskId, initialState)
|
||||
err = cloudprovider.WaitStatus(iVM, initialState, time.Second*5, time.Second*1800)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Debugf("VMrebuildRoot %s, and status is ready", iVM.GetGlobalId())
|
||||
|
||||
maxWaitSecs := 300
|
||||
waited := 0
|
||||
|
||||
for {
|
||||
// hack, wait disk number consistent
|
||||
idisks, err := iVM.GetIDisks()
|
||||
if err != nil {
|
||||
log.Errorf("fail to find VM idisks %s", err)
|
||||
return nil, err
|
||||
}
|
||||
if len(idisks) < len(desc.DataDisks)+1 {
|
||||
if waited > maxWaitSecs {
|
||||
log.Errorf("inconsistent disk number, wait timeout, must be something wrong on remote")
|
||||
return nil, cloudprovider.ErrTimeout
|
||||
}
|
||||
log.Debugf("inconsistent disk number???? %d != %d", len(idisks), len(desc.DataDisks)+1)
|
||||
time.Sleep(time.Second * 5)
|
||||
waited += 5
|
||||
} else {
|
||||
if idisks[0].GetGlobalId() == diskId {
|
||||
break
|
||||
}
|
||||
if waited > maxWaitSecs {
|
||||
return nil, fmt.Errorf("inconsistent sys disk id after rebuild root")
|
||||
}
|
||||
log.Debugf("current system disk id inconsistent %s != %s, try after 5 seconds", idisks[0].GetGlobalId(), diskId)
|
||||
time.Sleep(time.Second * 5)
|
||||
waited += 5
|
||||
}
|
||||
}
|
||||
|
||||
data := fetchIVMinfo(desc, iVM, guest.Id, desc.Account, desc.Password, desc.PublicKey, "rebuild")
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (self *SOpenStackGuestDriver) GetGuestInitialStateAfterRebuild() string {
|
||||
return api.VM_READY
|
||||
}
|
||||
|
||||
@@ -85,6 +85,7 @@ type VolumeImageMetadata struct {
|
||||
}
|
||||
|
||||
type SDisk struct {
|
||||
nova *SNovaStorage
|
||||
storage *SStorage
|
||||
multicloud.SDisk
|
||||
|
||||
@@ -168,6 +169,9 @@ func (disk *SDisk) GetId() string {
|
||||
}
|
||||
|
||||
func (disk *SDisk) Delete(ctx context.Context) error {
|
||||
if disk.nova != nil {
|
||||
return nil
|
||||
}
|
||||
err := disk.storage.zone.region.DeleteDisk(disk.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -195,6 +199,9 @@ func (disk *SDisk) attachInstances(attachments []Attachment) error {
|
||||
}
|
||||
|
||||
func (disk *SDisk) Resize(ctx context.Context, sizeMb int64) error {
|
||||
if disk.nova != nil {
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
instanceIds := []string{}
|
||||
|
||||
for _, attachement := range disk.Attachments {
|
||||
@@ -227,6 +234,9 @@ func (disk *SDisk) IsEmulated() bool {
|
||||
}
|
||||
|
||||
func (disk *SDisk) GetIStorage() (cloudprovider.ICloudStorage, error) {
|
||||
if disk.nova != nil {
|
||||
return disk.nova, nil
|
||||
}
|
||||
return disk.storage, nil
|
||||
}
|
||||
|
||||
@@ -252,14 +262,20 @@ func (disk *SDisk) GetStatus() string {
|
||||
}
|
||||
|
||||
func (disk *SDisk) Refresh() error {
|
||||
new, err := disk.storage.zone.region.GetDisk(disk.ID)
|
||||
if disk.nova != nil {
|
||||
return nil
|
||||
}
|
||||
_disk, err := disk.storage.zone.region.GetDisk(disk.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return jsonutils.Update(disk, new)
|
||||
return jsonutils.Update(disk, _disk)
|
||||
}
|
||||
|
||||
func (disk *SDisk) ResizeDisk(sizeMb int64) error {
|
||||
if disk.nova != nil {
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
return disk.storage.zone.region.ResizeDisk(disk.ID, sizeMb)
|
||||
}
|
||||
|
||||
@@ -394,6 +410,9 @@ func (region *SRegion) ResetDisk(diskId, snapshotId string) error {
|
||||
}
|
||||
|
||||
func (disk *SDisk) CreateISnapshot(ctx context.Context, name, desc string) (cloudprovider.ICloudSnapshot, error) {
|
||||
if disk.nova != nil {
|
||||
return nil, cloudprovider.ErrNotSupported
|
||||
}
|
||||
snapshot, err := disk.storage.zone.region.CreateSnapshot(disk.ID, name, desc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -402,14 +421,23 @@ func (disk *SDisk) CreateISnapshot(ctx context.Context, name, desc string) (clou
|
||||
}
|
||||
|
||||
func (disk *SDisk) GetISnapshot(snapshotId string) (cloudprovider.ICloudSnapshot, error) {
|
||||
if disk.nova != nil {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return disk.storage.zone.region.GetISnapshotById(snapshotId)
|
||||
}
|
||||
|
||||
func (disk *SDisk) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
|
||||
if disk.nova != nil {
|
||||
return []cloudprovider.ICloudSnapshot{}, nil
|
||||
}
|
||||
return disk.storage.zone.region.GetSnapshots(disk.ID)
|
||||
}
|
||||
|
||||
func (disk *SDisk) Reset(ctx context.Context, snapshotId string) (string, error) {
|
||||
if disk.nova != nil {
|
||||
return "", cloudprovider.ErrNotSupported
|
||||
}
|
||||
return disk.ID, disk.storage.zone.region.ResetDisk(disk.ID, snapshotId)
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,22 @@ func (region *SRegion) GetFlavor(flavorId string) (*SFlavor, error) {
|
||||
}
|
||||
|
||||
func (region *SRegion) SyncFlavor(name string, cpu, memoryMb, diskGB int) (string, error) {
|
||||
return region.syncFlavor(name, cpu, memoryMb, diskGB)
|
||||
id, err := region.syncFlavor(name, cpu, memoryMb, diskGB)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "syncFlavor")
|
||||
}
|
||||
flavor, err := region.GetFlavor(id)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "region.GetFlavor(%s)", id)
|
||||
}
|
||||
if flavor.GetCpuCoreCount() != cpu || flavor.GetMemorySizeMB() != memoryMb || flavor.Disk != diskGB {
|
||||
flavor, err = region.CreateFlavor(name, cpu, memoryMb, diskGB)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "CreateFlavor")
|
||||
}
|
||||
return flavor.ID, nil
|
||||
}
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) syncFlavor(name string, cpu, memoryMb, diskGB int) (string, error) {
|
||||
@@ -97,7 +112,7 @@ func (region *SRegion) syncFlavor(name string, cpu, memoryMb, diskGB int) (strin
|
||||
return flavor.ID, nil
|
||||
}
|
||||
}
|
||||
flavor, err := region.CreateFlavor(name, cpu, memoryMb, 40)
|
||||
flavor, err := region.CreateFlavor(name, cpu, memoryMb, diskGB)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "region.CreateClavor()")
|
||||
}
|
||||
|
||||
@@ -129,6 +129,10 @@ func (host *SHost) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
|
||||
result := []cloudprovider.ICloudStorage{}
|
||||
|
||||
for _, istorage := range istorages {
|
||||
if istorage.GetStorageType() == api.STORAGE_OPENSTACK_NOVA {
|
||||
result = append(result, istorage)
|
||||
continue
|
||||
}
|
||||
if storage := istorage.(*SStorage); len(storage.ExtraSpecs.VolumeBackendName) > 0 {
|
||||
for _, pool := range schedulerPools {
|
||||
if strings.HasPrefix(pool.Name, fmt.Sprintf("%s@%s", host.GetName(), storage.ExtraSpecs.VolumeBackendName)) {
|
||||
@@ -197,34 +201,40 @@ func (host *SHost) CreateVM(desc *cloudprovider.SManagedVMCreateConfig) (cloudpr
|
||||
return nil, err
|
||||
}
|
||||
|
||||
storage, err := host.zone.getStorageByCategory(desc.SysDisk.StorageType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sysDiskSizeGB := image.Size / 1024 / 1024 / 1024
|
||||
if desc.SysDisk.SizeGB < sysDiskSizeGB {
|
||||
desc.SysDisk.SizeGB = sysDiskSizeGB
|
||||
}
|
||||
|
||||
_sysDisk, err := host.zone.region.CreateDisk(desc.ExternalImageId, storage.Name, "", desc.SysDisk.SizeGB, desc.SysDisk.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if desc.SysDisk.SizeGB < image.GetMinOsDiskSizeGb() {
|
||||
desc.SysDisk.SizeGB = image.GetMinOsDiskSizeGb()
|
||||
}
|
||||
|
||||
BlockDeviceMappingV2 := []map[string]interface{}{
|
||||
{
|
||||
BlockDeviceMappingV2 := []map[string]interface{}{}
|
||||
|
||||
if desc.SysDisk.StorageType != api.STORAGE_OPENSTACK_NOVA { //新建volume
|
||||
storage, err := host.zone.getStorageByCategory(desc.SysDisk.StorageType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_sysDisk, err := host.zone.region.CreateDisk(desc.ExternalImageId, storage.Name, "", desc.SysDisk.SizeGB, desc.SysDisk.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
BlockDeviceMappingV2 = append(BlockDeviceMappingV2, map[string]interface{}{
|
||||
"boot_index": 0,
|
||||
"uuid": _sysDisk.GetGlobalId(),
|
||||
"source_type": "volume",
|
||||
"destination_type": "volume",
|
||||
"delete_on_termination": true,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
var _disk *SDisk
|
||||
for _, disk := range desc.DataDisks {
|
||||
storage, err = host.zone.getStorageByCategory(disk.StorageType)
|
||||
storage, err := host.zone.getStorageByCategory(disk.StorageType)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
@@ -263,12 +263,16 @@ func (instance *SInstance) GetInstanceType() string {
|
||||
|
||||
func (instance *SInstance) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
|
||||
disks := []SDisk{}
|
||||
hasSysDisk := false
|
||||
for i := 0; i < len(instance.VolumesAttached); i++ {
|
||||
disk, err := instance.host.zone.region.GetDisk(instance.VolumesAttached[i].ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disks = append(disks, *disk)
|
||||
if disk.Bootable {
|
||||
hasSysDisk = true
|
||||
}
|
||||
}
|
||||
iDisks := []cloudprovider.ICloudDisk{}
|
||||
for i := 0; i < len(disks); i++ {
|
||||
@@ -279,6 +283,13 @@ func (instance *SInstance) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
|
||||
disks[i].storage = store
|
||||
iDisks = append(iDisks, &disks[i])
|
||||
}
|
||||
|
||||
if !hasSysDisk {
|
||||
nova := SNovaStorage{zone: instance.host.zone}
|
||||
sysDisk, _ := nova.GetIDiskById(instance.ID)
|
||||
iDisks = append([]cloudprovider.ICloudDisk{sysDisk}, iDisks...)
|
||||
}
|
||||
|
||||
return iDisks, nil
|
||||
}
|
||||
|
||||
@@ -432,11 +443,7 @@ func (instance *SInstance) DeployVM(ctx context.Context, name string, username s
|
||||
}
|
||||
|
||||
func (instance *SInstance) RebuildRoot(ctx context.Context, imageId string, passwd string, publicKey string, sysSizeGB int) (string, error) {
|
||||
sysDiskId := ""
|
||||
if len(instance.VolumesAttached) > 0 {
|
||||
sysDiskId = instance.VolumesAttached[0].ID
|
||||
}
|
||||
return sysDiskId, instance.host.zone.region.ReplaceSystemDisk(instance.ID, imageId, passwd, publicKey, sysSizeGB)
|
||||
return instance.ID, instance.host.zone.region.ReplaceSystemDisk(instance.ID, imageId, passwd, publicKey, sysSizeGB)
|
||||
}
|
||||
|
||||
func (instance *SInstance) ChangeConfig(ctx context.Context, config *cloudprovider.SManagedVMChangeConfig) error {
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package openstack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
type SNovaStorage struct {
|
||||
zone *SZone
|
||||
}
|
||||
|
||||
func (storage *SNovaStorage) GetMetadata() *jsonutils.JSONDict {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (storage *SNovaStorage) GetId() string {
|
||||
return fmt.Sprintf("%s-%s", storage.zone.GetId(), storage.GetName())
|
||||
}
|
||||
|
||||
func (storage *SNovaStorage) GetName() string {
|
||||
return api.STORAGE_OPENSTACK_NOVA
|
||||
}
|
||||
|
||||
func (storage *SNovaStorage) GetGlobalId() string {
|
||||
return storage.GetId()
|
||||
}
|
||||
|
||||
func (storage *SNovaStorage) IsEmulated() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (storage *SNovaStorage) GetIZone() cloudprovider.ICloudZone {
|
||||
return storage.zone
|
||||
}
|
||||
|
||||
func (storage *SNovaStorage) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
|
||||
return []cloudprovider.ICloudDisk{}, nil
|
||||
}
|
||||
|
||||
func (storage *SNovaStorage) GetStorageType() string {
|
||||
return api.STORAGE_OPENSTACK_NOVA
|
||||
}
|
||||
|
||||
func (storage *SNovaStorage) GetMediumType() string {
|
||||
return api.DISK_TYPE_ROTATE
|
||||
}
|
||||
|
||||
func (storage *SNovaStorage) GetCapacityMB() int64 {
|
||||
return 1000000000
|
||||
}
|
||||
|
||||
func (storage *SNovaStorage) GetStorageConf() jsonutils.JSONObject {
|
||||
conf := jsonutils.NewDict()
|
||||
return conf
|
||||
}
|
||||
|
||||
func (storage *SNovaStorage) GetStatus() string {
|
||||
return api.STORAGE_ONLINE
|
||||
}
|
||||
|
||||
func (storage *SNovaStorage) Refresh() error {
|
||||
// do nothing
|
||||
return nil
|
||||
}
|
||||
|
||||
func (storage *SNovaStorage) GetEnabled() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (storage *SNovaStorage) GetIStoragecache() cloudprovider.ICloudStoragecache {
|
||||
return storage.zone.region.getStoragecache()
|
||||
}
|
||||
|
||||
func (storage *SNovaStorage) CreateIDisk(name string, sizeGb int, desc string) (cloudprovider.ICloudDisk, error) {
|
||||
return nil, cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (storage *SNovaStorage) GetIDiskById(idStr string) (cloudprovider.ICloudDisk, error) {
|
||||
instance, err := storage.zone.region.GetInstance(idStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disk := SDisk{
|
||||
ID: instance.ID,
|
||||
Name: fmt.Sprintf("root disk for %s", instance.Name),
|
||||
Size: instance.Flavor.Disk,
|
||||
Status: DISK_STATUS_IN_USE,
|
||||
Bootable: true,
|
||||
CreatedAt: instance.Created,
|
||||
VolumeType: api.STORAGE_OPENSTACK_NOVA,
|
||||
}
|
||||
disk.nova = storage
|
||||
return &disk, nil
|
||||
}
|
||||
|
||||
func (storage *SNovaStorage) GetMountPoint() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (storage *SNovaStorage) IsSysDiskStore() bool {
|
||||
return true
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
@@ -137,7 +138,7 @@ func (region *SRegion) GetIStorageById(id string) (cloudprovider.ICloudStorage,
|
||||
istore, err := izones[i].GetIStorageById(id)
|
||||
if err == nil {
|
||||
return istore, nil
|
||||
} else if err != cloudprovider.ErrNotFound {
|
||||
} else if errors.Cause(err) != cloudprovider.ErrNotFound {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,4 +30,16 @@ func init() {
|
||||
printList(zones, 0, 0, 0, nil)
|
||||
return nil
|
||||
})
|
||||
|
||||
type SchedulerPoolListOptions struct {
|
||||
}
|
||||
shellutils.R(&SchedulerPoolListOptions{}, "scheduler-pool-list", "List scheduler pool", func(cli *openstack.SRegion, args *SchedulerPoolListOptions) error {
|
||||
pools, err := cli.GetSchedulerStatsPool()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(pools, 0, 0, 0, nil)
|
||||
return nil
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
@@ -101,18 +102,26 @@ func (zone *SZone) GetIWires() ([]cloudprovider.ICloudWire, error) {
|
||||
}
|
||||
|
||||
func (zone *SZone) fetchSchedulerStatsPool() error {
|
||||
zone.schedulerPools = []SPool{}
|
||||
for _, service := range []string{"volumev3", "volumev2", "volume"} {
|
||||
_, resp, err := zone.region.List(service, "/scheduler-stats/get_pools", "", nil)
|
||||
if err == nil {
|
||||
if err := resp.Unmarshal(&zone.schedulerPools, "pools"); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
log.Warningf("failed to get scheduler-stats pool by service %s error: %v, try another", service, err)
|
||||
var err error = nil
|
||||
zone.schedulerPools, err = zone.region.GetSchedulerStatsPool()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "GetSchedulerStatsPool")
|
||||
}
|
||||
return fmt.Errorf("failed to find scheduler-stats pool by cinder service")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (region *SRegion) GetSchedulerStatsPool() ([]SPool, error) {
|
||||
pools := []SPool{}
|
||||
for _, service := range []string{"volumev3", "volumev2", "volume"} {
|
||||
_, resp, err := region.List(service, "/scheduler-stats/get_pools", "", nil)
|
||||
if err == nil {
|
||||
if err := resp.Unmarshal(&pools, "pools"); err != nil {
|
||||
return nil, errors.Wrap(err, "resp.Unmarshal(&pools)")
|
||||
}
|
||||
return pools, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("failed to find scheduler-stats pool by cinder service")
|
||||
}
|
||||
|
||||
func (zone *SZone) getSchedulerStatsPool() ([]SPool, error) {
|
||||
@@ -157,10 +166,12 @@ func (zone *SZone) fetchStorages() error {
|
||||
storages[i].zone = zone
|
||||
zone.istorages = append(zone.istorages, &storages[i])
|
||||
}
|
||||
return nil
|
||||
break
|
||||
}
|
||||
log.Debugf("failed to get volume types by service %s error: %v, try another", service, err)
|
||||
}
|
||||
nova := &SNovaStorage{zone: zone}
|
||||
zone.istorages = append(zone.istorages, nova)
|
||||
return fmt.Errorf("failed to find storage types by cinder service")
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user