Merge branch 'release/2.4.0' of ssh://git.yunion.io/~qiujian/onecloud into feature/qj-vm-resource-pooling

This commit is contained in:
Qiu Jian
2018-12-05 18:09:11 +08:00
44 changed files with 621 additions and 187 deletions
+21 -4
View File
@@ -301,6 +301,19 @@ func init() {
return nil
})
R(&options.ServerSecGroupOptions{}, "server-add-secgroup", "Add security group to a VM", func(s *mcclient.ClientSession, opts *options.ServerSecGroupOptions) error {
params, err := options.StructToParams(opts)
if err != nil {
return err
}
srv, err := modules.Servers.PerformAction(s, opts.ID, "add-secgroup", params)
if err != nil {
return err
}
printObject(srv)
return nil
})
R(&options.ServerSecGroupOptions{}, "server-assign-secgroup", "Assign security group to a VM", func(s *mcclient.ClientSession, opts *options.ServerSecGroupOptions) error {
params, err := options.StructToParams(opts)
if err != nil {
@@ -327,10 +340,14 @@ func init() {
return nil
})
R(&options.ServerIdOptions{}, "server-revoke-secgroup", "Assign security group to a VM", func(s *mcclient.ClientSession, opts *options.ServerIdOptions) error {
srv, e := modules.Servers.PerformAction(s, opts.ID, "revoke-secgroup", nil)
if e != nil {
return e
R(&options.ServerSecGroupOptions{}, "server-revoke-secgroup", "Revoke security group from VM", func(s *mcclient.ClientSession, opts *options.ServerSecGroupOptions) error {
params, err := options.StructToParams(opts)
if err != nil {
return err
}
srv, err := modules.Servers.PerformAction(s, opts.ID, "revoke-secgroup", params)
if err != nil {
return err
}
printObject(srv)
return nil
+1 -1
View File
@@ -7,7 +7,7 @@ import (
)
type GeneralUsageOptions struct {
HostType []string `help:"Host types" choices:"hypervisor|baremetal|esxi|xen|kubelet|hyperv"`
HostType []string `help:"Host types" choices:"hypervisor|baremetal|esxi|xen|kubelet|hyperv|aliyun|azure|aws|huawei|qcloud"`
Project string
}
+16 -8
View File
@@ -42,10 +42,11 @@ func (t *Timer2) Next(now time.Time) time.Time {
}
type SCronJob struct {
Name string
job func(ctx context.Context, userCred mcclient.TokenCredential)
Timer ICronTimer
Next time.Time
Name string
job func(ctx context.Context, userCred mcclient.TokenCredential)
Timer ICronTimer
Next time.Time
StartRun bool
}
type CronJobTimerHeap []*SCronJob
@@ -107,7 +108,7 @@ func (self *SCronJobManager) AddJob1(name string, interval time.Duration, jobFun
}
}
func (self *SCronJobManager) AddJob2(name string, day, hour, min, sec int, jobFunc func(ctx context.Context, userCred mcclient.TokenCredential)) {
func (self *SCronJobManager) AddJob2(name string, day, hour, min, sec int, jobFunc func(ctx context.Context, userCred mcclient.TokenCredential), startRun bool) {
t := Timer2{
day: day,
hour: hour,
@@ -115,9 +116,10 @@ func (self *SCronJobManager) AddJob2(name string, day, hour, min, sec int, jobFu
sec: sec,
}
job := SCronJob{
Name: name,
job: jobFunc,
Timer: &t,
Name: name,
job: jobFunc,
Timer: &t,
StartRun: startRun,
}
if !self.running {
self.jobs = append(self.jobs, &job)
@@ -155,6 +157,12 @@ func (self *SCronJobManager) run() {
} else {
timer = time.NewTimer(self.jobs[0].Next.Sub(now))
}
for i := 0; i < len(self.jobs); i += 1 {
if self.jobs[i].StartRun {
self.jobs[i].StartRun = false
self.jobs[i].runJob()
}
}
select {
case now = <-timer.C:
for i, job := range self.jobs {
+1
View File
@@ -187,6 +187,7 @@ type ICloudVM interface {
GetInstanceType() string
AssignSecurityGroup(secgroupId string) error
AssignSecurityGroups(secgroupIds []string) error
GetHypervisor() string
+4
View File
@@ -52,6 +52,10 @@ func (self *SAzureGuestDriver) ChooseHostStorage(host *models.SHost, backend str
return nil
}
func (self *SAzureGuestDriver) GetMaxSecurityGroupCount() int {
return 1
}
func (self *SAzureGuestDriver) GetDetachDiskStatus() ([]string, error) {
return []string{models.VM_READY, models.VM_RUNNING}, nil
}
+5
View File
@@ -34,6 +34,11 @@ func (self *SBaremetalGuestDriver) GetHypervisor() string {
return models.HYPERVISOR_BAREMETAL
}
func (self *SBaremetalGuestDriver) GetMaxSecurityGroupCount() int {
//暂不支持绑定安全组
return 0
}
func (self *SBaremetalGuestDriver) GetMaxVCpuCount() int {
return 1024
}
+4
View File
@@ -197,6 +197,10 @@ func (self *SBaseGuestDriver) RequestSyncToBackup(ctx context.Context, guest *mo
return fmt.Errorf("Not Implement")
}
func (self *SBaseGuestDriver) GetMaxSecurityGroupCount() int {
return 5
}
func (self *SBaseGuestDriver) getTaskRequestHeader(task taskman.ITask) http.Header {
return task.GetTaskRequestHeader()
}
+5
View File
@@ -33,6 +33,11 @@ func (self *SESXiGuestDriver) RequestSyncConfigOnHost(ctx context.Context, guest
return nil
}
func (self *SESXiGuestDriver) GetMaxSecurityGroupCount() int {
//暂不支持绑定安全组
return 0
}
func (self *SESXiGuestDriver) GetDetachDiskStatus() ([]string, error) {
return []string{models.VM_READY}, nil
}
+18 -14
View File
@@ -460,22 +460,26 @@ func (self *SManagedVirtualizedGuestDriver) RequestSyncConfigOnHost(ctx context.
if err != nil {
return nil, err
}
secgroups := guest.GetSecgroups()
externalIds := []string{}
for _, secgroup := range secgroups {
lockman.LockRawObject(ctx, "secgroupcache", fmt.Sprintf("%s-%s", guest.SecgrpId, vpcId))
defer lockman.ReleaseRawObject(ctx, "secgroupcache", fmt.Sprintf("%s-%s", guest.SecgrpId, vpcId))
lockman.LockRawObject(ctx, "secgroupcache", fmt.Sprintf("%s-%s", guest.SecgrpId, vpcId))
defer lockman.ReleaseRawObject(ctx, "secgroupcache", fmt.Sprintf("%s-%s", guest.SecgrpId, vpcId))
secgroupCache := models.SecurityGroupCacheManager.Register(ctx, task.GetUserCred(), guest.SecgrpId, vpcId, host.GetRegion().Id, host.ManagerId)
if secgroupCache == nil {
return nil, fmt.Errorf("failed to registor secgroupCache for secgroup: %s vpc: %s", guest.SecgrpId, vpcId)
secgroupCache := models.SecurityGroupCacheManager.Register(ctx, task.GetUserCred(), secgroup.Id, vpcId, host.GetRegion().Id, host.ManagerId)
if secgroupCache == nil {
return nil, fmt.Errorf("failed to registor secgroupCache for secgroup: %s vpc: %s", secgroup.Id, vpcId)
}
extID, err := iregion.SyncSecurityGroup(secgroupCache.ExternalId, vpcId, secgroup.Name, secgroup.Description, secgroup.GetSecRules(""))
if err != nil {
return nil, err
}
if err = secgroupCache.SetExternalId(extID); err != nil {
return nil, err
}
externalIds = append(externalIds, extID)
}
extID, err := iregion.SyncSecurityGroup(secgroupCache.ExternalId, vpcId, guest.GetSecgroupName(), "", guest.GetSecRules())
if err != nil {
return nil, err
}
if err = secgroupCache.SetExternalId(extID); err != nil {
return nil, err
}
return nil, iVM.AssignSecurityGroup(extID)
return nil, iVM.AssignSecurityGroups(externalIds)
}
iDisks, err := iVM.GetIDisks()
+22 -13
View File
@@ -75,6 +75,9 @@ func (self *SQcloudGuestDriver) ValidateResizeDisk(guest *models.SGuest, disk *m
if !utils.IsInStringArray(guest.Status, []string{models.VM_READY, models.VM_RUNNING}) {
return fmt.Errorf("Cannot resize disk when guest in status %s", guest.Status)
}
if disk.DiskType == models.DISK_TYPE_SYS {
return fmt.Errorf("Cannot resize system disk")
}
if utils.IsInStringArray(storage.StorageType, []string{models.STORAGE_LOCAL_BASIC, models.STORAGE_LOCAL_SSD}) {
return fmt.Errorf("Cannot resize %s disk", storage.StorageType)
}
@@ -312,21 +315,27 @@ func (self *SQcloudGuestDriver) RequestSyncConfigOnHost(ctx context.Context, gue
if err != nil {
return nil, err
}
lockman.LockRawObject(ctx, "secgroupcache", fmt.Sprintf("%s-normal", guest.SecgrpId))
defer lockman.ReleaseRawObject(ctx, "secgroupcache", fmt.Sprintf("%s-normal", guest.SecgrpId))
secgroups := guest.GetSecgroups()
externalIds := []string{}
for _, secgroup := range secgroups {
secgroupCache := models.SecurityGroupCacheManager.Register(ctx, task.GetUserCred(), guest.SecgrpId, "normal", host.GetRegion().Id, host.ManagerId)
if secgroupCache == nil {
return nil, fmt.Errorf("failed to registor secgroupCache for secgroup: %s", guest.SecgrpId)
lockman.LockRawObject(ctx, "secgroupcache", fmt.Sprintf("%s-normal", guest.SecgrpId))
defer lockman.ReleaseRawObject(ctx, "secgroupcache", fmt.Sprintf("%s-normal", guest.SecgrpId))
secgroupCache := models.SecurityGroupCacheManager.Register(ctx, task.GetUserCred(), secgroup.Id, "normal", host.GetRegion().Id, host.ManagerId)
if secgroupCache == nil {
return nil, fmt.Errorf("failed to registor secgroupCache for secgroup: %s", secgroup.Id)
}
extID, err := iregion.SyncSecurityGroup(secgroupCache.ExternalId, "", secgroup.Name, secgroup.Description, secgroup.GetSecRules(""))
if err != nil {
return nil, err
}
if err = secgroupCache.SetExternalId(extID); err != nil {
return nil, err
}
externalIds = append(externalIds, extID)
}
extID, err := iregion.SyncSecurityGroup(secgroupCache.ExternalId, "normal", guest.GetSecgroupName(), "", guest.GetSecRules())
if err != nil {
return nil, err
}
if err = secgroupCache.SetExternalId(extID); err != nil {
return nil, err
}
return nil, iVM.AssignSecurityGroup(extID)
return nil, iVM.AssignSecurityGroups(externalIds)
}
iDisks, err := iVM.GetIDisks()
+1
View File
@@ -92,6 +92,7 @@ func InitHandlers(app *appsrv.Application) {
models.HoststorageManager,
models.HostschedtagManager,
models.GuestnetworkManager,
models.GuestsecgroupManager,
models.LoadbalancernetworkManager,
models.GuestdiskManager,
models.GroupnetworkManager,
+91 -35
View File
@@ -14,6 +14,7 @@ import (
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
"yunion.io/x/onecloud/pkg/compute/options"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
@@ -633,6 +634,37 @@ func (self *SGuest) StartDeleteGuestTask(ctx context.Context, userCred mcclient.
return self.GetDriver().StartDeleteGuestTask(ctx, userCred, self, params, parentTaskId)
}
func (self *SGuest) AllowPerformAddSecgroup(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return self.IsOwner(userCred)
}
func (self *SGuest) PerformAddSecgroup(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if !utils.IsInStringArray(self.Status, []string{VM_READY, VM_RUNNING, VM_SUSPEND}) {
return nil, httperrors.NewInputParameterError("Cannot assign security rules in status %s", self.Status)
}
secgrpV := validators.NewModelIdOrNameValidator("secgrp", "secgroup", userCred.GetProjectId())
if err := secgrpV.Validate(data.(*jsonutils.JSONDict)); err != nil {
return nil, err
}
maxCount := self.GetDriver().GetMaxSecurityGroupCount()
if maxCount == 0 {
return nil, httperrors.NewUnsupportOperationError("Cannot assign security group for this guest %s", self.Name)
}
secgroups := self.GetSecgroups()
if len(secgroups) >= maxCount {
return nil, httperrors.NewUnsupportOperationError("guest %s band to up to %d security groups", self.Name, maxCount)
}
secgroup := secgrpV.Model.(*SSecurityGroup)
if _, err := GuestsecgroupManager.newGuestSecgroup(ctx, userCred, self, secgroup); err != nil {
return nil, httperrors.NewInputParameterError(err.Error())
}
return nil, self.StartSyncTask(ctx, userCred, true, "")
}
func (self *SGuest) AllowPerformAssignSecgroup(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "assign-secgroup")
}
@@ -641,51 +673,75 @@ func (self *SGuest) AllowPerformRevokeSecgroup(ctx context.Context, userCred mcc
return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "revoke-secgroup")
}
func (self *SGuest) revokeSecgroup(ctx context.Context, userCred mcclient.TokenCredential, secgroup *SSecurityGroup) error {
if secgroup == nil {
return fmt.Errorf("failed to revoke null secgroup")
}
if self.SecgrpId != secgroup.Id {
return GuestsecgroupManager.DeleteGuestSecgroup(ctx, userCred, self, secgroup)
}
secgroups := self.GetSecgroups()
if len(secgroups) == 1 {
_, err := self.GetModelManager().TableSpec().Update(self, func() error {
self.SecgrpId = "default"
return nil
})
return err
}
for _, _secgroup := range secgroups {
if _secgroup.Id != secgroup.Id {
err := GuestsecgroupManager.DeleteGuestSecgroup(ctx, userCred, self, &_secgroup)
if err != nil {
return err
}
_, err = self.GetModelManager().TableSpec().Update(self, func() error {
self.SecgrpId = _secgroup.Id
return nil
})
return err
}
}
return nil
}
func (self *SGuest) PerformRevokeSecgroup(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if !utils.IsInStringArray(self.Status, []string{VM_READY, VM_RUNNING, VM_SUSPEND}) {
return nil, httperrors.NewInputParameterError("Cannot revoke security rules in status %s", self.Status)
} else {
if _, err := self.GetModelManager().TableSpec().Update(self, func() error {
self.SecgrpId = "default"
return nil
}); err != nil {
return nil, err
}
if err := self.StartSyncTask(ctx, userCred, true, ""); err != nil {
return nil, err
}
}
return nil, nil
secgrpV := validators.NewModelIdOrNameValidator("secgrp", "secgroup", userCred.GetProjectId())
secgrpV.Optional(true)
if err := secgrpV.Validate(data.(*jsonutils.JSONDict)); err != nil {
return nil, err
}
secgroup, ok := secgrpV.Model.(*SSecurityGroup)
if !ok {
secgroup = self.getSecgroup()
}
if err := self.revokeSecgroup(ctx, userCred, secgroup); err != nil {
return nil, err
}
return nil, self.StartSyncTask(ctx, userCred, true, "")
}
func (self *SGuest) PerformAssignSecgroup(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if !utils.IsInStringArray(self.Status, []string{VM_READY, VM_RUNNING, VM_SUSPEND}) {
logclient.AddActionLog(self, logclient.ACT_VM_ASSIGNSECGROUP, "Cannot assign security rules in status "+self.Status, userCred, false)
return nil, httperrors.NewInputParameterError("Cannot assign security rules in status %s", self.Status)
} else {
if secgrp, err := data.GetString("secgrp"); err != nil {
logclient.AddActionLog(self, logclient.ACT_VM_ASSIGNSECGROUP, err, userCred, false)
return nil, err
} else if sg, err := SecurityGroupManager.FetchByIdOrName(userCred, secgrp); err != nil {
msg := fmt.Sprintf("SecurityGroup %s not found", secgrp)
logclient.AddActionLog(self, logclient.ACT_VM_ASSIGNSECGROUP, msg, userCred, false)
return nil, httperrors.NewNotFoundError("SecurityGroup %s not found", secgrp)
} else {
if _, err := self.GetModelManager().TableSpec().Update(self, func() error {
self.SecgrpId = sg.GetId()
return nil
}); err != nil {
logclient.AddActionLog(self, logclient.ACT_VM_ASSIGNSECGROUP, err, userCred, false)
return nil, err
}
if err := self.StartSyncTask(ctx, userCred, true, ""); err != nil {
logclient.AddActionLog(self, logclient.ACT_VM_ASSIGNSECGROUP, err, userCred, false)
return nil, err
}
}
}
logclient.AddActionLog(self, logclient.ACT_VM_ASSIGNSECGROUP, nil, userCred, true)
return nil, nil
secgrpV := validators.NewModelIdOrNameValidator("secgrp", "secgroup", userCred.GetProjectId())
if err := secgrpV.Validate(data.(*jsonutils.JSONDict)); err != nil {
return nil, err
}
if _, err := self.GetModelManager().TableSpec().Update(self, func() error {
self.SecgrpId = secgrpV.Model.GetId()
return nil
}); err != nil {
return nil, err
}
return nil, self.StartSyncTask(ctx, userCred, true, "")
}
func (self *SGuest) AllowPerformPurge(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
+1
View File
@@ -17,6 +17,7 @@ type IGuestDriver interface {
GetMaxVCpuCount() int
GetMaxVMemSizeGB() int
GetMaxSecurityGroupCount() int
IsSupportedBillingCycle(bc billing.SBillingCycle) bool
+107 -16
View File
@@ -8,6 +8,7 @@ import (
"strconv"
"strings"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/tristate"
@@ -281,7 +282,12 @@ func (manager *SGuestManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQ
if secgrp == nil {
return nil, httperrors.NewResourceNotFoundError("secgroup %s not found", secgrpFilter)
}
q = q.Equals("secgrp_id", secgrp.GetId())
q = q.Filter(
sqlchemy.OR(
sqlchemy.In(q.Field("id"), GuestsecgroupManager.Query("guest_id").Equals("secgroup_id", secgrp.GetId()).SubQuery()),
sqlchemy.Equals(q.Field("secgrp_id"), secgrp.GetId()),
),
)
}
zoneFilter, _ := queryDict.GetString("zone")
@@ -1052,6 +1058,10 @@ func (self *SGuest) GetCustomizeColumns(ctx context.Context, userCred mcclient.T
extra.Add(jsonutils.NewString(self.GetSecgroupName()), "secgroup")
if secgroups := self.getSecgroupJson(); len(secgroups) > 0 {
extra.Add(jsonutils.NewArray(secgroups...), "secgroups")
}
if self.PendingDeleted {
pendingDeletedAt := self.PendingDeletedAt.Add(time.Second * time.Duration(options.Options.PendingDeleteExpireSeconds))
extra.Add(jsonutils.NewString(timeutils.FullIsoTime(pendingDeletedAt)), "auto_delete_at")
@@ -1115,6 +1125,11 @@ func (self *SGuest) GetExtraDetails(ctx context.Context, userCred mcclient.Token
// extra.Add(jsonutils.NewString(self.getFlavorName()), "flavor")
extra.Add(jsonutils.NewString(self.getKeypairName()), "keypair")
extra.Add(jsonutils.NewString(self.GetSecgroupName()), "secgroup")
if secgroups := self.getSecgroupJson(); len(secgroups) > 0 {
extra.Add(jsonutils.NewArray(secgroups...), "secgroups")
}
extra.Add(jsonutils.NewString(strings.Join(self.getIPs(), ",")), "ips")
extra.Add(jsonutils.NewString(self.getSecurityRules()), "security_rules")
extra.Add(jsonutils.NewString(self.getIsolatedDeviceDetails()), "isolated_devices")
@@ -1416,6 +1431,30 @@ func (self *SGuest) IsWindows() bool {
}
}
func (self *SGuest) getSecgroupJson() []jsonutils.JSONObject {
secgroups := []jsonutils.JSONObject{}
for _, secGrp := range self.GetSecgroups() {
secgroups = append(secgroups, secGrp.getDesc())
}
return secgroups
}
func (self *SGuest) GetSecgroups() []SSecurityGroup {
secgrpQuery := SecurityGroupManager.Query()
secgrpQuery.Filter(
sqlchemy.OR(
sqlchemy.Equals(secgrpQuery.Field("id"), self.SecgrpId),
sqlchemy.In(secgrpQuery.Field("id"), GuestsecgroupManager.Query("secgroup_id").Equals("guest_id", self.Id).SubQuery()),
),
)
secgroups := []SSecurityGroup{}
if err := db.FetchModelObjects(SecurityGroupManager, secgrpQuery, &secgroups); err != nil {
log.Errorf("Get security group error: %v", err)
return nil
}
return secgroups
}
func (self *SGuest) getSecgroup() *SSecurityGroup {
return SecurityGroupManager.FetchSecgroupById(self.SecgrpId)
}
@@ -1446,7 +1485,7 @@ func (self *SGuest) GetSecRules() []secrules.SecurityRule {
func (self *SGuest) getSecRules() []secrules.SecurityRule {
if secgrp := self.getSecgroup(); secgrp != nil {
return secgrp.getSecRules("")
return secgrp.GetSecRules("")
}
if rule, err := secrules.ParseSecurityRule(options.Options.DefaultSecurityRules); err == nil {
return []secrules.SecurityRule{*rule}
@@ -1465,6 +1504,27 @@ func (self *SGuest) getSecurityRules() string {
}
}
//获取多个安全组规则,优先级降序排序
func (self *SGuest) getSecurityGroupsRules() string {
secgroups := self.GetSecgroups()
secgroupids := []string{}
for _, secgroup := range secgroups {
secgroupids = append(secgroupids, secgroup.Id)
}
q := SecurityGroupRuleManager.Query()
q.Filter(sqlchemy.In(q.Field("secgroup_id"), secgroupids)).Desc(q.Field("priority"))
secrules := []SSecurityGroupRule{}
if err := db.FetchModelObjects(SecurityGroupRuleManager, q, &secrules); err != nil {
log.Errorf("Get rules error: %v", err)
return options.Options.DefaultSecurityRules
}
rules := []string{}
for _, rule := range secrules {
rules = append(rules, rule.String())
}
return strings.Join(rules, SECURITY_GROUP_SEPARATOR)
}
func (self *SGuest) getAdminSecurityRules() string {
secgrp := self.getAdminSecgroup()
if secgrp != nil {
@@ -1539,12 +1599,23 @@ func (self *SGuest) syncWithCloudVM(ctx context.Context, userCred mcclient.Token
self.BillingType = extVM.GetBillingType()
self.ExpiredAt = extVM.GetExpiredAt()
if metaData != nil && metaData.Contains("secgroupId") {
if secgroupId, err := metaData.GetString("secgroupId"); err == nil && len(secgroupId) > 0 {
if secgrp, err := SecurityGroupManager.FetchByExternalId(secgroupId); err == nil && secgrp != nil {
self.SecgrpId = secgrp.GetId()
} else {
log.Errorf("Failed find secgroup %s for guest %s error: %v", secgroupId, self.Name, err)
if metaData != nil && metaData.Contains("secgroupIds") {
secgroupIds := []string{}
if err := metaData.Unmarshal(&secgroupIds, "secgroupIds"); err == nil {
for _, secgroupId := range secgroupIds {
secgrp, err := SecurityGroupManager.FetchByExternalId(secgroupId)
if err != nil {
log.Errorf("Failed find secgroup %s for guest %s error: %v", secgroupId, self.Name, err)
continue
}
secgroup := secgrp.(*SSecurityGroup)
if len(self.SecgrpId) == 0 {
self.SecgrpId = secgroup.Id
} else {
if _, err := GuestsecgroupManager.newGuestSecgroup(ctx, userCred, self, secgroup); err != nil {
log.Errorf("failed to bind secgroup %s for guest %s error: %v", secgroup.Name, self.Name, err)
}
}
}
}
}
@@ -1634,12 +1705,22 @@ func (manager *SGuestManager) newCloudVM(ctx context.Context, userCred mcclient.
guest.ProjectId = projectId
}
if metaData != nil && metaData.Contains("secgroupId") {
if secgroupId, err := metaData.GetString("secgroupId"); err == nil && len(secgroupId) > 0 {
if secgrp, err := SecurityGroupManager.FetchByExternalId(secgroupId); err == nil && secgrp != nil {
guest.SecgrpId = secgrp.GetId()
} else {
log.Errorf("Failed find secgroup %s for guest %s error: %v", secgroupId, guest.Name, err)
extraSecgroups := []*SSecurityGroup{}
if metaData != nil && metaData.Contains("secgroupIds") {
secgroupIds := []string{}
if err := metaData.Unmarshal(&secgroupIds, "secgroupIds"); err == nil {
for _, secgroupId := range secgroupIds {
secgrp, err := SecurityGroupManager.FetchByExternalId(secgroupId)
if err != nil {
log.Errorf("Failed find secgroup %s for guest %s error: %v", secgroupId, guest.Name, err)
continue
}
secgroup := secgrp.(*SSecurityGroup)
if len(guest.SecgrpId) == 0 {
guest.SecgrpId = secgroup.Id
} else {
extraSecgroups = append(extraSecgroups, secgroup)
}
}
}
}
@@ -1650,6 +1731,12 @@ func (manager *SGuestManager) newCloudVM(ctx context.Context, userCred mcclient.
return nil, err
}
for _, secgroup := range extraSecgroups {
if _, err := GuestsecgroupManager.newGuestSecgroup(ctx, userCred, &guest, secgroup); err != nil {
log.Errorf("failed to bind secgroup %s for guest %s error: %v", secgroup.Name, guest.Name, err)
}
}
if metaData != nil {
meta := make(map[string]string, 0)
if err := metaData.Unmarshal(meta); err != nil {
@@ -2653,13 +2740,17 @@ func (self *SGuest) GetJsonDescAtHypervisor(ctx context.Context, host *SHost) *j
desc.Add(jsonutils.NewString(secGrp.Name), "secgroup")
}
if secgroups := self.getSecgroupJson(); len(secgroups) > 0 {
desc.Add(jsonutils.NewArray(secgroups...), "secgroups")
}
/*
TODO
srs := self.getSecurityRuleSet()
if srs.estimatedSinglePortRuleCount() <= options.FirewallFlowCountLimit {
*/
rules := self.getSecurityRules()
rules := self.getSecurityGroupsRules()
if len(rules) > 0 {
desc.Add(jsonutils.NewString(rules), "security_rules")
}
@@ -2773,7 +2864,7 @@ func (self *SGuest) GetJsonDescAtBaremetal(ctx context.Context, host *SHost) *js
desc.Add(jsonutils.NewStringArray(netRoles), "network_roles")
}
rules := self.getSecurityRules()
rules := self.getSecurityGroupsRules()
if len(rules) > 0 {
desc.Add(jsonutils.NewString(rules), "security_rules")
}
+84
View File
@@ -0,0 +1,84 @@
package models
import (
"context"
"fmt"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
"yunion.io/x/onecloud/pkg/mcclient"
)
type SGuestsecgroupManager struct {
SGuestJointsManager
}
var GuestsecgroupManager *SGuestsecgroupManager
func init() {
db.InitManager(func() {
GuestsecgroupManager = &SGuestsecgroupManager{
SGuestJointsManager: NewGuestJointsManager(
SGuestsecgroup{},
"guestsecgroups_tbl",
"guestsecgroup",
"guestsecgroups",
SecurityGroupManager,
),
}
})
}
type SGuestsecgroup struct {
SGuestJointsBase
SecgroupId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required" key_index:"true"` // Column(VARCHAR(36, charset='ascii'), nullable=False)
}
func (self *SGuestsecgroup) getSecgroup() *SSecurityGroup {
secgrp, err := SecurityGroupManager.FetchById(self.SecgroupId)
if err != nil {
log.Errorf("failed to find secgroup %s", self.SecgroupId)
return nil
}
secgroup := secgrp.(*SSecurityGroup)
secgroup.SetModelManager(SecurityGroupManager)
return secgroup
}
func (manager *SGuestsecgroupManager) newGuestSecgroup(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, secgroup *SSecurityGroup) (*SGuestsecgroup, error) {
q := manager.Query()
q = q.Equals("guest_id", guest.Id).Equals("secgroup_id", secgroup.Id)
if count := q.Count(); count > 0 {
return nil, fmt.Errorf("security group %s has already been assigned to guest %s", secgroup.Name, guest.Name)
}
gs := SGuestsecgroup{SecgroupId: secgroup.Id}
gs.SetModelManager(manager)
gs.GuestId = guest.Id
lockman.LockObject(ctx, secgroup)
defer lockman.ReleaseObject(ctx, secgroup)
return &gs, manager.TableSpec().Insert(&gs)
}
func (manager *SGuestsecgroupManager) DeleteGuestSecgroup(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, secgroup *SSecurityGroup) error {
gss := []SGuestsecgroup{}
q := manager.Query()
q = q.Equals("guest_id", guest.Id).Equals("secgroup_id", secgroup.Id)
if err := db.FetchModelObjects(manager, q, &gss); err != nil {
return err
}
for _, gs := range gss {
if err := gs.Delete(ctx, userCred); err != nil {
return err
}
}
return nil
}
func (self *SGuestsecgroup) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
return db.DeleteModel(ctx, userCred, self)
}
+17 -4
View File
@@ -51,8 +51,13 @@ type SSecurityGroup struct {
func (self *SSecurityGroup) GetGuestsQuery() *sqlchemy.SQuery {
guests := GuestManager.Query().SubQuery()
return guests.Query().Filter(sqlchemy.OR(sqlchemy.Equals(guests.Field("secgrp_id"), self.Id),
sqlchemy.Equals(guests.Field("admin_secgrp_id"), self.Id)))
return guests.Query().Filter(
sqlchemy.OR(
sqlchemy.Equals(guests.Field("secgrp_id"), self.Id),
sqlchemy.Equals(guests.Field("admin_secgrp_id"), self.Id),
sqlchemy.In(guests.Field("id"), GuestsecgroupManager.Query("guest_id").Equals("secgroup_id", self.Id).SubQuery()),
),
)
}
func (self *SSecurityGroup) GetGuestsCount() int {
@@ -60,7 +65,7 @@ func (self *SSecurityGroup) GetGuestsCount() int {
}
func (self *SSecurityGroup) GetGuests() []SGuest {
guests := make([]SGuest, 0)
guests := []SGuest{}
q := self.GetGuestsQuery()
err := db.FetchModelObjects(GuestManager, q, &guests)
if err != nil {
@@ -70,6 +75,14 @@ func (self *SSecurityGroup) GetGuests() []SGuest {
return guests
}
func (self *SSecurityGroup) getDesc() jsonutils.JSONObject {
desc := jsonutils.NewDict()
desc.Add(jsonutils.NewString(self.Name), "name")
desc.Add(jsonutils.NewString(self.Id), "id")
desc.Add(jsonutils.NewString(self.getSecurityRuleString("")), "security_rules")
return desc
}
func (self *SSecurityGroup) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict {
extra := self.SSharableVirtualResourceBase.GetExtraDetails(ctx, userCred, query)
extra.Add(jsonutils.NewInt(int64(len(self.GetGuests()))), "guest_cnt")
@@ -121,7 +134,7 @@ func (self *SSecurityGroup) getSecurityRules(direction string) (rules []SSecurit
return
}
func (self *SSecurityGroup) getSecRules(direction string) []secrules.SecurityRule {
func (self *SSecurityGroup) GetSecRules(direction string) []secrules.SecurityRule {
rules := make([]secrules.SecurityRule, 0)
for _, _rule := range self.getSecurityRules(direction) {
//这里没必要拆分为单个单个的端口,到公有云那边适配
+2 -2
View File
@@ -4,10 +4,10 @@ import (
"context"
"database/sql"
"yunion.io/x/sqlchemy"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
+2 -1
View File
@@ -243,10 +243,11 @@ func (self *SStoragecache) StartImageCacheTask(ctx context.Context, userCred mcc
if image != nil {
imgInfo := imagetools.NormalizeImageInfo(image.Name, image.Properties["os_arch"], image.Properties["os_type"],
image.Properties["os_distribution"])
image.Properties["os_distribution"], image.Properties["os_version"])
data.Add(jsonutils.NewString(imgInfo.OsType), "os_type")
data.Add(jsonutils.NewString(imgInfo.OsArch), "os_arch")
data.Add(jsonutils.NewString(imgInfo.OsDistro), "os_distribution")
data.Add(jsonutils.NewString(imgInfo.OsVersion), "os_version")
}
if isForce {
+2 -2
View File
@@ -61,8 +61,8 @@ func StartService() {
cron.AddJob1("CleanPendingDeleteLoadbalancers", time.Duration(options.Options.LoadbalancerPendingDeleteCheckInterval)*time.Second, models.LoadbalancerAgentManager.CleanPendingDeleteLoadbalancers)
cron.AddJob1("CleanPendingDeleteServers", time.Duration(options.Options.PrepaidExpireCheckSeconds)*time.Second, models.GuestManager.DeleteExpiredPrepaidServers)
cron.AddJob2("AutoDiskSnapshot", options.Options.AutoSnapshotDay, options.Options.AutoSnapshotHour, 0, 0, models.DiskManager.AutoDiskSnapshot)
cron.AddJob2("SyncSkus", options.Options.SyncSkusDay, options.Options.SyncSkusHour, 0, 0, skus.SyncSkus)
cron.AddJob2("AutoDiskSnapshot", options.Options.AutoSnapshotDay, options.Options.AutoSnapshotHour, 0, 0, models.DiskManager.AutoDiskSnapshot, false)
cron.AddJob2("SyncSkus", options.Options.SyncSkusDay, options.Options.SyncSkusHour, 0, 0, skus.SyncSkus, true)
cron.Start()
defer cron.Stop()
+53 -19
View File
@@ -103,32 +103,41 @@ func processSkuData(ndata jsonutils.JSONObject) jsonutils.JSONObject {
func (self *SkusZone) Init() error {
s := auth.GetAdminSession(options.Options.Region, "")
p, r, z := self.getExternalZone()
ret, e := modules.CloudmetaSkus.GetSkus(s, p, r, z)
if e != nil {
log.Debugf("SkusZone %s init failed, %s", z, e.Error())
return e
}
limit := 1024
offset := 0
total := 1024
records := map[string]jsonutils.JSONObject{}
for _, sku := range ret.Data {
name, err := sku.GetString("name")
if err != nil {
log.Debugf("SkusZone sku name empty : %s", sku)
return err
for offset < total {
ret, e := modules.CloudmetaSkus.GetSkus(s, p, r, z, limit, offset)
if e != nil {
log.Debugf("SkusZone %s init failed, %s", z, e.Error())
return e
}
if odata, exists := records[name]; exists {
records[name] = mergeSkuData(odata, sku)
} else {
records[name] = processSkuData(sku)
for _, sku := range ret.Data {
name, err := sku.GetString("name")
if err != nil {
log.Debugf("SkusZone sku name empty : %s", sku)
return err
}
if odata, exists := records[name]; exists {
records[name] = mergeSkuData(odata, sku)
} else {
records[name] = processSkuData(sku)
}
}
offset += limit
total = ret.Total
}
filtedData := []jsonutils.JSONObject{}
for _, item := range records {
filtedData = append(filtedData, item)
}
self.total = len(records)
self.skus = filtedData
return nil
@@ -208,6 +217,9 @@ func (self *SkusZone) getExternalZone() (string, string, string) {
if len(parts) == 3 {
// provider, region, zone
return parts[0], parts[1], parts[2]
} else if len(parts) == 2 && parts[0] == models.CLOUD_PROVIDER_AZURE {
// azure 没有zone的概念
return parts[0], parts[1], parts[1]
}
log.Debugf("SkusZone invalid external zone id %s", self.ExternalZoneId)
@@ -235,9 +247,17 @@ func (self *SkusZoneList) initData(provider string, region models.SCloudregion,
}
}
func (self *SkusZoneList) Refresh() error {
provideIds := cloudprovider.GetRegistedProviderIds()
for _, p := range provideIds {
func (self *SkusZoneList) Refresh(providerIds *[]string) error {
self.Data = []*SkusZone{}
var pIds []string
if providerIds == nil {
pIds = cloudprovider.GetRegistedProviderIds()
} else {
pIds = *providerIds
}
for _, p := range pIds {
regions, e := models.CloudregionManager.GetRegionByProvider(p)
if e != nil {
return e
@@ -288,7 +308,7 @@ func (self *SkusZoneList) SyncToLocalDB() error {
func SyncSkus(ctx context.Context, userCred mcclient.TokenCredential) {
skus := SkusZoneList{}
if e := skus.Refresh(); e != nil {
if e := skus.Refresh(nil); e != nil {
log.Errorf("SyncSkus refresh failed, %s", e.Error())
}
@@ -296,3 +316,17 @@ func SyncSkus(ctx context.Context, userCred mcclient.TokenCredential) {
log.Errorf("SyncSkus sync to local db failed, %s", e.Error())
}
}
func SyncSkusByProviderIds(providerIds []string) error {
skus := SkusZoneList{}
log.Debugf("SyncSkusByProviderIds %s", providerIds)
if e := skus.Refresh(&providerIds); e != nil {
return fmt.Errorf("SyncSkus refresh failed, %s", e.Error())
}
if e := skus.SyncToLocalDB(); e != nil {
return fmt.Errorf("SyncSkus sync to local db failed, %s", e.Error())
}
return nil
}
@@ -7,6 +7,7 @@ import (
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/compute/skus"
)
type CloudAccountSyncInfoTask struct {
@@ -82,6 +83,11 @@ func (self *CloudAccountSyncInfoTask) OnCloudaccountSyncComplete(ctx context.Con
if account != nil {
account.SetStatus(self.UserCred, models.CLOUD_PROVIDER_CONNECTED, "")
}
// sync skus
if err := skus.SyncSkusByProviderIds([]string{cloudprovider.Provider}); err != nil {
self.SetStageFailed(ctx, err.Error())
}
}
self.SetStageComplete(ctx, nil)
}
+4 -3
View File
@@ -107,8 +107,9 @@ func (self *DiskResizeTask) OnDiskResizeComplete(ctx context.Context, disk *mode
self.finalReleasePendingUsage(ctx)
}
func (self *DiskResizeTask) OnDiskResizeCompleteFailed(ctx context.Context, disk *models.SDisk, reason jsonutils.JSONObject) {
disk.SetDiskReady(ctx, self.GetUserCred(), reason.String())
func (self *DiskResizeTask) OnDiskResizeCompleteFailed(ctx context.Context, disk *models.SDisk, data jsonutils.JSONObject) {
disk.SetDiskReady(ctx, self.GetUserCred(), data.String())
db.OpsLog.LogEvent(disk, db.ACT_RESIZE_FAIL, disk.GetShortDesc(), self.UserCred)
logclient.AddActionLog(disk, logclient.ACT_RESIZE, reason.String(), self.UserCred, false)
logclient.AddActionLog(disk, logclient.ACT_RESIZE, data.String(), self.UserCred, false)
self.SetStageFailed(ctx, data.String())
}
+1
View File
@@ -66,6 +66,7 @@ func (self *DiskSaveTask) StartBackupDisk(ctx context.Context, disk *models.SDis
func (self *DiskSaveTask) OnDiskBackupCompleteFailed(ctx context.Context, disk *models.SDisk, data jsonutils.JSONObject) {
disk.SetDiskReady(ctx, self.GetUserCred(), data.String())
db.OpsLog.LogEvent(disk, db.ACT_SAVE_FAIL, data.String(), self.GetUserCred())
self.SetStageFailed(ctx, data.String())
}
func (self *DiskSaveTask) OnDiskBackupComplete(ctx context.Context, disk *models.SDisk, data *jsonutils.JSONDict) {
+3 -2
View File
@@ -8,6 +8,7 @@ import (
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/models"
)
@@ -38,13 +39,13 @@ func (self *EipDissociateTask) OnInit(ctx context.Context, obj db.IStandaloneMod
}
extEip, err := eip.GetIEip()
if err != nil {
if err != nil && err != cloudprovider.ErrNotFound {
msg := fmt.Sprintf("fail to find iEIP for eip %s", err)
self.TaskFail(ctx, eip, msg, server)
return
}
if len(extEip.GetAssociationExternalId()) > 0 {
if err == nil && len(extEip.GetAssociationExternalId()) > 0 {
err = extEip.Dissociate()
if err != nil {
msg := fmt.Sprintf("fail to remote dissociate eip %s", err)
+9
View File
@@ -127,16 +127,25 @@ func (self *GuestDeployTask) OnDeployGuestComplete(ctx context.Context, obj db.I
func (self *GuestDeployTask) OnDeployGuestCompleteFailed(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
guest := obj.(*models.SGuest)
guest.SetStatus(self.UserCred, models.VM_DEPLOY_FAILED, data.String())
self.SetStageFailed(ctx, data.String())
}
func (self *GuestDeployTask) OnDeployStartGuestComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
self.SetStageComplete(ctx, nil)
}
func (self *GuestDeployTask) OnDeployStartGuestCompleteFailed(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
self.SetStageFailed(ctx, data.String())
}
func (self *GuestDeployTask) OnDeployGuestSyncstatusComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
self.SetStageComplete(ctx, nil)
}
func (self *GuestDeployTask) OnDeployGuestSyncstatusCompleteFailed(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
self.SetStageFailed(ctx, data.String())
}
type GuestDeployBackupTask struct {
GuestDeployTask
}
@@ -111,6 +111,7 @@ func (self *GuestRebuildRootTask) OnRebuildRootDiskCompleteFailed(ctx context.Co
db.OpsLog.LogEvent(guest, db.ACT_REBUILD_ROOT_FAIL, data, self.UserCred)
guest.SetStatus(self.UserCred, models.VM_REBUILD_ROOT_FAIL, "")
logclient.AddActionLog(guest, logclient.ACT_VM_REBUILD, data, self.UserCred, false)
self.SetStageFailed(ctx, data.String())
}
func (self *GuestRebuildRootTask) OnSyncStatusComplete(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
+9 -9
View File
@@ -68,7 +68,7 @@ func (self *GuestStartTask) RequestStart(ctx context.Context, guest *models.SGue
guest.SetStatus(self.UserCred, models.VM_STARTING, "")
result, err := guest.GetDriver().RequestStartOnHost(ctx, guest, host, self.UserCred, self)
if err != nil {
self.onStartGuestFailed(ctx, guest, err)
self.OnStartCompleteFailed(ctx, guest, jsonutils.NewString(err.Error()))
} else {
if result != nil && jsonutils.QueryBoolean(result, "is_running", false) {
// guest.SetStatus(self.UserCred, models.VM_RUNNING, "start")
@@ -84,7 +84,7 @@ func (self *GuestStartTask) RequestStartBacking(ctx context.Context, guest *mode
guest.SetStatus(self.UserCred, models.VM_BACKUP_STARTING, "")
result, err := guest.GetDriver().RequestStartOnHost(ctx, guest, host, self.UserCred, self)
if err != nil {
self.onStartGuestFailed(ctx, guest, err)
self.OnStartCompleteFailed(ctx, guest, jsonutils.NewString(err.Error()))
} else {
if result != nil && jsonutils.QueryBoolean(result, "is_running", false) {
self.OnStartBackupGuestComplete(ctx, guest, nil)
@@ -100,13 +100,17 @@ func (self *GuestStartTask) OnStartBackupGuestComplete(ctx context.Context, gues
nbdServerUri := fmt.Sprintf("nbd:%s:%d", backupHost.AccessIp, nbdServerPort)
guest.SetMetadata(ctx, "backup_nbd_server_uri", nbdServerUri, self.UserCred)
} else {
self.onStartGuestFailed(ctx, guest, fmt.Errorf("Start backup guest result missing nbd_server_port"))
self.OnStartCompleteFailed(ctx, guest, jsonutils.NewString("Start backup guest result missing nbd_server_port"))
return
}
}
self.RequestStart(ctx, guest)
}
func (self *GuestStartTask) OnStartBackupGuestCompleteFailed(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
self.OnStartCompleteFailed(ctx, guest, data)
}
func (self *GuestStartTask) OnStartComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
guest := obj.(*models.SGuest)
db.OpsLog.LogEvent(guest, db.ACT_START, guest.GetShortDesc(), self.UserCred)
@@ -123,14 +127,10 @@ func (self *GuestStartTask) OnGuestSyncstatusAfterStart(ctx context.Context, obj
func (self *GuestStartTask) OnStartCompleteFailed(ctx context.Context, obj db.IStandaloneModel, err jsonutils.JSONObject) {
guest := obj.(*models.SGuest)
guest.SetStatus(self.UserCred, models.VM_START_FAILED, err.String())
db.OpsLog.LogEvent(guest, db.ACT_START_FAIL, err, self.UserCred)
}
func (self *GuestStartTask) onStartGuestFailed(ctx context.Context, guest *models.SGuest, err error) {
guest.SetStatus(self.UserCred, models.VM_START_FAILED, err.Error())
self.SetStageFailed(ctx, err.Error())
self.OnStartCompleteFailed(ctx, guest, jsonutils.NewString(err.Error()))
logclient.AddActionLog(guest, logclient.ACT_VM_START, err, self.UserCred, false)
self.SetStageFailed(ctx, err.String())
}
func (self *GuestStartTask) taskComplete(ctx context.Context, guest *models.SGuest) {
+1
View File
@@ -40,6 +40,7 @@ func (self *GuestSuspendTask) OnSuspendCompleteFailed(ctx context.Context, obj d
guest := obj.(*models.SGuest)
guest.SetStatus(self.UserCred, models.VM_RUNNING, "")
db.OpsLog.LogEvent(guest, db.ACT_STOP_FAIL, err.String(), self.UserCred)
self.SetStageFailed(ctx, err.String())
}
func (self *GuestSuspendTask) OnSuspendGuestFail(guest *models.SGuest, reason string) {
+2 -2
View File
@@ -37,11 +37,11 @@ func init() {
registerCompute(&ServerSkus)
}
func (self *SkusManager) GetSkus(s *mcclient.ClientSession, providerId, regionId, zoneId string) (*ListResult, error) {
func (self *SkusManager) GetSkus(s *mcclient.ClientSession, providerId, regionId, zoneId string, limit, offset int) (*ListResult, error) {
p := strings.ToLower(providerId)
r := strings.ToLower(regionId)
z := strings.ToLower(zoneId)
url := fmt.Sprintf("/providers/%s/regions/%s/zones/%s/skus", p, r, z)
url := fmt.Sprintf("/providers/%s/regions/%s/zones/%s/skus?limit=%d&offset=%d", p, r, z, limit, offset)
ret, err := self._list(s, url, self.KeywordPlural)
if err != nil {
return &ListResult{}, err
+8 -5
View File
@@ -11,6 +11,7 @@ import (
"yunion.io/x/pkg/utils"
"context"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/util/billing"
@@ -228,13 +229,11 @@ func (self *SInstance) GetMetadata() *jsonutils.JSONDict {
data.Update(meta)
}
}
secgroupIds := jsonutils.NewArray()
for _, secgroupId := range self.SecurityGroupIds.SecurityGroupId {
if len(secgroupId) > 0 {
data.Add(jsonutils.NewString(secgroupId), "secgroupId")
break
}
secgroupIds.Add(jsonutils.NewString(secgroupId))
}
data.Add(secgroupIds, "secgroupIds")
return data
}
@@ -859,6 +858,10 @@ func (self *SInstance) AssignSecurityGroup(secgroupId string) error {
return self.host.zone.region.AssignSecurityGroup(secgroupId, self.InstanceId)
}
func (self *SInstance) AssignSecurityGroups(secgroupIds []string) error {
return self.host.zone.region.AssignSecurityGroups(secgroupIds, self.InstanceId)
}
func (self *SInstance) GetBillingType() string {
switch self.InstanceChargeType {
case PrePaidInstanceChargeType:
+11 -4
View File
@@ -501,16 +501,23 @@ func (self *SRegion) syncSecgroupRules(secgroupId string, rules []secrules.Secur
}
func (self *SRegion) AssignSecurityGroup(secgroupId, instanceId string) error {
params := map[string]string{"InstanceId": instanceId, "SecurityGroupId": secgroupId}
if _, err := self.ecsRequest("JoinSecurityGroup", params); err != nil {
return err
return self.AssignSecurityGroups([]string{secgroupId}, instanceId)
}
func (self *SRegion) AssignSecurityGroups(secgroupIds []string, instanceId string) error {
params := map[string]string{"InstanceId": instanceId}
for _, secgroupId := range secgroupIds {
params["SecurityGroupId"] = secgroupId
if _, err := self.ecsRequest("JoinSecurityGroup", params); err != nil {
return err
}
}
instance, err := self.GetInstance(instanceId)
if err != nil {
return err
}
for _, _secgroupId := range instance.SecurityGroupIds.SecurityGroupId {
if _secgroupId != secgroupId {
if !utils.IsInStringArray(_secgroupId, secgroupIds) {
if err := self.leaveSecurityGroup(_secgroupId, instanceId); err != nil {
return err
}
+10 -3
View File
@@ -87,7 +87,6 @@ func (self *SImage) GetStatus() string {
}
func (self *SImage) Refresh() error {
// todo: GetImage
new, err := self.storageCache.region.GetImage(self.ImageId)
if err != nil {
return err
@@ -173,7 +172,11 @@ func (self *SRegion) ExportImage(instanceId string, imageId string) (*ImageExpor
}
func (self *SRegion) GetImage(imageId string) (*SImage, error) {
images, _, err := self.GetImages("", ImageOwnerSelf, []string{imageId}, "", 0, 1)
if len(imageId) == 0 {
return nil, fmt.Errorf("image id should not be empty")
}
images, _, err := self.GetImages("", ImageOwnerType(""), []string{imageId}, "", 0, 1)
if err != nil {
return nil, err
}
@@ -184,7 +187,11 @@ func (self *SRegion) GetImage(imageId string) (*SImage, error) {
}
func (self *SRegion) GetImageByName(name string) (*SImage, error) {
images, _, err := self.GetImages("", ImageOwnerSelf, nil, name, 0, 1)
if len(name) == 0 {
return nil, fmt.Errorf("image name should not be empty")
}
images, _, err := self.GetImages("", ImageOwnerType(""), nil, name, 0, 1)
if err != nil {
return nil, err
}
+13 -6
View File
@@ -6,6 +6,7 @@ import (
"time"
"context"
"github.com/aws/aws-sdk-go/service/ec2"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
@@ -172,13 +173,11 @@ func (self *SInstance) GetMetadata() *jsonutils.JSONDict {
data.Update(meta)
}
}
secgroupIds := jsonutils.NewArray()
for _, secgroupId := range self.SecurityGroupIds.SecurityGroupId {
if len(secgroupId) > 0 {
data.Add(jsonutils.NewString(secgroupId), "secgroupId")
break
}
secgroupIds.Add(jsonutils.NewString(secgroupId))
}
data.Add(secgroupIds, "secgroupIds")
return data
}
@@ -281,7 +280,15 @@ func (self *SInstance) GetMachine() string {
}
func (self *SInstance) AssignSecurityGroup(secgroupId string) error {
return self.host.zone.region.assignSecurityGroup(secgroupId, self.InstanceId)
return self.AssignSecurityGroups([]string{secgroupId})
}
func (self *SInstance) AssignSecurityGroups(secgroupIds []string) error {
ids := []*string{}
for i := 0; i < len(secgroupIds); i++ {
ids = append(ids, &secgroupIds[i])
}
return self.host.zone.region.assignSecurityGroups(ids, self.InstanceId)
}
func (self *SInstance) GetHypervisor() string {
+5 -1
View File
@@ -246,6 +246,10 @@ func (self *SRegion) revokeSecurityGroup(secgroupId, instanceId string, keep boo
}
func (self *SRegion) assignSecurityGroup(secgroupId, instanceId string) error {
return self.assignSecurityGroups([]*string{&secgroupId}, instanceId)
}
func (self *SRegion) assignSecurityGroups(secgroupIds []*string, instanceId string) error {
instance, err := self.GetInstance(instanceId)
if err != nil {
return err
@@ -254,7 +258,7 @@ func (self *SRegion) assignSecurityGroup(secgroupId, instanceId string) error {
for _, eth := range instance.NetworkInterfaces.NetworkInterface {
params := &ec2.ModifyNetworkInterfaceAttributeInput{}
params.SetNetworkInterfaceId(eth.NetworkInterfaceId)
params.SetGroups([]*string{&secgroupId})
params.SetGroups(secgroupIds)
_, err := self.ec2Client.ModifyNetworkInterfaceAttribute(params)
if err != nil {
+9 -1
View File
@@ -6,6 +6,7 @@ import (
"time"
"context"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/cloudprovider"
@@ -130,9 +131,12 @@ func (self *SClassicInstance) GetMetadata() *jsonutils.JSONDict {
data := jsonutils.NewDict()
priceKey := fmt.Sprintf("%s::%s", self.Properties.HardwareProfile.Size, self.host.zone.region.Name)
data.Add(jsonutils.NewString(priceKey), "price_key")
data.Add(jsonutils.NewString(self.host.zone.GetGlobalId()), "zone_ext_id")
secgroupIds := jsonutils.NewArray()
if self.Properties.NetworkProfile.NetworkSecurityGroup != nil {
data.Add(jsonutils.NewString(self.Properties.NetworkProfile.NetworkSecurityGroup.ID), "secgroupId")
secgroupIds.Add(jsonutils.NewString(self.Properties.NetworkProfile.NetworkSecurityGroup.ID))
}
data.Add(secgroupIds, "secgroupIds")
return data
}
@@ -483,6 +487,10 @@ type assignProperties struct {
NetworkSecurityGroup SubResource `json:"networkSecurityGroup,omitempty"`
}
func (self *SClassicInstance) AssignSecurityGroups(secgroupIds []string) error {
return cloudprovider.ErrNotSupported
}
func (self *SClassicInstance) AssignSecurityGroup(secgroupId string) error {
if self.Properties.NetworkProfile.NetworkSecurityGroup != nil {
if self.Properties.NetworkProfile.NetworkSecurityGroup.ID == secgroupId {
+8 -2
View File
@@ -6,6 +6,7 @@ import (
"time"
"context"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/cloudprovider"
@@ -212,17 +213,18 @@ func (self *SInstance) GetMetadata() *jsonutils.JSONDict {
data.Add(jsonutils.NewString(self.host.zone.GetGlobalId()), "zone_ext_id")
priceKey := fmt.Sprintf("%s::%s", self.Properties.HardwareProfile.VMSize, self.host.zone.region.Name)
data.Add(jsonutils.NewString(priceKey), "price_key")
secgroupIds := jsonutils.NewArray()
if nics, err := self.getNics(); err == nil {
for _, nic := range nics {
if nic.Properties.NetworkSecurityGroup != nil {
if len(nic.Properties.NetworkSecurityGroup.ID) > 0 {
data.Add(jsonutils.NewString(nic.Properties.NetworkSecurityGroup.ID), "secgroupId")
secgroupIds.Add(jsonutils.NewString(nic.Properties.NetworkSecurityGroup.ID))
break
}
}
}
}
data.Add(secgroupIds, "secgroupIds")
return data
}
@@ -1018,6 +1020,10 @@ func (self *SInstance) AssignSecurityGroup(secgroupId string) error {
return self.host.zone.region.AssiginSecurityGroup(self.ID, secgroupId)
}
func (self *SInstance) AssignSecurityGroups(secgroupIds []string) error {
return cloudprovider.ErrNotSupported
}
func (self *SInstance) GetBillingType() string {
return models.BILLING_TYPE_POSTPAID
}
+4
View File
@@ -514,6 +514,10 @@ func (dc *SVirtualMachine) ChangeConfig2(ctx context.Context, instanceType strin
return cloudprovider.ErrNotImplemented
}
func (self *SVirtualMachine) AssignSecurityGroups(secgroupIds []string) error {
return cloudprovider.ErrNotImplemented
}
func (self *SVirtualMachine) GetBillingType() string {
return models.BILLING_TYPE_POSTPAID
}
+3 -3
View File
@@ -3,12 +3,12 @@ package imagetools
import "testing"
func TestNormalizeImageInfo(t *testing.T) {
info := NormalizeImageInfo("rhel67_20180816.qcow2", "", "", "")
info := NormalizeImageInfo("rhel67_20180816.qcow2", "", "", "", "")
t.Logf("%#v", info)
info = NormalizeImageInfo("Ubuntu_16.04.3_amd64_qingcloud_20180817.qcow2", "", "", "")
info = NormalizeImageInfo("Ubuntu_16.04.3_amd64_qingcloud_20180817.qcow2", "", "", "", "")
t.Logf("%#v", info)
info = NormalizeImageInfo("windows-server-2008-dc-cn-20180717", "", "", "")
info = NormalizeImageInfo("windows-server-2008-dc-cn-20180717", "", "", "", "")
t.Logf("%#v", info)
}
+43 -14
View File
@@ -38,21 +38,23 @@ func normalizeOsDistribution(osDist string, imageName string) string {
osDist = imageName
}
osDist = strings.ToLower(osDist)
if strings.HasPrefix(osDist, "centos") || strings.HasPrefix(osDist, "redhat") || strings.HasPrefix(osDist, "rhel") {
if strings.Contains(osDist, "centos") || strings.Contains(osDist, "redhat") || strings.Contains(osDist, "rhel") {
return "CentOS"
} else if strings.HasPrefix(osDist, "ubuntu") {
} else if strings.Contains(osDist, "ubuntu") {
return "Ubuntu"
} else if strings.HasPrefix(osDist, "suse") {
} else if strings.Contains(osDist, "suse") {
return "SUSE"
} else if strings.HasPrefix(osDist, "opensuse") {
} else if strings.Contains(osDist, "opensuse") {
return "OpenSUSE"
} else if strings.HasPrefix(osDist, "debian") {
} else if strings.Contains(osDist, "debian") {
return "Debian"
} else if strings.HasPrefix(osDist, "coreos") {
} else if strings.Contains(osDist, "coreos") {
return "CoreOS"
} else if strings.HasPrefix(osDist, "aliyun") {
} else if strings.Contains(osDist, "aliyun") {
return "Aliyun"
} else if strings.HasPrefix(osDist, "windows") {
} else if strings.Contains(osDist, "freebsd") {
return "FreeBSD"
} else if strings.Contains(osDist, "windows") {
if strings.Contains(osDist, "2003") {
return "Windows Server 2003"
} else if strings.Contains(osDist, "2008") {
@@ -69,18 +71,45 @@ func normalizeOsDistribution(osDist string, imageName string) string {
}
}
type ImageInfo struct {
Name string
OsArch string
OsType string
OsDistro string
var imageVersions = map[string][]string{
"CentOS": {"5", "6", "7"},
"FreeBSD": {"10"},
"Ubuntu": {"10", "12", "14", "16"},
"OpenSUSE": {"11", "12"},
"SUSE": {"10", "11", "12", "13"},
"Debian": {"6", "7", "8", "9"},
"CoreOS": {"7"},
"Aliyun": {},
}
func NormalizeImageInfo(imageName, osArch, osType, osDist string) ImageInfo {
func normalizeOsVersion(imageName string, osDist string, osVersion string) string {
if versions, ok := imageVersions[osDist]; ok {
for _, version := range versions {
if strings.HasPrefix(osVersion, version) {
return version
}
}
if len(versions) > 0 {
return versions[0]
}
}
return "-"
}
type ImageInfo struct {
Name string
OsArch string
OsType string
OsDistro string
OsVersion string
}
func NormalizeImageInfo(imageName, osArch, osType, osDist, osVersion string) ImageInfo {
info := ImageInfo{}
info.Name = imageName
info.OsDistro = normalizeOsDistribution(osDist, imageName)
info.OsType = normalizeOsType(osType, info.OsDistro)
info.OsArch = normalizeOsArch(osArch, info.OsType, info.OsDistro)
info.OsVersion = normalizeOsVersion(imageName, info.OsDistro, osVersion)
return info
}
+3
View File
@@ -227,6 +227,9 @@ func (self *SRegion) GetImportImageParams(name string, osArch, osDist, osVersion
}
if !utils.IsInStringArray(osVersion, _imageSet.OsVersions) {
osVersion = "-"
if len(_imageSet.OsVersions) > 0 {
osVersion = _imageSet.OsVersions[0]
}
}
break
}
+8 -1
View File
@@ -146,7 +146,6 @@ func (self *SInstance) GetMetadata() *jsonutils.JSONDict {
data.Add(jsonutils.NewString(self.host.zone.GetGlobalId()), "zone_ext_id")
secgroupIds := jsonutils.NewArray()
for _, secgroupId := range self.SecurityGroupIds {
data.Add(jsonutils.NewString(secgroupId), "secgroupId")
secgroupIds.Add(jsonutils.NewString(secgroupId))
}
data.Add(secgroupIds, "secgroupIds")
@@ -731,6 +730,14 @@ func (self *SInstance) AssignSecurityGroup(secgroupId string) error {
return self.host.zone.region.instanceOperation(self.InstanceId, "ModifyInstancesAttribute", params)
}
func (self *SInstance) AssignSecurityGroups(secgroupIds []string) error {
params := map[string]string{}
for i := 0; i < len(secgroupIds); i++ {
params[fmt.Sprintf("SecurityGroups.%d", i)] = secgroupIds[i]
}
return self.host.zone.region.instanceOperation(self.InstanceId, "ModifyInstancesAttribute", params)
}
func (self *SInstance) GetIEIP() (cloudprovider.ICloudEIP, error) {
eip, total, err := self.host.zone.region.GetEips("", self.InstanceId, 0, 1)
if err != nil {
+2 -2
View File
@@ -99,8 +99,8 @@ func _jsonRequest(client *common.Client, domain string, version string, apiName
break
}
needRetry := false
for _, msg := range []string{"EOF", "TLS handshake timeout", "Code=InternalError"} {
if strings.Index(err.Error(), msg) > 0 {
for _, msg := range []string{"EOF", "TLS handshake timeout", "Code=InternalError", "retry later", "Code=MutexOperation.TaskRunning"} {
if strings.Contains(err.Error(), msg) {
needRetry = true
break
}
-9
View File
@@ -1,9 +0,0 @@
(The MIT License)
Copyright (c) 2017 marvin + konsorten GmbH (open-source@konsorten.de)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+1 -1
View File
@@ -106,7 +106,7 @@ func GetOSProfileFromImageProperties(imgProp map[string]string, hypervisor strin
}
var imgHypers []string
imgHyperStr, ok := imgProp["hypervisor"]
if ok {
if ok && len(imgHyperStr) > 0 {
imgHypers = strings.Split(imgHyperStr, ",")
} else {
imgHypers = []string{}