Automatic merge from release/2.1.0 -> release/2.2.0

* commit '1bb838607b441c9e4f14240bcc13c0007cbd2d41':
  minor fixes
  minior fixes
  guestdisk support index filter
  修正:1. 阿里云刚删除主机的IP地址不能占用 2. rebuild root no-account-init无效 3. 其他问题...
This commit is contained in:
邱剑
2018-09-15 21:30:39 +08:00
16 changed files with 144 additions and 25 deletions
+7
View File
@@ -12,6 +12,8 @@ func init() {
type ServerDiskListOptions struct {
options.BaseListOptions
Server string `help:"ID or Name of Server"`
Disk string `help:"ID or name of disk"`
Index int64 `help:"disk index" default:"-1"`
}
R(&ServerDiskListOptions{}, "server-disk-list", "List server disk pairs", func(s *mcclient.ClientSession, args *ServerDiskListOptions) error {
var params *jsonutils.JSONDict
@@ -23,10 +25,15 @@ func init() {
}
}
if args.Index >= 0 {
params.Add(jsonutils.NewInt(args.Index), "index")
}
var result *modules.ListResult
var err error
if len(args.Server) > 0 {
result, err = modules.Serverdisks.ListDescendent(s, args.Server, params)
} else if len(args.Disk) > 0 {
result, err = modules.Serverdisks.ListDescendent2(s, args.Disk, params)
} else {
result, err = modules.Serverdisks.List(s, params)
}
+4
View File
@@ -31,6 +31,10 @@ func (manager *SResourceBaseManager) Query(fields ...string) *sqlchemy.SQuery {
return manager.SModelBaseManager.Query(fields...).IsFalse("deleted")
}
func (manager *SResourceBaseManager) RawQuery(fields ...string) *sqlchemy.SQuery {
return manager.SModelBaseManager.Query(fields...)
}
func CanDelete(model IModel, ctx context.Context) bool {
err := model.ValidateDeleteCondition(ctx)
if err == nil {
+2
View File
@@ -293,4 +293,6 @@ type ICloudNetwork interface {
GetIsPublic() bool
Delete() error
GetAllocTimeoutSeconds() int
}
+2 -2
View File
@@ -188,7 +188,7 @@ func fetchIVMinfo(desc SAliyunVMCreateConfig, iVM cloudprovider.ICloudVM, guestI
func (self *SAliyunGuestDriver) RequestDeployGuestOnHost(ctx context.Context, guest *models.SGuest, host *models.SHost, task taskman.ITask) error {
config := guest.GetDeployConfigOnHost(ctx, host, task.GetParams())
log.Debugf("RequestDeployGuestOnHost: %s", config)
/* onfinish, err := config.GetString("on_finish")
if err != nil {
return err
@@ -400,7 +400,7 @@ func (self *SAliyunGuestDriver) RequestDeployGuestOnHost(ctx context.Context, gu
}
if len(idisks) < len(desc.DataDisks)+1 {
if waited > maxWaitSecs {
log.Errorf("inconsistent disk number, wait timeout, must be something wrong one remote")
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)
+1 -1
View File
@@ -154,7 +154,7 @@ func (self *SManagedVirtualizedGuestDriver) GetGuestVncInfo(userCred mcclient.To
}
func (self *SManagedVirtualizedGuestDriver) RequestRebuildRootDisk(ctx context.Context, guest *models.SGuest, task taskman.ITask) error {
subtask, err := taskman.TaskManager.NewTask(ctx, "ManagedGuestRebuildRootTask", guest, task.GetUserCred(), nil, task.GetTaskId(), "", nil)
subtask, err := taskman.TaskManager.NewTask(ctx, "ManagedGuestRebuildRootTask", guest, task.GetUserCred(), task.GetParams(), task.GetTaskId(), "", nil)
if err != nil {
return err
}
+4 -1
View File
@@ -249,6 +249,9 @@ func (manager *SDiskManager) ValidateCreateData(ctx context.Context, userCred mc
if !utils.IsInStringArray(storage.Status, []string{STORAGE_ENABLED, STORAGE_ONLINE}) {
return nil, httperrors.NewInputParameterError("Cannot create disk with offline storage[%s]", storage.Name)
}
if len(diskConfig.Backend) == 0 {
diskConfig.Backend = storage.StorageType
}
if storage.StorageType != diskConfig.Backend {
return nil, httperrors.NewInputParameterError("Storage type[%s] not match backend %s", storage.StorageType, diskConfig.Backend)
}
@@ -787,7 +790,7 @@ func parseDiskInfo(ctx context.Context, userCred mcclient.TokenCredential, info
}
// default backend and medium type
diskConfig.Backend = STORAGE_LOCAL
diskConfig.Backend = "" // STORAGE_LOCAL
diskConfig.Medium = DISK_TYPE_HYBRID
diskStr, err := info.GetString()
+1
View File
@@ -78,6 +78,7 @@ func (self *SGuestdisk) getExtraInfo(extra *jsonutils.JSONDict) *jsonutils.JSOND
disk := self.GetDisk()
extra.Add(jsonutils.NewInt(int64(disk.DiskSize)), "disk_size")
extra.Add(jsonutils.NewString(disk.Status), "status")
extra.Add(jsonutils.NewString(disk.DiskType), "disk_type")
return extra
}
+28 -1
View File
@@ -137,7 +137,8 @@ func (manager *SGuestnetworkManager) newGuestNetwork(ctx context.Context, userCr
gn.MacAddr = macAddr
if !virtual {
addrTable := network.GetUsedAddresses()
ipAddr, err := network.GetFreeIP(ctx, userCred, addrTable, address, allocDir, reserved)
recentAddrTable := manager.getRecentlyReleasedIPAddresses(network.Id, time.Duration(network.AllocTimoutSeconds)*time.Second)
ipAddr, err := network.GetFreeIP(ctx, userCred, addrTable, recentAddrTable, address, allocDir, reserved)
if err != nil {
return nil, err
}
@@ -552,3 +553,29 @@ func (self *SGuestnetwork) getJsonDescAtHost(host *SHost) jsonutils.JSONObject {
return desc
}
func (manager *SGuestnetworkManager) getRecentlyReleasedIPAddresses(networkId string, recentDuration time.Duration) map[string]bool {
if recentDuration == 0 {
return nil
}
since := time.Now().UTC().Add(-recentDuration)
q := manager.RawQuery("ip_addr")
q = q.Equals("network_id", networkId).IsTrue("deleted")
q = q.GT("deleted_at", since).Distinct()
rows, err := q.Rows()
if err != nil {
log.Errorf("GetRecentlyReleasedIPAddresses fail %s", err)
return nil
}
ret := make(map[string]bool)
for rows.Next() {
var ip string
err = rows.Scan(&ip)
if err != nil {
log.Errorf("scan error %s", err)
} else {
ret[ip] = true
}
}
return ret
}
+29
View File
@@ -582,6 +582,11 @@ func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred m
return nil, httperrors.NewInputParameterError("Invalid root image: %s", err)
}
if len(diskConfig.Backend) == 0 {
diskConfig.Backend = STORAGE_LOCAL
}
rootStorageType := diskConfig.Backend
data.Add(jsonutils.Marshal(diskConfig), "disk.0")
imgProperties := diskConfig.ImageProperties
@@ -713,6 +718,7 @@ func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred m
}
data.Add(jsonutils.NewString(hypervisor), "hypervisor")
// start from data disk
for idx := 1; data.Contains(fmt.Sprintf("disk.%d", idx)); idx += 1 {
diskJson, err := data.Get(fmt.Sprintf("disk.%d", idx))
if err != nil {
@@ -722,6 +728,9 @@ func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred m
if err != nil {
return nil, httperrors.NewInputParameterError("parse disk description error %s", err)
}
if len(diskConfig.Backend) == 0 {
diskConfig.Backend = rootStorageType
}
if len(diskConfig.Driver) == 0 {
diskConfig.Driver = osProf.DiskDriver
}
@@ -2560,6 +2569,9 @@ func (self *SGuest) PerformCreatedisk(ctx context.Context, userCred mcclient.Tok
logclient.AddActionLog(self, logclient.ACT_CREATE, err.Error(), userCred, false)
return nil, httperrors.NewBadRequestError(err.Error())
}
if len(diskInfo.Backend) == 0 {
diskInfo.Backend = self.getDefaultStorageType()
}
disksConf.Set(diskSeq, jsonutils.Marshal(diskInfo))
if _, ok := diskSizes[diskInfo.Backend]; !ok {
diskSizes[diskInfo.Backend] = diskInfo.Size
@@ -2909,12 +2921,18 @@ func (self *SGuest) PerformChangeConfig(ctx context.Context, userCred mcclient.T
if err != nil {
return nil, httperrors.NewBadRequestError("Parse disk info error: %s", err)
}
if len(diskConf.Backend) == 0 {
diskConf.Backend = self.getDefaultStorageType()
}
if diskConf.Size > 0 {
if diskIdx >= len(disks) {
newDisks.Add(jsonutils.Marshal(diskConf), fmt.Sprintf("disk.%d", newDiskIdx))
newDiskIdx += 1
addDisk += diskConf.Size
storage := host.GetLeastUsedStorage(diskConf.Backend)
if storage == nil {
return nil, httperrors.NewResourceNotReadyError("host not connect storage %s", diskConf.Backend)
}
_, ok := diskSizes[storage.Id]
if !ok {
diskSizes[storage.Id] = 0
@@ -4382,3 +4400,14 @@ func (self *SGuest) SetDisableDelete(val bool) error {
})
return err
}
func (self *SGuest) getDefaultStorageType() string {
diskCat := self.CategorizeDisks()
if diskCat.Root != nil {
rootStorage := diskCat.Root.GetStorage()
if rootStorage != nil {
return rootStorage.StorageType
}
}
return STORAGE_LOCAL
}
+27 -6
View File
@@ -101,6 +101,8 @@ type SNetwork struct {
ServerType string `width:"16" charset:"ascii" nullable:"true" list:"user" update:"user" create:"optional"` // Column(VARCHAR(16, charset='ascii'), nullable=True)
AllocPolicy string `width:"16" charset:"ascii" nullable:"true" get:"user" update:"user" create:"optional"` // Column(VARCHAR(16, charset='ascii'), nullable=True)
AllocTimoutSeconds int `default:"0" nullable:"true" get:"admin"`
}
func (manager *SNetworkManager) GetContextManager() []db.IModelManager {
@@ -188,7 +190,22 @@ func (self *SNetwork) getIPRange() netutils.IPV4AddrRange {
return netutils.NewIPV4AddrRange(start, end)
}
func (self *SNetwork) getFreeIP(addrTable map[string]bool, candidate string, allocDir IPAddlocationDirection) (string, error) {
func isIpUsed(ipstr string, addrTable map[string]bool, recentUsedAddrTable map[string]bool) bool {
_, ok := addrTable[ipstr]
if !ok {
recentUsed := false
if recentUsedAddrTable != nil {
if _, ok := recentUsedAddrTable[ipstr]; ok {
recentUsed = true
}
}
return recentUsed
} else {
return true
}
}
func (self *SNetwork) getFreeIP(addrTable map[string]bool, recentUsedAddrTable map[string]bool, candidate string, allocDir IPAddlocationDirection) (string, error) {
iprange := self.getIPRange()
if len(candidate) > 0 {
candIP, err := netutils.NewIPV4Addr(candidate)
@@ -208,7 +225,7 @@ func (self *SNetwork) getFreeIP(addrTable map[string]bool, candidate string, all
if len(allocDir) == 0 || allocDir == IPAllocationStepdown {
ip, _ := netutils.NewIPV4Addr(self.GuestIpEnd)
for iprange.Contains(ip) {
if _, ok := addrTable[ip.String()]; !ok {
if !isIpUsed(ip.String(), addrTable, recentUsedAddrTable) {
return ip.String(), nil
}
ip = ip.StepDown()
@@ -219,7 +236,7 @@ func (self *SNetwork) getFreeIP(addrTable map[string]bool, candidate string, all
const MAX_TRIES = 5
for i := 0; i < MAX_TRIES; i += 1 {
ip := iprange.Random()
if _, ok := addrTable[ip.String()]; !ok {
if !isIpUsed(ip.String(), addrTable, recentUsedAddrTable) {
return ip.String(), nil
}
}
@@ -227,7 +244,7 @@ func (self *SNetwork) getFreeIP(addrTable map[string]bool, candidate string, all
}
ip, _ := netutils.NewIPV4Addr(self.GuestIpStart)
for iprange.Contains(ip) {
if _, ok := addrTable[ip.String()]; !ok {
if !isIpUsed(ip.String(), addrTable, recentUsedAddrTable) {
return ip.String(), nil
}
ip = ip.StepUp()
@@ -236,7 +253,7 @@ func (self *SNetwork) getFreeIP(addrTable map[string]bool, candidate string, all
return "", httperrors.NewInsufficientResourceError("Out of IP address")
}
func (self *SNetwork) GetFreeIP(ctx context.Context, userCred mcclient.TokenCredential, addrTable map[string]bool, candidate string, allocDir IPAddlocationDirection, reserved bool) (string, error) {
func (self *SNetwork) GetFreeIP(ctx context.Context, userCred mcclient.TokenCredential, addrTable map[string]bool, recentUsedAddrTable map[string]bool, candidate string, allocDir IPAddlocationDirection, reserved bool) (string, error) {
if reserved {
rip := ReservedipManager.GetReservedIP(self, candidate)
if rip == nil {
@@ -245,7 +262,7 @@ func (self *SNetwork) GetFreeIP(ctx context.Context, userCred mcclient.TokenCred
rip.Release(ctx, userCred, self)
return candidate, nil
} else {
cand, err := self.getFreeIP(addrTable, candidate, allocDir)
cand, err := self.getFreeIP(addrTable, recentUsedAddrTable, candidate, allocDir)
if err != nil {
return "", err
}
@@ -471,6 +488,8 @@ func (self *SNetwork) SyncWithCloudNetwork(userCred mcclient.TokenCredential, ex
self.ServerType = extNet.GetServerType()
self.IsPublic = extNet.GetIsPublic()
self.AllocTimoutSeconds = extNet.GetAllocTimeoutSeconds()
self.ProjectId = userCred.GetProjectId()
return nil
})
@@ -495,6 +514,8 @@ func (manager *SNetworkManager) newFromCloudNetwork(userCred mcclient.TokenCrede
net.ServerType = extNet.GetServerType()
net.IsPublic = extNet.GetIsPublic()
net.AllocTimoutSeconds = extNet.GetAllocTimeoutSeconds()
net.ProjectId = userCred.GetProjectId()
err := manager.TableSpec().Insert(&net)
@@ -110,6 +110,11 @@ func (self *GuestChangeConfigTask) DoCreateDisksTask(ctx context.Context, guest
}
func (self *GuestChangeConfigTask) OnCreateDisksCompleteFailed(ctx context.Context, obj db.IStandaloneModel, err jsonutils.JSONObject) {
self.markStageFailed(obj, ctx, err.String())
logclient.AddActionLog(obj, logclient.ACT_VM_CHANGE_FLAVOR, err, self.UserCred, false)
}
func (self *GuestChangeConfigTask) OnCreateDisksComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
iVcpuCount, errCpu := self.Params.Get("vcpu_count")
iVmemSize, errMem := self.Params.Get("vmem_size")
+8 -8
View File
@@ -59,6 +59,14 @@ func (self *GuestRebuildRootTask) StartRebuildRootDisk(ctx context.Context, gues
self.SetStage("OnRebuildRootDiskComplete", nil)
guest.SetStatus(self.UserCred, models.VM_REBUILD_ROOT, "")
// clear logininfo
loginParams := make(map[string]interface{})
loginParams["login_account"] = "none"
loginParams["login_key"] = "none"
loginParams["login_key_timestamp"] = "none"
guest.SetAllMetadata(ctx, loginParams, self.UserCred)
guest.GetDriver().RequestRebuildRootDisk(ctx, guest, self)
}
@@ -141,14 +149,6 @@ func (self *KVMGuestRebuildRootTask) OnRebuildRootDiskComplete(ctx context.Conte
guest.SetStatus(self.UserCred, models.VM_DEPLOYING, "")
// params := jsonutils.NewDict()
// params.Set("reset_password", jsonutils.JSONTrue)
// clear logininfo
loginParams := make(map[string]interface{})
loginParams["login_account"] = "none"
loginParams["login_key"] = "none"
loginParams["login_key_timestamp"] = "none"
guest.SetAllMetadata(ctx, loginParams, self.UserCred)
guest.StartGuestDeployTask(ctx, self.UserCred, self.GetParams(), "deploy", self.GetTaskId())
}
+1 -1
View File
@@ -10,7 +10,7 @@ func init() {
"guestdisks",
[]string{"Guest_ID", "Guest",
"Disk_ID", "Disk", "Disk_size",
"Driver", "Cache_mode", "Index", "Status"},
"Driver", "Cache_mode", "Index", "Status", "Disk_type"},
[]string{},
&Servers,
&Disks)
+20 -4
View File
@@ -314,11 +314,27 @@ func (self *SInstance) GetHypervisor() string {
}
func (self *SInstance) StartVM() error {
err := self.host.zone.region.StartVM(self.InstanceId)
if err != nil {
return err
timeout := 300*time.Second
interval := 15*time.Second
startTime := time.Now()
for time.Now().Sub(startTime) < timeout {
err := self.Refresh()
if err != nil {
return err
}
log.Debugf("status %s expect %s", self.GetStatus(), models.VM_RUNNING)
if self.GetStatus() == models.VM_RUNNING {
return nil
} else if self.GetStatus() == models.VM_READY {
err := self.host.zone.region.StartVM(self.InstanceId)
if err != nil {
return err
}
}
time.Sleep(interval)
}
return cloudprovider.WaitStatus(self, models.VM_RUNNING, 5*time.Second, 180*time.Second) // 3minutes
return cloudprovider.ErrTimeout
}
func (self *SInstance) StopVM(isForce bool) error {
+4
View File
@@ -152,3 +152,7 @@ func (self *SRegion) deleteVSwitch(vswitchId string) error {
func (self *SVSwitch) Delete() error {
return self.wire.zone.region.deleteVSwitch(self.VSwitchId)
}
func (self *SVSwitch) GetAllocTimeoutSeconds() int {
return 120 // 2 minutes
}
+1 -1
View File
@@ -16,7 +16,7 @@ const (
ALL_DIGITS = "0123456789"
ALL_LETTERS = "abcdefghijklmnopqrstuvwxyz"
ALL_UPPERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
ALL_PUNC = "~`!@#$%^&*()-_=+[]{}|:':\",./<>?"
ALL_PUNC = "~`!@#$%^&*()-_=+[]{}|:';\",./<>?"
)
type PasswordStrength struct {