rebuild root bugfix

This commit is contained in:
TangBin
2019-02-14 12:28:36 +08:00
parent 5fbc28f8aa
commit d927f2dfc4
5 changed files with 93 additions and 22 deletions
+2 -2
View File
@@ -184,11 +184,11 @@ func (self *SHuaweiGuestDriver) RequestDeployGuestOnHost(ctx context.Context, gu
log.Debugf("VMrebuildRoot %s new diskID %s, wait status ready ...", iVM.GetGlobalId(), diskId)
err = cloudprovider.WaitStatus(iVM, models.VM_READY, time.Second*5, time.Second*1800)
err = cloudprovider.WaitStatus(iVM, models.VM_RUNNING, time.Second*5, time.Second*1800)
if err != nil {
return nil, err
}
log.Debugf("VMrebuildRoot %s, and status is ready", iVM.GetGlobalId())
log.Debugf("VMrebuildRoot %s, and status is %s", iVM.GetGlobalId(), iVM.GetStatus())
maxWaitSecs := 300
waited := 0
+4 -1
View File
@@ -4,7 +4,10 @@ package huawei
const DATETIME_FORMAT = "2006-01-02T15:04:05.999999999"
// Task status
const TASK_SUCCESS = "SUCCESS"
const (
TASK_SUCCESS = "SUCCESS"
TASK_FAIL = "FAIL"
)
// Charging Type
const (
+8 -1
View File
@@ -95,6 +95,7 @@ type SDisk struct {
ConsistencygroupID string `json:"consistencygroup_id"`
UpdatedAt string `json:"updated_at"`
DiskType string // 额外添加的字段用于标记是否为系统盘
/*下面这些字段也许不需要*/
ExpiredTime time.Time
}
@@ -233,8 +234,14 @@ func (self *SDisk) GetTemplateId() string {
return self.VolumeImageMetadata.ImageID
}
// Bootable 表示硬盘是否为启动盘。
// 启动盘 != 系统盘(必须是启动盘且挂载在root device上)
func (self *SDisk) GetDiskType() string {
if self.Bootable == "true" {
if self.Bootable != "true" || len(self.Attachments) == 0 {
return models.DISK_TYPE_DATA
}
if self.DiskType == models.DISK_TYPE_SYS {
return models.DISK_TYPE_SYS
} else {
return models.DISK_TYPE_DATA
+68 -17
View File
@@ -96,7 +96,6 @@ type SInstance struct {
Tags []string `json:"tags"`
Description string `json:"description"`
Locked bool `json:"locked"`
Image Image `json:"image"`
ConfigDrive string `json:"config_drive"`
TenantID string `json:"tenant_id"`
UserID string `json:"user_id"`
@@ -156,6 +155,25 @@ func compareSet(currentSet []string, newSet []string) (add []string, remove []st
return add, remove, keep
}
func markDiskType(server *SInstance, disk *SDisk) {
if disk.Bootable != "true" {
return
}
if len(disk.Attachments) == 0 {
return
}
for _, attachment := range disk.Attachments {
if attachment.ServerID == server.GetId() && attachment.Device == server.OSEXTSRVATTRRootDeviceName {
disk.DiskType = models.DISK_TYPE_SYS
return
}
}
return
}
func (self *SInstance) GetId() string {
return self.ID
}
@@ -216,9 +234,9 @@ func (self *SInstance) GetMetadata() *jsonutils.JSONDict {
priceKey := fmt.Sprintf("%s::%s::%s", self.host.zone.region.GetId(), self.GetInstanceType(), lowerOs)
data.Add(jsonutils.NewString(priceKey), "price_key")
data.Add(jsonutils.NewString(self.host.zone.GetGlobalId()), "zone_ext_id")
if len(self.Image.ID) > 0 {
if image, err := self.host.zone.region.GetImage(self.Image.ID); err != nil {
log.Errorf("Failed to find image %s for instance %s zone %s", self.Image.ID, self.GetId(), self.OSEXTAZAvailabilityZone)
if len(self.Metadata.MeteringImageID) > 0 {
if image, err := self.host.zone.region.GetImage(self.Metadata.MeteringImageID); err != nil {
log.Errorf("Failed to find image %s for instance %s zone %s", self.Metadata.MeteringImageID, self.GetId(), self.OSEXTAZAvailabilityZone)
} else if meta := image.GetMetadata(); meta != nil {
data.Update(meta)
}
@@ -281,6 +299,7 @@ func (self *SInstance) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
}
disks[i].storage = storage
idisks[i] = &disks[i]
markDiskType(self, &disks[i])
// todo: 通过这个字段判断可能更准确 "OS-EXT-SRV-ATTR:root_device_name": "/dev/vda"
// 将系统盘放到第0个位置
if disks[i].GetDiskType() == models.DISK_TYPE_SYS {
@@ -481,20 +500,40 @@ func (self *SInstance) UpdateUserData(userData string) error {
// todo: 支持注入user_data
func (self *SInstance) RebuildRoot(ctx context.Context, imageId string, passwd string, publicKey string, sysSizeGB int) (string, error) {
var err error
if self.Image.ID == imageId {
err = self.host.zone.region.RebuildRoot(ctx, self.GetId(), passwd, publicKey)
var jobId string
if self.Metadata.MeteringImageID == imageId {
jobId, err = self.host.zone.region.RebuildRoot(ctx, self.GetId(), passwd, publicKey)
if err != nil {
return "", err
}
} else {
err = self.host.zone.region.ChangeRoot(ctx, self.GetId(), imageId, passwd, publicKey)
jobId, err = self.host.zone.region.ChangeRoot(ctx, self.GetId(), imageId, passwd, publicKey)
if err != nil {
return "", err
}
}
// todo: wait job finished here
return "", nil
err = self.host.zone.region.waitTaskStatus(self.host.zone.region.ecsClient.Servers.ServiceType(), jobId, TASK_SUCCESS, 15*time.Second, 900*time.Second)
if err != nil {
log.Errorf("RebuildRoot task error %s", err)
return "", err
}
err = self.Refresh()
if err != nil {
return "", err
}
idisks, err := self.GetIDisks()
if err != nil {
return "", err
}
if len(idisks) == 0 {
return "", fmt.Errorf("server %s has no volume attached.", self.GetId())
}
return idisks[0].GetId(), nil
}
func (self *SInstance) DeployVM(ctx context.Context, name string, password string, publicKey string, deleteKeypair bool, description string) error {
@@ -883,7 +922,9 @@ func (self *SRegion) UpdateVM(instanceId, name string) error {
return err
}
func (self *SRegion) RebuildRoot(ctx context.Context, instanceId, passwd, publicKeyName string) error {
// https://support.huaweicloud.com/api-ecs/zh-cn_topic_0067876349.html
// 返回job id
func (self *SRegion) RebuildRoot(ctx context.Context, instanceId, passwd, publicKeyName string) (string, error) {
params := jsonutils.NewDict()
reinstallObj := jsonutils.NewDict()
// meta := jsonutils.NewDict()
@@ -893,15 +934,21 @@ func (self *SRegion) RebuildRoot(ctx context.Context, instanceId, passwd, public
} else if len(publicKeyName) > 0 {
reinstallObj.Add(jsonutils.NewString(publicKeyName), "keyname")
} else {
return fmt.Errorf("both password and publicKey are empty.")
return "", fmt.Errorf("both password and publicKey are empty.")
}
params.Add(reinstallObj, "os-reinstall")
_, err := self.ecsClient.Servers.PerformAction2("reinstallos", instanceId, params, "")
return err
ret, err := self.ecsClient.Servers.PerformAction2("reinstallos", instanceId, params, "")
if err != nil {
return "", err
}
return ret.GetString("job_id")
}
func (self *SRegion) ChangeRoot(ctx context.Context, instanceId, imageId, passwd, publicKeyName string) error {
// https://support.huaweicloud.com/api-ecs/zh-cn_topic_0067876971.html
// 返回job id
func (self *SRegion) ChangeRoot(ctx context.Context, instanceId, imageId, passwd, publicKeyName string) (string, error) {
params := jsonutils.NewDict()
changeOsObj := jsonutils.NewDict()
// meta := jsonutils.NewDict()
@@ -911,14 +958,18 @@ func (self *SRegion) ChangeRoot(ctx context.Context, instanceId, imageId, passwd
} else if len(publicKeyName) > 0 {
changeOsObj.Add(jsonutils.NewString(publicKeyName), "keyname")
} else {
return fmt.Errorf("both password and publicKey are empty.")
return "", fmt.Errorf("both password and publicKey are empty.")
}
changeOsObj.Add(jsonutils.NewString(imageId), "imageid")
params.Add(changeOsObj, "os-change")
_, err := self.ecsClient.Servers.PerformAction2("changeos", instanceId, params, "")
return err
ret, err := self.ecsClient.Servers.PerformAction2("changeos", instanceId, params, "")
if err != nil {
return "", err
}
return ret.GetString("job_id")
}
// https://support.huaweicloud.com/api-ecs/zh-cn_topic_0020212692.html
+11 -1
View File
@@ -1,7 +1,10 @@
package huawei
import (
"fmt"
"time"
"yunion.io/x/log"
)
func (self *SRegion) waitTaskStatus(serviceType string, taskId string, targetStatus string, interval time.Duration, timeout time.Duration) error {
@@ -13,6 +16,8 @@ func (self *SRegion) waitTaskStatus(serviceType string, taskId string, targetSta
}
if status == targetStatus {
break
} else if status == TASK_FAIL {
return fmt.Errorf("task %s failed", taskId)
} else {
time.Sleep(interval)
}
@@ -27,7 +32,12 @@ func (self *SRegion) GetTaskStatus(serviceType string, taskId string) (string, e
return "", err
}
return task.GetString("status")
status, err := task.GetString("status")
if status == TASK_FAIL {
log.Debugf("task %s failed: %s", taskId, task.String())
}
return status, err
}
// https://support.huaweicloud.com/api-ecs/zh-cn_topic_0022225398.html