Merge pull request #215 in YUNIONIO/onecloud from ~QIUJIAN/onecloud:hotfix/qj-bugfix-misc-20180914 to release/2.1.0

* commit 'd9e401249e5ccd4108e011a47e6145d7ee8e7002':
  adjust import order
  fix typos
  增加eip操作的状态变化
  network/wire/vpc增加zone/region信息
  修正:1. 主机创建/rebuild root密码设置问题 2. climc 密码设置问题 3. billing_type字段为空导致创建主机失败问题
This commit is contained in:
邱剑
2018-09-15 12:53:09 +08:00
16 changed files with 358 additions and 79 deletions
+17
View File
@@ -50,6 +50,11 @@ func init() {
if err != nil {
return err
}
if opts.NoAccountInit != nil && *opts.NoAccountInit {
params.Add(jsonutils.JSONFalse, "reset_password")
}
count := options.IntV(opts.Count)
if options.BoolV(opts.DryRun) {
results, err := modules.SchedManager.DoScheduleListResult(s, params, count)
@@ -328,6 +333,11 @@ func init() {
if err != nil {
return err
}
if opts.NoAccountInit != nil && *opts.NoAccountInit {
params.Add(jsonutils.JSONFalse, "reset_password")
}
srv, err := modules.Servers.PerformAction(s, opts.ID, "rebuild-root", params)
if err != nil {
return err
@@ -338,6 +348,13 @@ func init() {
R(&options.ServerChangeConfigOptions{}, "server-change-config", "Change configuration of VM", func(s *mcclient.ClientSession, opts *options.ServerChangeConfigOptions) error {
params, err := options.StructToParams(opts)
if len(opts.Disk) > 0 {
params.Remove("disk.0")
for i, d := range opts.Disk {
params.Set(fmt.Sprintf("disk.%d", i+1), jsonutils.NewString(d))
}
}
if err != nil {
return err
}
+1 -1
View File
@@ -8,7 +8,7 @@ const (
)
type SBillingResourceBase struct {
BillingType string `width:"36" charset:"ascii" nullable:"true" default:"postpaid" list:"user" create:"required"`
BillingType string `width:"36" charset:"ascii" nullable:"true" default:"postpaid" list:"user" create:"optional"`
ExpiredAt time.Time `nullable:"true" list:"user" create:"optional"`
}
+3
View File
@@ -51,6 +51,7 @@ func getHypervisors(zone *SZone) []string {
if zone != nil {
q = q.Equals("zone_id", zone.Id)
}
q = q.IsNotEmpty("host_type").IsNotNull("host_type")
q = q.Distinct()
rows, err := q.Rows()
if err != nil {
@@ -72,6 +73,8 @@ func getStorageTypes(zone *SZone) []string {
if zone != nil {
q = q.Equals("zone_id", zone.Id)
}
q = q.IsNotEmpty("storage_type").IsNotNull("storage_type")
q = q.IsNotEmpty("medium_type").IsNotNull("medium_type")
q = q.Distinct()
rows, err := q.Rows()
if err != nil {
+17 -4
View File
@@ -39,6 +39,8 @@ const (
EIP_STATUS_DISSOCIATE = "dissociate"
EIP_STATUS_DISSOCIATE_FAIL = "dissociate_fail"
EIP_STATUS_CHANGE_BANDWIDTH = "change_bandwidth"
EIP_CHARGE_TYPE_BY_TRAFFIC = "traffic"
EIP_CHARGE_TYPE_BY_BANDWIDTH = "bandwidth"
EIP_CHARGE_TYPE_DEFAULT = EIP_CHARGE_TYPE_BY_TRAFFIC
@@ -178,7 +180,7 @@ func (manager *SElasticipManager) SyncEips(ctx context.Context, userCred mcclien
}
func (self *SElasticip) SyncInstanceWithCloudEip(ctx context.Context, userCred mcclient.TokenCredential, ext cloudprovider.ICloudEIP) error {
vm := self.getVM()
vm := self.GetAssociateVM()
vmExtId := ext.GetAssociationExternalId()
if vm == nil && len(vmExtId) == 0 {
@@ -281,7 +283,7 @@ func (manager *SElasticipManager) getEipForInstance(instanceType string, instanc
return &eip, nil
}
func (self *SElasticip) getVM() *SGuest {
func (self *SElasticip) GetAssociateVM() *SGuest {
if self.AssociateType == "server" && len(self.AssociateId) > 0 {
return GuestManager.FetchGuestById(self.AssociateId)
}
@@ -292,7 +294,7 @@ func (self *SElasticip) Dissociate(ctx context.Context, userCred mcclient.TokenC
if len(self.AssociateType) == 0 {
return nil
}
vm := self.getVM()
vm := self.GetAssociateVM()
if vm == nil {
log.Errorf("dissociate VM not exists???")
}
@@ -305,7 +307,9 @@ func (self *SElasticip) Dissociate(ctx context.Context, userCred mcclient.TokenC
return err
}
if vm != nil {
db.OpsLog.LogDetachEvent(vm, self, userCred, self.GetShortDesc())
db.OpsLog.LogEvent(self, db.ACT_EIP_DETACH, vm.GetShortDesc(), userCred)
db.OpsLog.LogEvent(vm, db.ACT_EIP_DETACH, self.GetShortDesc(), userCred)
}
if self.Mode == EIP_MODE_INSTANCE_PUBLICIP {
self.Delete(ctx, userCred)
@@ -325,7 +329,11 @@ func (self *SElasticip) AssociateVM(userCred mcclient.TokenCredential, vm *SGues
if err != nil {
return err
}
db.OpsLog.LogAttachEvent(vm, self, userCred, self.GetShortDesc())
db.OpsLog.LogEvent(self, db.ACT_EIP_ATTACH, vm.GetShortDesc(), userCred)
db.OpsLog.LogEvent(vm, db.ACT_EIP_ATTACH, self.GetShortDesc(), userCred)
return nil
}
@@ -638,7 +646,7 @@ func (self *SElasticip) GetCustomizeColumns(ctx context.Context, userCred mcclie
}
func (self *SElasticip) getMoreDetails(extra *jsonutils.JSONDict) *jsonutils.JSONDict {
vm := self.getVM()
vm := self.GetAssociateVM()
if vm != nil {
extra.Add(jsonutils.NewString(vm.GetName()), "associate_name")
}
@@ -704,6 +712,9 @@ func (self *SElasticip) PerformChangeBandwidth(ctx context.Context, userCred mcc
}
func (self *SElasticip) StartEipChangeBandwidthTask(ctx context.Context, userCred mcclient.TokenCredential, bandwidth int64) error {
self.SetStatus(userCred, EIP_STATUS_CHANGE_BANDWIDTH, "change bandwidth")
params := jsonutils.NewDict()
params.Add(jsonutils.NewInt(bandwidth), "bandwidth")
@@ -722,6 +733,8 @@ func (self *SElasticip) DoChangeBandwidth(userCred mcclient.TokenCredential, ban
return nil
})
self.SetStatus(userCred, EIP_STATUS_READY, "finish change bandwidth")
if err != nil {
log.Errorf("DoChangeBandwidth update fail %s", err)
return err
+117 -43
View File
@@ -36,6 +36,7 @@ import (
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/util/httputils"
"yunion.io/x/onecloud/pkg/util/logclient"
"yunion.io/x/onecloud/pkg/util/seclib2"
)
const (
@@ -99,6 +100,9 @@ const (
VM_RESTORE_STATE = "restore_state"
VM_RESTORE_FAILED = "restore_failed"
VM_ASSOCIATE_EIP = "associate_eip"
VM_DISSOCIATE_EIP = "dissociate_eip"
VM_REMOVE_STATEFILE = "remove_state"
VM_ADMIN = "admin"
@@ -272,8 +276,8 @@ func (manager *SGuestManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQ
if count > 0 {
sgq := guestdisks.Query(guestdisks.Field("guest_id")).
Filter(sqlchemy.AND(
sqlchemy.Equals(guestdisks.Field("disk_id"), disk.Id),
sqlchemy.IsFalse(guestdisks.Field("deleted"))))
sqlchemy.Equals(guestdisks.Field("disk_id"), disk.Id),
sqlchemy.IsFalse(guestdisks.Field("deleted"))))
q = q.Filter(sqlchemy.In(q.Field("id"), sgq))
} else {
hosts := HostManager.Query().SubQuery()
@@ -281,11 +285,11 @@ func (manager *SGuestManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQ
storages := StorageManager.Query().SubQuery()
sq := hosts.Query(hosts.Field("id")).
Join(hoststorages, sqlchemy.AND(
sqlchemy.Equals(hoststorages.Field("host_id"), hosts.Field("id")),
sqlchemy.IsFalse(hoststorages.Field("deleted")))).
sqlchemy.Equals(hoststorages.Field("host_id"), hosts.Field("id")),
sqlchemy.IsFalse(hoststorages.Field("deleted")))).
Join(storages, sqlchemy.AND(
sqlchemy.Equals(storages.Field("id"), hoststorages.Field("storage_id")),
sqlchemy.IsFalse(storages.Field("deleted")))).
sqlchemy.Equals(storages.Field("id"), hoststorages.Field("storage_id")),
sqlchemy.IsFalse(storages.Field("deleted")))).
Filter(sqlchemy.Equals(storages.Field("id"), disk.StorageId)).SubQuery()
q = q.In("host_id", sq)
}
@@ -339,8 +343,8 @@ func (manager *SGuestManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQ
isodev := IsolatedDeviceManager.Query().SubQuery()
sgq := isodev.Query(isodev.Field("guest_id")).
Filter(sqlchemy.AND(
sqlchemy.IsNotNull(isodev.Field("guest_id")),
sqlchemy.Startswith(isodev.Field("dev_type"), "GPU")))
sqlchemy.IsNotNull(isodev.Field("guest_id")),
sqlchemy.Startswith(isodev.Field("dev_type"), "GPU")))
showGpu := utils.ToBool(gpu)
cond := sqlchemy.NotIn
if showGpu {
@@ -561,6 +565,14 @@ func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred m
data.Add(jsonutils.NewInt(int64(vmemSize)), "vmem_size")
data.Add(jsonutils.NewInt(int64(vcpuCount)), "vcpu_count")
resetPassword := jsonutils.QueryBoolean(data, "reset_password", true)
passwd, _ := data.GetString("password")
if resetPassword && len(passwd) > 0 {
if ! seclib2.MeetComplxity(passwd) {
return nil, httperrors.NewWeakPasswordError()
}
}
disk0Json, _ := data.Get("disk.0")
if disk0Json == nil {
return nil, httperrors.NewInputParameterError("No disk information provided")
@@ -2411,41 +2423,81 @@ func (self *SGuest) PerformPurge(ctx context.Context, userCred mcclient.TokenCre
return nil, err
}
func (self *SGuest) setKeypairId(userCred mcclient.TokenCredential, keypairId string) error {
diff, err := self.GetModelManager().TableSpec().Update(self, func() error {
self.KeypairId = keypairId
return nil
})
if err != nil {
db.OpsLog.LogEvent(self, db.ACT_UPDATE, diff, userCred)
}
return err
}
func (self *SGuest) AllowPerformRebuildRoot(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return self.IsOwner(userCred)
}
func (self *SGuest) PerformRebuildRoot(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
imageId, _ := data.GetString("image_id")
if utils.IsInStringArray(self.Status, []string{VM_READY, VM_RUNNING, VM_ADMIN}) {
if !data.Contains("image_id") {
gdc := self.CategorizeDisks()
imageId = gdc.Root.GetTemplateId()
if len(imageId) == 0 {
return nil, httperrors.NewBadRequestError("No template for root disk")
}
img, err := CachedimageManager.getImageInfo(ctx, userCred, imageId, false)
if err != nil {
return nil, httperrors.NewBadRequestError("Template %s not accessible: %s", imageId, err.Error())
}
osType, _ := img.Properties["os_type"]
osName := self.GetMetadata("os_name", userCred)
if len(osName) == 0 && len(osType) == 0 && strings.ToLower(osType) != strings.ToLower(osName) {
return nil, httperrors.NewBadRequestError("Cannot switch OS between %s-%s", osName, osType)
}
}
autoStart := jsonutils.QueryBoolean(data, "auto_start", false)
var needStop = false
if self.Status == VM_RUNNING {
needStop = true
}
err := self.StartRebuildRootTask(ctx, userCred, imageId, needStop, autoStart)
return nil, err
if ! utils.IsInStringArray(self.Status, []string{VM_READY, VM_RUNNING, VM_ADMIN}) {
return nil, httperrors.NewInvalidStatusError("Cannot reset root in status %s", self.Status)
}
return nil, httperrors.NewInvalidStatusError("Cannot reset root in status %s", self.Status)
if !data.Contains("image_id") {
gdc := self.CategorizeDisks()
imageId = gdc.Root.GetTemplateId()
if len(imageId) == 0 {
return nil, httperrors.NewBadRequestError("No template for root disk")
}
img, err := CachedimageManager.getImageInfo(ctx, userCred, imageId, false)
if err != nil {
return nil, httperrors.NewBadRequestError("Template %s not accessible: %s", imageId, err.Error())
}
osType, _ := img.Properties["os_type"]
osName := self.GetMetadata("os_name", userCred)
if len(osName) == 0 && len(osType) == 0 && strings.ToLower(osType) != strings.ToLower(osName) {
return nil, httperrors.NewBadRequestError("Cannot switch OS between %s-%s", osName, osType)
}
}
autoStart := jsonutils.QueryBoolean(data, "auto_start", false)
var needStop = false
if self.Status == VM_RUNNING {
needStop = true
}
resetPasswd := jsonutils.QueryBoolean(data, "reset_password", true)
passwd, _ := data.GetString("password")
if len(passwd) > 0 {
if ! seclib2.MeetComplxity(passwd) {
return nil, httperrors.NewWeakPasswordError()
}
}
keypairStr := jsonutils.GetAnyString(data, []string{"keypair", "keypair_id"})
if len(keypairStr) > 0 {
keypairObj, err := KeypairManager.FetchByIdOrName(userCred.GetUserId(), keypairStr)
if err != nil {
if err == sql.ErrNoRows {
return nil, httperrors.NewResourceNotFoundError("keypair %s not found", keypairStr)
} else {
return nil, httperrors.NewGeneralError(err)
}
}
if self.KeypairId != keypairObj.GetId() {
err = self.setKeypairId(userCred, keypairObj.GetId())
if err != nil {
return nil, httperrors.NewGeneralError(err)
}
}
}
err := self.StartRebuildRootTask(ctx, userCred, imageId, needStop, autoStart, passwd, resetPasswd)
return nil, err
}
func (self *SGuest) StartRebuildRootTask(ctx context.Context, userCred mcclient.TokenCredential, imageId string, needStop, autoStart bool) error {
func (self *SGuest) StartRebuildRootTask(ctx context.Context, userCred mcclient.TokenCredential, imageId string, needStop, autoStart bool, passwd string, resetPasswd bool) error {
data := jsonutils.NewDict()
data.Set("image_id", jsonutils.NewString(imageId))
if needStop {
@@ -2454,6 +2506,14 @@ func (self *SGuest) StartRebuildRootTask(ctx context.Context, userCred mcclient.
if autoStart {
data.Set("auto_start", jsonutils.JSONTrue)
}
if resetPasswd {
data.Set("reset_password", jsonutils.JSONTrue)
} else {
data.Set("reset_password", jsonutils.JSONFalse)
}
if len(passwd) > 0 {
data.Set("password", jsonutils.NewString(passwd))
}
if self.GetHypervisor() == HYPERVISOR_BAREMETAL {
task, err := taskman.TaskManager.NewTask(ctx, "BaremetalServerRebuildRootTask", self, userCred, data, "", "", nil)
if err != nil {
@@ -2875,12 +2935,12 @@ func (self *SGuest) PerformChangeConfig(ctx context.Context, userCred mcclient.T
}
provider, e := self.GetHost().GetDriver()
if e != nil {
/*if e != nil {
log.Errorf("Get Provider Error: %s", e)
return nil, httperrors.NewInsufficientResourceError("Provider Not Found")
}
}*/
if !provider.IsPublicCloud() {
if e != nil || !provider.IsPublicCloud() {
for storageId, needSize := range diskSizes {
iStorage, err := StorageManager.FetchById(storageId)
if err != nil {
@@ -2904,6 +2964,9 @@ func (self *SGuest) PerformChangeConfig(ctx context.Context, userCred mcclient.T
if jsonutils.QueryBoolean(data, "auto_start", false) {
confs.Add(jsonutils.NewBool(true), "auto_start")
}
log.Debugf("%s", confs.String())
pendingUsage := &SQuota{}
if addCpu > 0 {
pendingUsage.Cpu = addCpu
@@ -3140,17 +3203,23 @@ func (self *SGuest) GetDeployConfigOnHost(ctx context.Context, host *SHost, para
deployAction = "deploy"
}
resetPasswd := true
if deployAction == "deploy" {
resetPasswd = jsonutils.QueryBoolean(params, "reset_password", false)
}
// resetPasswd := true
// if deployAction == "deploy" {
resetPasswd := jsonutils.QueryBoolean(params, "reset_password", true)
//}
if resetPasswd {
config.Add(jsonutils.JSONTrue, "reset_password")
passwd, _ := params.GetString("password")
if len(passwd) > 0 {
config.Add(jsonutils.NewString(passwd), "password")
}
keypair := self.getKeypair()
if keypair != nil {
config.Add(jsonutils.NewString(keypair.PublicKey), "public_key")
}
} else {
config.Add(jsonutils.JSONFalse, "reset_password")
}
config.Add(jsonutils.NewString(deployAction), "action")
@@ -3939,7 +4008,7 @@ func (manager *SGuestManager) GetIpInProjectWithName(projectId, name string, isE
sqlchemy.IsFalse(guests.Field("pending_deleted"))),
sqlchemy.IsFalse(guests.Field("deleted")))).
Join(networks, sqlchemy.AND(sqlchemy.Equals(networks.Field("id"), guestnics.Field("network_id")),
sqlchemy.IsFalse(networks.Field("deleted")))).
sqlchemy.IsFalse(networks.Field("deleted")))).
Filter(sqlchemy.Equals(guests.Field("name"), name)).
Filter(sqlchemy.NotEquals(guestnics.Field("ip_addr"), "")).
Filter(sqlchemy.IsNotNull(guestnics.Field("ip_addr"))).
@@ -4138,7 +4207,7 @@ func (self *SGuest) PerformAssociateEip(ctx context.Context, userCred mcclient.T
return nil, httperrors.NewUnsupportOperationError("fixed eip cannot be associated")
}
eipVm := eip.getVM()
eipVm := eip.GetAssociateVM()
if eipVm != nil {
return nil, httperrors.NewConflictError("eip has been associated")
}
@@ -4156,6 +4225,8 @@ func (self *SGuest) PerformAssociateEip(ctx context.Context, userCred mcclient.T
return nil, httperrors.NewInputParameterError("cannot associate eip and instance in different provider")
}
self.SetStatus(userCred, VM_ASSOCIATE_EIP, "associate eip")
params := jsonutils.NewDict()
params.Add(jsonutils.NewString(self.ExternalId), "instance_external_id")
params.Add(jsonutils.NewString(self.Id), "instance_id")
@@ -4179,6 +4250,9 @@ func (self *SGuest) PerformDissociateEip(ctx context.Context, userCred mcclient.
if eip == nil {
return nil, httperrors.NewInvalidStatusError("No eip to dissociate")
}
self.SetStatus(userCred, VM_DISSOCIATE_EIP, "associate eip")
err = eip.StartEipDissociateTask(ctx, userCred, "")
if err != nil {
log.Errorf("fail to start dissociate task %s", err)
+52
View File
@@ -734,6 +734,30 @@ func isExitNetworkInfo(netConfig *SNetworkConfig) bool {
return false
}
func (self *SNetwork) getZone() *SZone {
wire := self.GetWire()
if wire != nil {
return wire.GetZone()
}
return nil
}
func (self *SNetwork) getVpc() *SVpc {
wire := self.GetWire()
if wire != nil {
return wire.getVpc()
}
return nil
}
func (self *SNetwork) getRegion() *SCloudregion {
wire := self.GetWire()
if wire != nil {
return wire.getRegion()
}
return nil
}
func (self *SNetwork) getMoreDetails(extra *jsonutils.JSONDict) *jsonutils.JSONDict {
wire := self.GetWire()
extra.Add(jsonutils.NewString(wire.Name), "wire")
@@ -747,6 +771,34 @@ func (self *SNetwork) getMoreDetails(extra *jsonutils.JSONDict) *jsonutils.JSOND
extra.Add(jsonutils.NewInt(int64(self.GetBaremetalNicsCount())), "bm_vnics")
extra.Add(jsonutils.NewInt(int64(self.GetGroupNicsCount())), "group_vnics")
extra.Add(jsonutils.NewInt(int64(self.GetReservedNicsCount())), "reserve_vnics")
zone := self.getZone()
if zone != nil {
extra.Add(jsonutils.NewString(zone.GetId()), "zone_id")
extra.Add(jsonutils.NewString(zone.GetName()), "zone")
if len(zone.GetExternalId()) > 0 {
extra.Add(jsonutils.NewString(zone.GetExternalId()), "zone_external_id")
}
}
region := self.getRegion()
if region != nil {
extra.Add(jsonutils.NewString(region.GetId()), "region_id")
extra.Add(jsonutils.NewString(region.GetName()), "region")
if len(region.GetExternalId()) > 0 {
extra.Add(jsonutils.NewString(region.GetExternalId()), "region_external_id")
}
}
vpc := self.getVpc()
if vpc != nil {
extra.Add(jsonutils.NewString(vpc.GetId()), "vpc_id")
extra.Add(jsonutils.NewString(vpc.GetName()), "vpc")
if len(vpc.GetExternalId()) > 0 {
extra.Add(jsonutils.NewString(vpc.GetExternalId()), "vpc_external_id")
}
}
return extra
}
+6 -1
View File
@@ -124,7 +124,12 @@ func (self *SVpc) getMoreDetails(extra *jsonutils.JSONDict) *jsonutils.JSONDict
extra.Add(jsonutils.NewInt(int64(self.GetWireCount())), "wire_count")
extra.Add(jsonutils.NewInt(int64(self.GetNetworkCount())), "network_count")
region := self.GetRegion()
extra.Add(jsonutils.NewString(region.GetName()), "region")
if region != nil {
extra.Add(jsonutils.NewString(region.GetName()), "region")
if len(region.GetExternalId()) > 0 {
extra.Add(jsonutils.NewString(region.GetExternalId()), "region_external_id")
}
}
return extra
}
+45
View File
@@ -561,3 +561,48 @@ func (manager *SWireManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQu
return q, err
}
func (self *SWire) getRegion() *SCloudregion {
zone := self.GetZone()
if zone != nil {
return zone.GetRegion()
}
return nil
}
func (self *SWire) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict {
extra := self.SStandaloneResourceBase.GetCustomizeColumns(ctx, userCred, query)
return self.getMoreDetails(extra)
}
func (self *SWire) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict {
extra := self.SStandaloneResourceBase.GetExtraDetails(ctx, userCred, query)
return self.getMoreDetails(extra)
}
func (self *SWire) getMoreDetails(extra *jsonutils.JSONDict) *jsonutils.JSONDict {
extra.Add(jsonutils.NewInt(int64(self.NetworkCount())), "networks")
zone := self.GetZone()
if zone != nil {
extra.Add(jsonutils.NewString(zone.GetName()), "zone")
if len(zone.GetExternalId()) > 0 {
extra.Add(jsonutils.NewString(zone.GetExternalId()), "zone_external_id")
}
}
region := self.getRegion()
if region != nil {
extra.Add(jsonutils.NewString(region.GetId()), "region_id")
extra.Add(jsonutils.NewString(region.GetName()), "region")
if len(region.GetExternalId()) > 0 {
extra.Add(jsonutils.NewString(region.GetExternalId()), "region_external_id")
}
}
vpc := self.getVpc()
if vpc != nil {
extra.Add(jsonutils.NewString(vpc.GetName()), "vpc")
if len(vpc.GetExternalId()) > 0 {
extra.Add(jsonutils.NewString(vpc.GetExternalId()), "vpc_external_id")
}
}
return extra
}
+7
View File
@@ -32,6 +32,11 @@ func (self *EipAssociateTask) OnInit(ctx context.Context, obj db.IStandaloneMode
instanceId, _ := self.Params.GetString("instance_id")
server := models.GuestManager.FetchGuestById(instanceId)
if server.Status != models.VM_ASSOCIATE_EIP {
server.SetStatus(self.UserCred, models.VM_ASSOCIATE_EIP, "associate eip")
}
if server == nil {
msg := fmt.Sprintf("fail to find server for instanceId %s", instanceId)
eip.SetStatus(self.UserCred, models.EIP_STATUS_ASSOCIATE_FAIL, msg)
@@ -57,5 +62,7 @@ func (self *EipAssociateTask) OnInit(ctx context.Context, obj db.IStandaloneMode
eip.SetStatus(self.UserCred, models.EIP_STATUS_READY, "associate")
server.StartSyncstatus(ctx, self.UserCred, "")
self.SetStageComplete(ctx, nil)
}
+29 -19
View File
@@ -23,33 +23,43 @@ func init() {
func (self *EipDissociateTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
eip := obj.(*models.SElasticip)
extEip, err := eip.GetIEip()
if err != nil {
msg := fmt.Sprintf("fail to find iEIP for eip %s", err)
eip.SetStatus(self.UserCred, models.EIP_STATUS_DISSOCIATE_FAIL, msg)
self.SetStageFailed(ctx, msg)
return
}
server := eip.GetAssociateVM()
if server != nil {
if len(extEip.GetAssociationExternalId()) > 0 {
err = extEip.Dissociate()
if server.Status != models.VM_DISSOCIATE_EIP {
server.SetStatus(self.UserCred, models.VM_DISSOCIATE_EIP, "dissociate eip")
}
extEip, err := eip.GetIEip()
if err != nil {
msg := fmt.Sprintf("fail to remote dissociate eip %s", err)
msg := fmt.Sprintf("fail to find iEIP for eip %s", err)
eip.SetStatus(self.UserCred, models.EIP_STATUS_DISSOCIATE_FAIL, msg)
self.SetStageFailed(ctx, msg)
return
}
}
err = eip.Dissociate(ctx, self.UserCred)
if err != nil {
msg := fmt.Sprintf("fail to local dissociate eip %s", err)
eip.SetStatus(self.UserCred, models.EIP_STATUS_DISSOCIATE_FAIL, msg)
self.SetStageFailed(ctx, msg)
return
}
if len(extEip.GetAssociationExternalId()) > 0 {
err = extEip.Dissociate()
if err != nil {
msg := fmt.Sprintf("fail to remote dissociate eip %s", err)
eip.SetStatus(self.UserCred, models.EIP_STATUS_DISSOCIATE_FAIL, msg)
self.SetStageFailed(ctx, msg)
return
}
}
eip.SetStatus(self.UserCred, models.EIP_STATUS_READY, "dissociate")
err = eip.Dissociate(ctx, self.UserCred)
if err != nil {
msg := fmt.Sprintf("fail to local dissociate eip %s", err)
eip.SetStatus(self.UserCred, models.EIP_STATUS_DISSOCIATE_FAIL, msg)
self.SetStageFailed(ctx, msg)
return
}
eip.SetStatus(self.UserCred, models.EIP_STATUS_READY, "dissociate")
server.StartSyncstatus(ctx, self.UserCred, "")
}
self.SetStageComplete(ctx, nil)
+11 -3
View File
@@ -139,9 +139,17 @@ func (self *KVMGuestRebuildRootTask) OnRebuildRootDiskComplete(ctx context.Conte
self.SetStage("OnGuestDeployComplete", nil)
guest.SetStatus(self.UserCred, models.VM_DEPLOYING, "")
params := jsonutils.NewDict()
params.Set("reset_password", jsonutils.JSONTrue)
guest.StartGuestDeployTask(ctx, self.UserCred, params, "deploy", self.GetTaskId())
// 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())
}
func (self *KVMGuestRebuildRootTask) OnRebuildRootDiskCompleteFailed(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
+5
View File
@@ -100,6 +100,11 @@ func NewInputParameterError(msg string, params ...interface{}) *httputils.JSONCl
return NewJsonClientError(400, "InputParameterError", msg, err)
}
func NewWeakPasswordError() *httputils.JSONClientError {
msg, err := errorMessage("password must be 12 chars of at least one digit, letter, uppercase letter and punctuate", nil)
return NewJsonClientError(400, "WeakPasswordError", msg, err)
}
func NewInsufficientResourceError(msg string, params ...interface{}) *httputils.JSONClientError {
msg, err := errorMessage(msg, params)
return NewJsonClientError(400, "InsufficientResourceError", msg, err)
+7 -6
View File
@@ -98,7 +98,7 @@ type ServerCreateOptions struct {
Bios string `help:"BIOS" choices:"BIOS|UEFI"`
Desc string `help:"Description" metavar:"<DESCRIPTION>" json:"description"`
Boot string `help:"Boot device" metavar:"<BOOT_DEVICE>" choices:"disk|cdrom" json:"-"`
NoAccountInit *bool `help:"Not reset account password" json:"reset_password"`
NoAccountInit *bool `help:"Not reset account password"`
AllowDelete *bool `help:"Unlock server to allow deleting" json:"-"`
ShutdownBehavior string `help:"Behavior after VM server shutdown, stop or terminate server" metavar:"<SHUTDOWN_BEHAVIOR>" choices:"stop|terminate"`
AutoStart *bool `help:"Auto start server after it is created"`
@@ -264,11 +264,12 @@ type ServerSaveImageOptions struct {
}
type ServerRebuildRootOptions struct {
ID string `help:"Server to rebuild root" json:"-"`
Image string `help:"New root Image template ID" json:"image_id"`
Keypair string `help:"ssh Keypair used for login"`
Password string `help:"Default user password"`
AutoStart *bool `help:"Auto start server after it is created"`
ID string `help:"Server to rebuild root" json:"-"`
Image string `help:"New root Image template ID" json:"image_id"`
Keypair string `help:"ssh Keypair used for login"`
Password string `help:"Default user password"`
NoAccountInit *bool `help:"Not reset account password"`
AutoStart *bool `help:"Auto start server after it is created"`
}
type ServerChangeConfigOptions struct {
+8 -1
View File
@@ -88,10 +88,17 @@ func (self *SStoragecache) GetIImages() ([]cloudprovider.ICloudImage, error) {
func (self *SStoragecache) UploadImage(userCred mcclient.TokenCredential, imageId string, osArch, osType, osDist string, extId string, isForce bool) (string, error) {
if len(extId) > 0 {
status, _ := self.region.GetImageStatus(extId)
log.Debugf("UploadImage: Image external ID exists %s", extId)
status, err := self.region.GetImageStatus(extId)
if err != nil {
log.Errorf("GetImageStatus error %s", err)
}
if status == ImageStatusAvailable && !isForce {
return extId, nil
}
} else {
log.Debugf("UploadImage: no external ID")
}
return self.uploadImage(userCred, imageId, osArch, osType, osDist, isForce)
+18 -1
View File
@@ -16,7 +16,7 @@ const (
ALL_DIGITS = "0123456789"
ALL_LETTERS = "abcdefghijklmnopqrstuvwxyz"
ALL_UPPERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
ALL_PUNC = PUNC
ALL_PUNC = "~`!@#$%^&*()-_=+[]{}|:':\",./<>?"
)
type PasswordStrength struct {
@@ -72,3 +72,20 @@ func AnalyzePasswordStrenth(passwd string) PasswordStrength {
}
return ps
}
func (ps PasswordStrength) Len() int {
return ps.Punctuats + ps.Uppercases + ps.Lowercases + ps.Digits
}
func (ps PasswordStrength) MeetComplexity() bool {
if ps.Punctuats > 0 && ps.Digits > 0 && ps.Lowercases > 0 && ps.Uppercases > 0 && ps.Len() >= 12 {
return true
} else {
return false
}
}
func MeetComplxity(passwd string) bool {
ps := AnalyzePasswordStrenth(passwd)
return ps.MeetComplexity()
}
+15
View File
@@ -10,3 +10,18 @@ func TestRandomPassword2(t *testing.T) {
rand.Seed(time.Now().Unix())
t.Logf("%s", RandomPassword2(12))
}
func TestMeetComplxity(t *testing.T) {
cases := [] struct {
in string
want bool
} {
{"123456", false},
{"123abcABC!@#", true},
}
for _, c := range cases {
if c.want != MeetComplxity(c.in) {
t.Errorf("%s != %v", c.in, c.want)
}
}
}