Compare commits

...

58 Commits

Author SHA1 Message Date
yunion-ci-robot
a5ec90abdb Merge pull request #7907 from wanyaoqi/automated-cherry-pick-of-#7905-upstream-release-3.3
Automated cherry pick of #7905: webconsole: fix defer order to release zombie process
2020-09-15 10:26:11 +08:00
wanyaoqi
77c3e490c2 webconsole: fix defer order to release zombie process 2020-09-14 18:21:38 +08:00
Zexi Li
12aef33055 Merge pull request #7904 from rainzm/automated-cherry-pick-of-#7902-upstream-release-3.3
Automated cherry pick of #7902: fix(esxi): return when host.Vm is empty
2020-09-14 16:28:11 +08:00
rainzm
c4180811b5 fix(esxi): return when host.Vm is empty 2020-09-14 16:27:04 +08:00
yunion-ci-robot
8d8439db4f Merge pull request #7901 from ioito/automated-cherry-pick-of-#7899-upstream-release-3.3
Automated cherry pick of #7899: fix: cos use proxy
2020-09-14 14:03:15 +08:00
Zexi Li
871df54d3b Merge pull request #7897 from wanyaoqi/automated-cherry-pick-of-#7895-upstream-release-3.3
Automated cherry pick of #7895: disk: check disk is need renew on guest set renew
2020-09-14 13:02:11 +08:00
Qu Xuan
24e3da7818 fix: cos use proxy 2020-09-14 13:01:36 +08:00
wanyaoqi
6f5bb55ea0 disk: check disk is need renew on guest set renew 2020-09-14 12:08:17 +08:00
yunion-ci-robot
1d006efc78 Merge pull request #7892 from swordqiu/automated-cherry-pick-of-#7890-upstream-release-3.3
Automated cherry pick of #7890: fix: disable webkms for esxi older than 6.5
2020-09-12 23:55:16 +08:00
yunion-ci-robot
5a91d66939 Merge pull request #7889 from yousong/automated-cherry-pick-of-#7887-upstream-release-3.3
Automated cherry pick of #7887: elasticips: filter by owner when doing auto allocation
2020-09-12 23:54:10 +08:00
Qiu Jian
c2fbe4faf1 fix: disable webkms for esxi older than 6.5 2020-09-12 17:32:41 +08:00
Yousong Zhou
ef8b9e6aea elasticips: filter by owner when doing auto allocation 2020-09-12 17:15:02 +08:00
yunion-ci-robot
2a3464e8e7 Merge pull request #7878 from ioito/automated-cherry-pick-of-#7876-upstream-release-3.3
Automated cherry pick of #7876: fix: 默认不自动合并安全组
2020-09-11 21:03:55 +08:00
Zexi Li
db596b0db1 Merge pull request #7881 from ioito/automated-cherry-pick-of-#7879-upstream-release-3.3
Automated cherry pick of #7879: fix: avoid sync natgateway eip panic
2020-09-11 21:03:50 +08:00
Zexi Li
c766696df9 Merge pull request #7872 from rainzm/automated-cherry-pick-of-#7870-upstream-release-3.3
Automated cherry pick of #7870: fix(esxiagent): add HostDelayTaskWorkerCount
2020-09-11 20:55:42 +08:00
Zexi Li
bc4540649a Merge pull request #7864 from wanyaoqi/automated-cherry-pick-of-#7836-upstream-release-3.3
Automated cherry pick of #7836: host: fix rbd storage cache iso image
2020-09-11 20:54:12 +08:00
Zexi Li
c3a2349f41 Merge pull request #7861 from ioito/automated-cherry-pick-of-#7859-upstream-release-3.3
Automated cherry pick of #7859: fix: 平滑迁移数据
2020-09-11 20:52:22 +08:00
Qu Xuan
9920e3b50d fix: avoid sync natgateway eip panic 2020-09-11 19:17:52 +08:00
Qu Xuan
e5d7fee933 fix: 默认不自动合并安全组 2020-09-11 17:38:16 +08:00
rainzm
da0246e667 fix(esxiagent): add HostDelayTaskWorkerCount
之前,HostDelayWorker 是通过 hostutils.InitWorkerManager 来初始化,
worker的数量依赖于options.HostOptions.DefaultRequestWorkerCount, 因为
这个options没有经过初始化,所以就是0,导致worker count的数量变为1。

现在增加了 HostDelayTaskWorkerCount 来管理这个count,默认值为8。
2020-09-11 17:22:30 +08:00
wanyaoqi
f017daafc2 host: fix rbd storage cache iso image 2020-09-10 23:17:08 +08:00
yunion-ci-robot
bd4d0e11b2 Merge pull request #7857 from ioito/automated-cherry-pick-of-#7855-upstream-release-3.3
Automated cherry pick of #7855: fix: optimized qcloud keypair
2020-09-10 21:34:33 +08:00
Qu Xuan
0428425011 fix: 平滑迁移数据 2020-09-10 17:40:07 +08:00
Qu Xuan
dfafa03364 fix: 腾讯云不支持同时设置秘钥和密码,若设置秘钥,则将密码置空 2020-09-10 17:26:22 +08:00
Qu Xuan
a1aafa67df fix: optimized qcloud keypair 2020-09-10 17:26:22 +08:00
yunion-ci-robot
1041d6e017 Merge pull request #7833 from rainzm/automated-cherry-pick-of-#7832-upstream-release-3.3
Automated cherry pick of #7832: refactor(region): optimize preparenet of cloudaccount
2020-09-10 16:04:56 +08:00
rainzm
df64b90805 refactor(region): optimize preparenet of cloudaccount
1. 从vcenter中获取host和vm的信息时,只需要获取网络相关的字段就可以了。
2. 每个host的vms,单独启用一个goroutine。
3. 优化了处理vms ip的逻辑,现在的时间复杂度是O(n)。
2020-09-10 15:48:40 +08:00
yunion-ci-robot
c90ee3522f Merge pull request #7850 from ioito/automated-cherry-pick-of-#7834-upstream-release-3.3
Automated cherry pick of #7834: fix: uniform cachedimage active status
2020-09-10 14:36:04 +08:00
Qu Xuan
cb288f65eb fix: uniform cachedimage active status 2020-09-10 10:22:57 +08:00
yunion-ci-robot
e073fab189 Merge pull request #7847 from rainzm/automated-cherry-pick-of-#7845-upstream-release-3.3
Automated cherry pick of #7845: Feat & Fix & Refactor for ESXi
2020-09-10 09:41:58 +08:00
rainzm
13608b43e7 fix(region): add RequestSyncstatusOnHost for SESXiGuestDriver
esxi 平台 Guest 进行 syncstatus 和其他平台有所区别,Vcenter 可能会更改
 VM 所在的 Host,所以在 Host 上寻找 VM 可能会出现 ErrNotFound。此时,应该
主动去整个 datacenter 中寻找 VM,然后更改 Host,进行同步。
2020-09-09 21:57:11 +08:00
rainzm
be4a95ca80 fix(esxi): fetch templatevm from datacenter before clone vm
这里应该和image_cache那里保持一直,对template的获取应该从datacenter
中获取,而不是host。
2020-09-09 21:56:20 +08:00
rainzm
35919e1ece refactor(esxi): replace GetTemplateVMById with FetchTemplateVMById
FetchTemplateVMById 更好,因为它更轻量,更快。
2020-09-09 21:56:20 +08:00
rainzm
af76ae975e feat(esxicli): better vm operator
现在,可以通过Datacenter来获取vm,不一定要指定HostIp,
Datacenter和HostIp必须指定一个。
2020-09-09 21:56:20 +08:00
rainzm
3a8c90d7df feat(esxi): support fetchVM form datacenter 2020-09-09 21:56:20 +08:00
rainzm
86c0af8ca5 refactor(esxi): fetchVms and fetchHardwareInfo
1. fetchHardwareInfo 只有一种error,原因是moVM的某些字段为nil,这种情况下,完全可以打印日志直接返回。
2. fetchVms 现在只返回[]*SVirtualMachine, 进一步的过滤(是不是template)交给调用者。
2020-09-09 21:56:20 +08:00
yunion-ci-robot
44313bb394 Merge pull request #7830 from swordqiu/automated-cherry-pick-of-#7828-upstream-release-3.3
Automated cherry pick of #7828: fix: wire usage stats incorrect
2020-09-08 20:28:56 +08:00
yunion-ci-robot
2be6a06580 Merge pull request #7824 from swordqiu/automated-cherry-pick-of-#7820-upstream-release-3.3
Automated cherry pick of #7820: fix: ignore 409 error when doing redfish power on
2020-09-08 20:24:53 +08:00
yunion-ci-robot
8fe49104cb Merge pull request #7823 from rainzm/automated-cherry-pick-of-#7821-upstream-release-3.3
Automated cherry pick of #7821: fix(esxiagent): return image extid not id
2020-09-08 20:23:55 +08:00
Qiu Jian
45d6686a39 fix: wire usage stats incorrect 2020-09-08 16:43:44 +08:00
rainzm
171c95bf55 fix(esxiagent): return image extid not id
调用 disk/image_cache 接口的Task StorageCacheImageTask 会根据回调
回来数据中的 image_id,来设置 storagecachedimage 中的 externalid,
所以这里的 image_id 应该是 externalid。
2020-09-08 15:33:48 +08:00
Qiu Jian
508c934e8a fix: ignore 409 error when doing redfish power on 2020-09-08 15:22:48 +08:00
yunion-ci-robot
dc5eb6c09e Merge pull request #7806 from yousong/automated-cherry-pick-of-#7804-upstream-release-3.3
Automated cherry pick of #7804: vpcagent: guard against foul eip records
2020-09-08 10:07:51 +08:00
yunion-ci-robot
af0e87bd54 Merge pull request #7800 from wanyaoqi/automated-cherry-pick-of-#7798-upstream-release-3.3
Automated cherry pick of #7798: guest short desc add backup host id
2020-09-07 21:01:51 +08:00
yunion-ci-robot
d77616fb5f Merge pull request #7791 from wanyaoqi/automated-cherry-pick-of-#7789-upstream-release-3.3
Automated cherry pick of #7789: fix get ubuntu version
2020-09-07 20:59:45 +08:00
Zexi Li
def5bad5f5 Merge pull request #7795 from ioito/automated-cherry-pick-of-#7793-upstream-release-3.3
Automated cherry pick of #7793: fix: aliyun wulanchabu region
2020-09-07 20:55:42 +08:00
yunion-ci-robot
15ec57cad6 Merge pull request #7812 from swordqiu/automated-cherry-pick-of-#7811-upstream-release-3.3
Automated cherry pick of #7811: fix: prevent users in disabled idp from login
2020-09-07 20:55:13 +08:00
Qiu Jian
e64af28e89 fix: prevent users in disabled idp from login 2020-09-07 18:25:12 +08:00
Yousong Zhou
96058b4afe vpcagent: guard against foul eip records 2020-09-07 17:27:36 +08:00
wanyaoqi
b120b87c4f guest short desc add backup host id 2020-09-07 17:06:02 +08:00
Qu Xuan
fb9ae22fec fix: aliyun wulanchabu region 2020-09-07 16:11:02 +08:00
wanyaoqi
22e4181b37 fix get ubuntu version 2020-09-07 16:00:56 +08:00
yunion-ci-robot
6fef273e9c Merge pull request #7788 from rainzm/automated-cherry-pick-of-#7786-upstream-release-3.3
Automated cherry pick of #7786: fix(scheduler): fix array out of bounds when sorting hosts
2020-09-07 15:33:41 +08:00
yunion-ci-robot
cf1b81c70e Merge pull request #7784 from rainzm/automated-cherry-pick-of-#7782-upstream-release-3.3
Automated cherry pick of #7782: fix(notify): Replace String() with GetString()
2020-09-07 15:26:42 +08:00
rainzm
6874b94404 fix(scheduler): fix array out of bounds when sorting hosts 2020-09-07 15:21:58 +08:00
rainzm
4da5a00422 fix(notify): Replace String() with GetString()
The String() of jsonutils.JSONObject will add a pair of
double quotes around the content. The GetString() will
get a clean content.
2020-09-07 15:11:25 +08:00
yunion-ci-robot
92c99fe828 Merge pull request #7779 from ioito/automated-cherry-pick-of-#7729-upstream-release-3.3
Automated cherry pick of #7729: optimized cachedimages sync
2020-09-07 11:08:42 +08:00
Qu Xuan
23b02045a1 optimized cachedimages sync 2020-09-07 10:18:15 +08:00
75 changed files with 1241 additions and 492 deletions

View File

@@ -27,7 +27,7 @@ type CachedImageUncacheImageInput struct {
}
type CachedimageDetails struct {
apis.StandaloneResourceDetails
apis.SharableVirtualResourceDetails
SCachedimage

View File

@@ -18,7 +18,7 @@ const (
CACHED_IMAGE_STATUS_INIT = "init"
CACHED_IMAGE_STATUS_SAVING = "saving"
CACHED_IMAGE_STATUS_CACHING = "caching"
CACHED_IMAGE_STATUS_READY = "ready"
CACHED_IMAGE_STATUS_ACTIVE = "active"
CACHED_IMAGE_STATUS_DELETING = "deleting"
CACHED_IMAGE_STATUS_CACHE_FAILED = "cache_fail"

View File

@@ -57,6 +57,7 @@ const (
CITY_FO_SHAN = "Foshan" //佛山
CITY_QUAN_ZHOU = "Quanzhou" //泉州
CITY_NEI_MENG_GU = "Neimenggu" //内蒙古
CITY_WU_LAN_CHA_BU = "Wulanchabu" //乌兰察布
// 日本
CITY_TOKYO = "Tokyo" //东京

View File

@@ -49,7 +49,7 @@ type KeypairListInput struct {
}
type CachedimageListInput struct {
apis.StandaloneResourceListInput
apis.SharableVirtualResourceListInput
apis.ExternalizedResourceBaseListInput
ManagedResourceListInput

View File

@@ -248,3 +248,6 @@ type GuestsecgroupDetails struct {
// 安全组名称
Secgroup string `json:"secgroup"`
}
type SecurityGroupPurgeInput struct {
}

View File

@@ -61,6 +61,7 @@ import (
"yunion.io/x/onecloud/pkg/mcclient/modules"
"yunion.io/x/onecloud/pkg/util/dhcp"
"yunion.io/x/onecloud/pkg/util/fileutils2"
"yunion.io/x/onecloud/pkg/util/httputils"
"yunion.io/x/onecloud/pkg/util/influxdb"
"yunion.io/x/onecloud/pkg/util/procutils"
"yunion.io/x/onecloud/pkg/util/redfish"
@@ -1398,7 +1399,15 @@ func (b *SBaremetalInstance) DoRedfishPowerOn() error {
b.ClearSSHConfig()
redfishApi := b.GetRedfishCli(ctx)
if redfishApi != nil {
return redfishApi.Reset(ctx, "On")
err := redfishApi.Reset(ctx, "On")
if err != nil {
if httputils.ErrorCode(err) == 409 {
log.Warningf("redfishApi.Reset On fail %s", err)
} else {
return errors.Wrap(err, "redfishApi.Reset On")
}
}
return nil
}
return fmt.Errorf("Baremetal %s redfishApi is nil", b.GetId())
}

View File

@@ -126,7 +126,7 @@ func RawNotify(recipientId []string, isGroup bool, channel notify.TNotifyChannel
msg.Topic = topic
body, _ := getContent(event, "content", channel, data)
if len(body) == 0 {
body = data.String()
body, _ = data.GetString()
}
msg.Msg = body
// log.Debugf("send notification %s %s", topic, body)

View File

@@ -156,7 +156,7 @@ type ICloudZone interface {
}
type ICloudImage interface {
ICloudResource
IVirtualResource
Delete(ctx context.Context) error
GetIStoragecache() ICloudStoragecache
@@ -173,6 +173,7 @@ type ICloudImage interface {
GetImageFormat() string
GetCreatedAt() time.Time
UEFI() bool
GetPublicScope() rbacutils.TRbacScope
}
type ICloudStoragecache interface {

View File

@@ -314,6 +314,10 @@ func (self *SBaseGuestDriver) IsWindowsUserDataTypeNeedEncode() bool {
return false
}
func (self *SBaseGuestDriver) IsSupportdDcryptPasswordFromSecretKey() bool {
return true
}
func (self *SBaseGuestDriver) GetUserDataType() string {
return cloudprovider.CLOUD_CONFIG
}

View File

@@ -172,7 +172,7 @@ func (self *SESXiGuestDriver) GetJsonDescAtHost(ctx context.Context, userCred mc
if img.ImageType != cloudprovider.CachedImageTypeSystem {
return desc
}
sciSubQ := models.StoragecachedimageManager.Query("storagecache_id").Equals("cachedimage_id", templateId).Equals("status", api.CACHED_IMAGE_STATUS_READY).SubQuery()
sciSubQ := models.StoragecachedimageManager.Query("storagecache_id").Equals("cachedimage_id", templateId).Equals("status", api.CACHED_IMAGE_STATUS_ACTIVE).SubQuery()
scQ := models.StoragecacheManager.Query().In("id", sciSubQ)
storageCaches := make([]models.SStoragecache, 0, 1)
err = db.FetchModelObjects(models.StoragecacheManager, scQ, &storageCaches)
@@ -368,3 +368,42 @@ func (self *SESXiGuestDriver) RequestAssociateEip(ctx context.Context, userCred
func (self *SESXiGuestDriver) IsSupportCdrom(guest *models.SGuest) (bool, error) {
return false, nil
}
func (self *SESXiGuestDriver) RequestSyncstatusOnHost(ctx context.Context, guest *models.SGuest, host *models.SHost, userCred mcclient.TokenCredential) (jsonutils.JSONObject, error) {
ihost, err := host.GetIHost()
if err != nil {
return nil, err
}
ivm, err := ihost.GetIVMById(guest.GetExternalId())
if err != nil && errors.Cause(err) != errors.ErrNotFound {
return nil, err
}
// VM may be migrated by Vcenter, try to find VM from whole datacenter.
if err != nil {
ehost := ihost.(*esxi.SHost)
dc, err := ehost.GetDatacenter()
if err != nil {
return nil, errors.Wrapf(err, "ehost.GetDatacenter")
}
vm, err := dc.FetchVMById(guest.GetExternalId())
if err != nil {
log.Errorf("fail to find ivm by id %q in dc %q: %v", guest.GetExternalId(), dc.GetName(), err)
return nil, err
}
ihost = vm.GetIHost()
host = models.HostManager.FetchHostByExtId(ihost.GetGlobalId())
if host == nil {
return nil, errors.Wrapf(errors.ErrNotFound, "find ivm %q in ihost %q which is not existed here", guest.GetExternalId(), ihost.GetGlobalId())
}
ivm = vm
}
err = guest.SyncAllWithCloudVM(ctx, userCred, host, ivm)
if err != nil {
return nil, err
}
status := GetCloudVMStatus(ivm)
body := jsonutils.NewDict()
body.Add(jsonutils.NewString(status), "status")
return body, nil
}

View File

@@ -226,6 +226,10 @@ func (self *SQcloudGuestDriver) GetGuestInitialStateAfterRebuild() string {
return api.VM_RUNNING
}
func (self *SQcloudGuestDriver) IsSupportdDcryptPasswordFromSecretKey() bool {
return false
}
func (self *SQcloudGuestDriver) GetUserDataType() string {
return cloudprovider.CLOUD_SHELL
}

View File

@@ -182,7 +182,7 @@ func (self *SManagedVirtualizationHostDriver) RequestSaveUploadImageOnHost(ctx c
osType, _ := params.GetString("properties", "os_type")
scimg := models.StoragecachedimageManager.Register(ctx, task.GetUserCred(), iStoragecache.GetId(), imageId, "")
if scimg.Status != api.CACHED_IMAGE_STATUS_READY {
if scimg.Status != api.CACHED_IMAGE_STATUS_ACTIVE {
scimg.SetStatus(task.GetUserCred(), api.CACHED_IMAGE_STATUS_CACHING, "request_prepare_save_disk_on_host")
}
iImage, err := iStoragecache.CreateIImage(snapshot.GetId(), fmt.Sprintf("Image-%s", imageId), osType, "")
@@ -208,7 +208,7 @@ func (self *SManagedVirtualizationHostDriver) RequestSaveUploadImageOnHost(ctx c
if err := snapshot.Delete(); err != nil {
log.Errorf("Delete snapshot %s failed: %v", snapshot.GetId(), err)
}
scimg.SetStatus(task.GetUserCred(), api.CACHED_IMAGE_STATUS_READY, "")
scimg.SetStatus(task.GetUserCred(), api.CACHED_IMAGE_STATUS_ACTIVE, "")
return result, nil
})
return nil

View File

@@ -37,11 +37,12 @@ import (
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/mcclient/modules"
"yunion.io/x/onecloud/pkg/util/rbacutils"
"yunion.io/x/onecloud/pkg/util/stringutils2"
)
type SCachedimageManager struct {
db.SStandaloneResourceBaseManager
db.SSharableVirtualResourceBaseManager
db.SExternalizedResourceBaseManager
}
@@ -49,7 +50,7 @@ var CachedimageManager *SCachedimageManager
func init() {
CachedimageManager = &SCachedimageManager{
SStandaloneResourceBaseManager: db.NewStandaloneResourceBaseManager(
SSharableVirtualResourceBaseManager: db.NewSharableVirtualResourceBaseManager(
SCachedimage{},
"cachedimages_tbl",
"cachedimage",
@@ -60,7 +61,7 @@ func init() {
}
type SCachedimage struct {
db.SStandaloneResourceBase
db.SSharableVirtualResourceBase
db.SExternalizedResourceBase
// 镜像大小单位: Byte
@@ -100,10 +101,10 @@ func (self *SCachedimage) ValidateDeleteCondition(ctx context.Context) error {
if cnt > 0 {
return httperrors.NewNotEmptyError("The image has been cached on storages")
}
if self.GetStatus() == "active" && !self.isReferenceSessionExpire() {
if self.GetStatus() == api.CACHED_IMAGE_STATUS_ACTIVE && !self.isReferenceSessionExpire() {
return httperrors.NewConflictError("the image reference session has not been expired!")
}
return self.SStandaloneResourceBase.ValidateDeleteCondition(ctx)
return self.SSharableVirtualResourceBase.ValidateDeleteCondition(ctx)
}
func (self *SCachedimage) isReferenceSessionExpire() bool {
@@ -194,32 +195,44 @@ func (manager *SCachedimageManager) cacheGlanceImageInfo(ctx context.Context, us
lockman.LockClass(ctx, manager, db.GetLockClassKey(manager, userCred))
defer lockman.ReleaseClass(ctx, manager, db.GetLockClassKey(manager, userCred))
imgId, _ := info.GetString("id")
if len(imgId) == 0 {
img := struct {
Id string
Size int64
Name string
Status string
IsPublic bool
ProjectId string `json:"tenant_id"`
PublicScope string
}{}
err := info.Unmarshal(&img)
if err != nil {
return nil, errors.Wrapf(err, "Unmarshal %s", info.String())
}
if len(img.Id) == 0 {
return nil, fmt.Errorf("invalid image info")
}
if len(img.Name) == 0 {
img.Name = img.Id
}
imageCache := SCachedimage{}
imageCache.SetModelManager(manager, &imageCache)
size, _ := info.Int("size")
name, _ := info.GetString("name")
if len(name) == 0 {
name = imgId
}
name, err := db.GenerateName(manager, nil, name)
img.Name, err = db.GenerateName(manager, nil, img.Name)
if err != nil {
return nil, err
return nil, errors.Wrapf(err, "db.GenerateName(%s)", img.Name)
}
err = manager.RawQuery().Equals("id", imgId).First(&imageCache)
err = manager.RawQuery().Equals("id", img.Id).First(&imageCache)
if err != nil {
if err == sql.ErrNoRows { // insert
imageCache.Id = imgId
imageCache.Name = name
imageCache.Size = size
imageCache.Id = img.Id
imageCache.Name = img.Name
imageCache.Size = img.Size
imageCache.Info = info
imageCache.Status = img.Status
imageCache.IsPublic = img.IsPublic
imageCache.PublicScope = img.PublicScope
imageCache.LastSync = timeutils.UtcNow()
err = manager.TableSpec().Insert(ctx, &imageCache)
@@ -230,13 +243,16 @@ func (manager *SCachedimageManager) cacheGlanceImageInfo(ctx context.Context, us
return &imageCache, nil
} else {
log.Errorf("fetching image cache (%s) failed: %s", imgId, err)
log.Errorf("fetching image cache (%s) failed: %s", img.Id, err)
return nil, err
}
} else { // update
diff, err := db.Update(&imageCache, func() error {
imageCache.Size = size
imageCache.Size = img.Size
imageCache.Info = info
imageCache.Status = img.Status
imageCache.IsPublic = img.IsPublic
imageCache.PublicScope = img.PublicScope
imageCache.LastSync = timeutils.UtcNow()
if imageCache.Deleted == true {
imageCache.Deleted = false
@@ -323,16 +339,15 @@ func (manager *SCachedimageManager) FetchCustomizeColumns(
isList bool,
) []api.CachedimageDetails {
rows := make([]api.CachedimageDetails, len(objs))
stdRows := manager.SStandaloneResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
virtRows := manager.SSharableVirtualResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
for i := range rows {
ci := objs[i].(*SCachedimage)
rows[i] = api.CachedimageDetails{
StandaloneResourceDetails: stdRows[i],
Status: ci.GetStatus(),
OsType: ci.GetOSType(),
OsDistribution: ci.GetOSDistribution(),
OsVersion: ci.GetOSVersion(),
Hypervisor: ci.GetHypervisor(),
SharableVirtualResourceDetails: virtRows[i],
OsType: ci.GetOSType(),
OsDistribution: ci.GetOSDistribution(),
OsVersion: ci.GetOSVersion(),
Hypervisor: ci.GetHypervisor(),
}
rows[i].CachedCount, _ = ci.getStoragecacheCount()
}
@@ -372,7 +387,7 @@ func (self *SCachedimage) PerformUncacheImage(ctx context.Context, userCred mccl
}
func (self *SCachedimage) addRefCount() {
if self.GetStatus() != "active" {
if self.GetStatus() != api.CACHED_IMAGE_STATUS_ACTIVE {
return
}
_, err := db.Update(self, func() error {
@@ -397,7 +412,7 @@ func (self *SCachedimage) ChooseSourceStoragecacheInRange(hostType string, exclu
Join(hostStorage, sqlchemy.Equals(hostStorage.Field("storage_id"), storage.Field("id"))).
Join(host, sqlchemy.Equals(hostStorage.Field("host_id"), host.Field("id"))).
Filter(sqlchemy.Equals(storageCachedImage.Field("cachedimage_id"), self.Id)).
Filter(sqlchemy.Equals(storageCachedImage.Field("status"), api.CACHED_IMAGE_STATUS_READY)).
Filter(sqlchemy.Equals(storageCachedImage.Field("status"), api.CACHED_IMAGE_STATUS_ACTIVE)).
Filter(sqlchemy.Equals(host.Field("status"), api.HOST_STATUS_RUNNING)).
Filter(sqlchemy.IsTrue(host.Field("enabled"))).
Filter(sqlchemy.Equals(host.Field("host_status"), api.HOST_ONLINE)).
@@ -455,12 +470,17 @@ func (self *SCachedimage) canDeleteLastCache() bool {
return false
}
func (self *SCachedimage) syncWithCloudImage(ctx context.Context, userCred mcclient.TokenCredential, image cloudprovider.ICloudImage) error {
func (self *SCachedimage) syncWithCloudImage(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, image cloudprovider.ICloudImage, managerId string) error {
diff, err := db.UpdateWithLock(ctx, self, func() error {
self.Name = image.GetName()
self.Size = image.GetSizeByte()
self.ExternalId = image.GetGlobalId()
self.ImageType = image.GetImageType()
self.PublicScope = string(image.GetPublicScope())
self.Status = image.GetStatus()
if image.GetPublicScope() == rbacutils.ScopeSystem {
self.IsPublic = true
}
self.UEFI = tristate.NewFromBool(image.UEFI())
sImage := cloudprovider.CloudImage2Image(image)
self.Info = jsonutils.Marshal(&sImage)
@@ -468,10 +488,12 @@ func (self *SCachedimage) syncWithCloudImage(ctx context.Context, userCred mccli
return nil
})
db.OpsLog.LogSyncUpdate(self, diff, userCred)
SyncCloudProject(userCred, self, ownerId, image, managerId)
return err
}
func (manager *SCachedimageManager) newFromCloudImage(ctx context.Context, userCred mcclient.TokenCredential, image cloudprovider.ICloudImage) (*SCachedimage, error) {
func (manager *SCachedimageManager) newFromCloudImage(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, image cloudprovider.ICloudImage, managerId string) (*SCachedimage, error) {
lockman.LockClass(ctx, manager, db.GetLockClassKey(manager, userCred))
defer lockman.ReleaseClass(ctx, manager, db.GetLockClassKey(manager, userCred))
@@ -491,12 +513,21 @@ func (manager *SCachedimageManager) newFromCloudImage(ctx context.Context, userC
cachedImage.LastSync = time.Now().UTC()
cachedImage.ImageType = image.GetImageType()
cachedImage.ExternalId = image.GetGlobalId()
cachedImage.Status = image.GetStatus()
cachedImage.PublicScope = string(image.GetPublicScope())
switch image.GetPublicScope() {
case rbacutils.ScopeNone:
default:
cachedImage.IsPublic = true
}
err = manager.TableSpec().Insert(ctx, &cachedImage)
if err != nil {
return nil, err
}
SyncCloudProject(userCred, &cachedImage, ownerId, image, managerId)
return &cachedImage, nil
}
@@ -529,7 +560,7 @@ func (image *SCachedimage) requestRefreshExternalImage(ctx context.Context, user
log.Errorf("iCache.GetIImageById fail %s", err)
return nil, err
}
err = image.syncWithCloudImage(ctx, userCred, iImage)
err = image.syncWithCloudImage(ctx, userCred, nil, iImage, "")
if err != nil {
log.Errorf("image.syncWithCloudImage fail %s", err)
return nil, err
@@ -549,7 +580,7 @@ func (image *SCachedimage) getValidStoragecache() []SStoragecache {
q = q.Filter(sqlchemy.In(providers.Field("status"), api.CLOUD_PROVIDER_VALID_STATUS))
q = q.Filter(sqlchemy.In(providers.Field("health_status"), api.CLOUD_PROVIDER_VALID_HEALTH_STATUS))
q = q.Filter(sqlchemy.Equals(storagecacheimages.Field("cachedimage_id"), image.Id))
q = q.Filter(sqlchemy.Equals(storagecacheimages.Field("status"), api.CACHED_IMAGE_STATUS_READY))
q = q.Filter(sqlchemy.Equals(storagecacheimages.Field("status"), api.CACHED_IMAGE_STATUS_ACTIVE))
caches := make([]SStoragecache, 0)
err := db.FetchModelObjects(StoragecacheManager, q, &caches)
@@ -589,7 +620,7 @@ func (image *SCachedimage) GetUsableZoneIds() ([]string, error) {
q = q.Filter(sqlchemy.In(providers.Field("status"), api.CLOUD_PROVIDER_VALID_STATUS))
q = q.Filter(sqlchemy.In(providers.Field("health_status"), api.CLOUD_PROVIDER_VALID_HEALTH_STATUS))
q = q.Filter(sqlchemy.Equals(storagecacheimages.Field("cachedimage_id"), image.Id))
q = q.Filter(sqlchemy.Equals(storagecacheimages.Field("status"), api.CACHED_IMAGE_STATUS_READY))
q = q.Filter(sqlchemy.Equals(storagecacheimages.Field("status"), api.CACHED_IMAGE_STATUS_ACTIVE))
q = q.Filter(sqlchemy.Equals(q.Field("status"), api.ZONE_ENABLE))
result := []string{}
@@ -632,6 +663,10 @@ func (manager *SCachedimageManager) ListItemFilter(
query api.CachedimageListInput,
) (*sqlchemy.SQuery, error) {
var err error
q, err = manager.SSharableBaseResourceManager.ListItemFilter(ctx, q, userCred, query.SharableResourceBaseListInput)
if err != nil {
return nil, errors.Wrapf(err, "SSharableBaseResourceManager.ListItemFilter")
}
q, err = managedResourceFilterByAccount(q, query.ManagedResourceListInput, "id", func() *sqlchemy.SQuery {
cachedImages := CachedimageManager.Query().SubQuery()
@@ -647,9 +682,9 @@ func (manager *SCachedimageManager) ListItemFilter(
return nil, errors.Wrap(err, "managedResourceFilterByAccount")
}
q, err = manager.SStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, query.StandaloneResourceListInput)
q, err = manager.SSharableVirtualResourceBaseManager.ListItemFilter(ctx, q, userCred, query.SharableVirtualResourceListInput)
if err != nil {
return nil, errors.Wrap(err, "SStandaloneResourceBaseManager.ListItemFilter")
return nil, errors.Wrap(err, "SSharableVirtualResourceBaseManager.ListItemFilter")
}
q, err = manager.SExternalizedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ExternalizedResourceBaseListInput)
@@ -667,7 +702,7 @@ func (manager *SCachedimageManager) ListItemFilter(
subq = subq.Join(storageCaches, sqlchemy.Equals(storagecachedImages.Field("storagecache_id"), storageCaches.Field("id")))
subq = subq.Join(storages, sqlchemy.Equals(storageCaches.Field("id"), storages.Field("storagecache_id")))
subq = subq.Join(zones, sqlchemy.Equals(storages.Field("zone_id"), zones.Field("id")))
subq = subq.Filter(sqlchemy.Equals(storagecachedImages.Field("status"), api.CACHED_IMAGE_STATUS_READY))
subq = subq.Filter(sqlchemy.Equals(storagecachedImages.Field("status"), api.CACHED_IMAGE_STATUS_ACTIVE))
return subq
})
if err != nil {
@@ -682,7 +717,7 @@ func (manager *SCachedimageManager) ListItemFilter(
subq := storagecachedImages.Query(storagecachedImages.Field("cachedimage_id"))
subq = subq.Join(storageCaches, sqlchemy.Equals(storagecachedImages.Field("storagecache_id"), storageCaches.Field("id")))
subq = subq.Join(storages, sqlchemy.Equals(storageCaches.Field("id"), storages.Field("storagecache_id")))
subq = subq.Filter(sqlchemy.Equals(storagecachedImages.Field("status"), api.CACHED_IMAGE_STATUS_READY))
subq = subq.Filter(sqlchemy.Equals(storagecachedImages.Field("status"), api.CACHED_IMAGE_STATUS_ACTIVE))
return subq
})
if err != nil {
@@ -704,9 +739,9 @@ func (manager *SCachedimageManager) OrderByExtraFields(
) (*sqlchemy.SQuery, error) {
var err error
q, err = manager.SStandaloneResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.StandaloneResourceListInput)
q, err = manager.SSharableVirtualResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.SharableVirtualResourceListInput)
if err != nil {
return nil, errors.Wrap(err, "SStandaloneResourceBaseManager.OrderByExtraFields")
return nil, errors.Wrap(err, "SSharableVirtualResourceBaseManager.OrderByExtraFields")
}
return q, nil
@@ -715,10 +750,44 @@ func (manager *SCachedimageManager) OrderByExtraFields(
func (manager *SCachedimageManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
var err error
q, err = manager.SStandaloneResourceBaseManager.QueryDistinctExtraField(q, field)
q, err = manager.SSharableVirtualResourceBaseManager.QueryDistinctExtraField(q, field)
if err == nil {
return q, nil
}
return q, httperrors.ErrNotFound
}
func (manager *SCachedimageManager) ListItemExportKeys(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, keys stringutils2.SSortedStrings) (*sqlchemy.SQuery, error) {
q, err := manager.SSharableVirtualResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
if err != nil {
return nil, errors.Wrapf(err, "SSharableVirtualResourceBaseManager.L.ListItemExportKeys")
}
return q, nil
}
func (manager *SCachedimageManager) InitializeData() error {
images := []SCachedimage{}
q := manager.Query().IsNullOrEmpty("tenant_id")
err := db.FetchModelObjects(manager, q, &images)
if err != nil {
return errors.Wrapf(err, "db.FetchModelObjects")
}
for i := range images {
_, err := db.Update(&images[i], func() error {
images[i].IsPublic = true
images[i].PublicScope = string(rbacutils.ScopeSystem)
images[i].ProjectId = "system"
if len(images[i].ExternalId) > 0 {
images[i].Status = api.CACHED_IMAGE_STATUS_ACTIVE
} else {
images[i].Status = images[i].GetStatus()
}
return nil
})
if err != nil {
return errors.Wrapf(err, "db.Update(%s)", images[i].Id)
}
}
return nil
}

View File

@@ -48,6 +48,7 @@ import (
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/multicloud/esxi"
"yunion.io/x/onecloud/pkg/multicloud/esxi/vcenter"
"yunion.io/x/onecloud/pkg/util/choices"
"yunion.io/x/onecloud/pkg/util/httputils"
@@ -417,9 +418,11 @@ func (scm *SCloudaccountManager) PerformPrepareNets(ctx context.Context, userCre
if err != nil {
return output, errors.Wrap(err, "provider.GetOnPremiseIRegion")
}
hosts, err := iregion.GetIHosts()
// hack
client := iregion.(*esxi.SESXiClient)
hostIps, simpleVms, err := client.HostVmIPs(ctx)
if err != nil {
return output, errors.Wrap(err, "unable to get hosts")
return output, errors.Wrap(err, "unable to fetch ips of hosts and vms")
}
// fetch networks
networks := make([][]SNetwork, len(wires))
@@ -430,20 +433,15 @@ func (scm *SCloudaccountManager) PerformPrepareNets(ctx context.Context, userCre
}
networks[i] = nets
}
// fetch host ips
// key of ipHosts is host's ip
ipHosts := make(map[netutils.IPV4Addr]cloudprovider.ICloudHost, len(hosts))
for i := range hosts {
ip := hosts[i].GetAccessIp()
if len(ip) == 0 {
log.Errorf("unable to get accessip of host %q", hosts[i].GetName())
continue
}
ipHosts := make(map[netutils.IPV4Addr]string, len(hostIps))
for name, ip := range hostIps {
addr, err := netutils.NewIPV4Addr(ip)
if err != nil {
return output, err
}
ipHosts[addr] = hosts[i]
ipHosts[addr] = name
}
// Find suitable wire and the network containing the Host IP in suitable wire.
var (
@@ -490,15 +488,15 @@ func (scm *SCloudaccountManager) PerformPrepareNets(ctx context.Context, userCre
// Give the suggested network configuration for the Host IP that does not have a corresponding suitable network.
noNetHostIP := make([]netutils.IPV4Addr, 0, len(ipHosts))
for hip, host := range ipHosts {
for ip, name := range ipHosts {
rnet := api.CAHostNet{
Name: host.GetName(),
IP: host.GetAccessIp(),
Name: name,
IP: ip.String(),
}
if net, ok := suitableNetworks[hip]; ok {
if net, ok := suitableNetworks[ip]; ok {
rnet.SuitableNetwork = net.GetId()
} else {
noNetHostIP = append(noNetHostIP, hip)
noNetHostIP = append(noNetHostIP, ip)
}
output.Hosts = append(output.Hosts, rnet)
}
@@ -515,7 +513,7 @@ func (scm *SCloudaccountManager) PerformPrepareNets(ctx context.Context, userCre
// Find the suitable network containing the VM IP in Project 'input.Project', and if not, give the corresponding suggested network configuration in this project.
project := input.Project
nets := []*SNetwork{}
excludeNets := []*SNetwork{}
var allNets []SNetwork
if suitableWire != nil {
allNets, err = suitableWire.getNetworks(userCred, rbacutils.ScopeSystem)
@@ -524,85 +522,161 @@ func (scm *SCloudaccountManager) PerformPrepareNets(ctx context.Context, userCre
}
for i := range allNets {
if allNets[i].ProjectId == project {
nets = append(nets, &allNets[i])
excludeNets = append(excludeNets, &allNets[i])
}
}
}
// find suitable network
vms := make([]cloudprovider.ICloudVM, 0, len(hosts))
for _, host := range hosts {
vs, err := host.GetIVMs()
if err != nil {
return output, errors.Wrapf(err, "unable to get VMs of host %q", host.GetName())
}
vms = append(vms, vs...)
type vm struct {
FakeID int
IP netutils.IPV4Addr
Name string
}
ipVMs := make(map[netutils.IPV4Addr]int, len(vms))
for i, vm := range vms {
nics, err := vm.GetINics()
if err != nil {
return output, errors.Wrapf(err, "unable get nics of vm %q", vm.GetName())
}
for _, nic := range nics {
ipStr := nic.GetIP()
if len(ipStr) == 0 {
continue
}
ip, err := netutils.NewIPV4Addr(ipStr)
if err != nil {
return output, errors.Wrapf(err, "unable to new IPV4Addr for ip %q", nic.GetIP())
}
ipVMs[ip] = i
}
output.Guests = append(output.Guests, api.CAGuestNet{
Name: vm.GetName(),
IPNets: make([]api.CAIPNet, 0, 1),
})
}
suitableNetworks = make(map[netutils.IPV4Addr]*SNetwork)
if len(nets) != 0 {
for vip := range ipVMs {
for i := range nets {
ipRange := nets[i].GetIPRange()
if !ipRange.Contains(vip) {
continue
vms := make([]vm, 0, len(simpleVms))
var nip netutils.IPV4Addr
guestMap := make(map[int]*api.CAGuestNet)
for i := range simpleVms {
id := i
if len(simpleVms[i].IPs) == 0 {
if _, ok := guestMap[id]; !ok {
guestMap[id] = &api.CAGuestNet{
Name: simpleVms[i].Name,
IPNets: []api.CAIPNet{},
}
suitableNetworks[vip] = nets[i]
break
}
}
}
noNetVMIPs := make([]netutils.IPV4Addr, 0, len(ipVMs))
for vip, i := range ipVMs {
ipnet := api.CAIPNet{
IP: vip.String(),
for _, ip := range simpleVms[i].IPs {
nip, err = netutils.NewIPV4Addr(ip)
if err != nil {
return output, err
}
vms = append(vms, vm{
FakeID: i,
IP: nip,
Name: simpleVms[i].Name,
})
}
if net, ok := suitableNetworks[vip]; ok {
ipnet.SuitableNetwork = net.GetId()
} else {
noNetVMIPs = append(noNetVMIPs, vip)
}
output.Guests[i].IPNets = append(output.Guests[ipVMs[vip]].IPNets, ipnet)
}
// sort vms via vm's ip
sort.Slice(vms, func(i, j int) bool {
return vms[i].IP < vms[j].IP
})
// excludedIRs is to prevent network conflicts
excludedIRs := make([]netutils.IPV4AddrRange, len(allNets))
for i := range excludedIRs {
excludedIRs[i] = allNets[i].GetIPRange()
excludeNets = make([]*SNetwork, 0, len(allNets)+len(output.HostSuggestedNetworks))
for i := range allNets {
excludeNets = append(excludeNets, &allNets[i])
}
for i := range output.HostSuggestedNetworks {
startIPStr := output.HostSuggestedNetworks[i].GuestIpStart
endIPStr := output.HostSuggestedNetworks[i].GuestIpEnd
startIP, _ := netutils.NewIPV4Addr(startIPStr)
endIP, _ := netutils.NewIPV4Addr(endIPStr)
excludedIRs = append(excludedIRs, netutils.NewIPV4AddrRange(startIP, endIP))
startipStr := output.HostSuggestedNetworks[i].GuestIpStart
endipStr := output.HostSuggestedNetworks[i].GuestIpEnd
excludeNets = append(excludeNets, &SNetwork{GuestIpEnd: endipStr, GuestIpStart: startipStr})
}
if len(noNetVMIPs) > 0 {
sConfs := scm.suggestVMNetwors(noNetVMIPs, excludedIRs)
confs := make([]api.CANetConf, len(sConfs))
// sort excludeNets via their GuestIpStart
sort.Slice(excludeNets, func(i, j int) bool {
return excludeNets[i].GuestIpStart < excludeNets[j].GuestIpStart
})
svNets := make([]netutils.IPV4AddrRange, 0, 5)
var vmi, neti int
lastEndIp := netutils.IPV4Addr(0)
Loop:
for neti = 0; neti < len(excludeNets); {
startIp, _ := netutils.NewIPV4Addr(excludeNets[neti].GuestIpStart)
endIp, _ := netutils.NewIPV4Addr(excludeNets[neti].GuestIpEnd)
switch {
case vms[vmi].IP > endIp:
lastEndIp = endIp
neti++
case vms[vmi].IP >= startIp:
for vms[vmi].IP <= endIp {
id := vms[vmi].FakeID
if _, ok := guestMap[id]; !ok {
guestMap[id] = &api.CAGuestNet{
Name: vms[vmi].Name,
IPNets: []api.CAIPNet{},
}
}
guestMap[id].IPNets = append(guestMap[id].IPNets, api.CAIPNet{
IP: vms[vmi].IP.String(),
SuitableNetwork: excludeNets[neti].Id,
})
vmi += 1
if vmi == len(vms) {
break Loop
}
}
lastEndIp = endIp
neti++
default:
for vms[vmi].IP < startIp {
suggestStartIp := vms[vmi].IP.NetAddr(24) + 1
if suggestStartIp <= lastEndIp {
suggestStartIp = lastEndIp + 1
}
if suggestStartIp >= startIp {
break
}
suggestEndIp := suggestStartIp.NetAddr(24) + 255
if suggestEndIp >= startIp {
suggestEndIp = startIp - 1
}
svNets = append(svNets, netutils.NewIPV4AddrRange(suggestStartIp, suggestEndIp))
for vmi < len(vms) && vms[vmi].IP <= suggestEndIp {
id := vms[vmi].FakeID
if _, ok := guestMap[id]; !ok {
guestMap[id] = &api.CAGuestNet{
Name: vms[vmi].Name,
IPNets: []api.CAIPNet{},
}
}
guestMap[id].IPNets = append(guestMap[id].IPNets, api.CAIPNet{
IP: vms[vmi].IP.String(),
})
vmi++
}
if vmi == len(vms) {
break Loop
}
}
}
}
for vmi < len(vms) {
suggestStartIp := vms[vmi].IP.NetAddr(24) + 1
if suggestStartIp <= lastEndIp {
suggestStartIp = lastEndIp + 1
}
suggestEndIp := suggestStartIp.NetAddr(24) + 255
svNets = append(svNets, netutils.NewIPV4AddrRange(suggestStartIp, suggestEndIp))
for vmi < len(vms) && vms[vmi].IP <= suggestEndIp {
id := vms[vmi].FakeID
if _, ok := guestMap[id]; !ok {
guestMap[id] = &api.CAGuestNet{
Name: vms[vmi].Name,
IPNets: []api.CAIPNet{},
}
}
guestMap[id].IPNets = append(guestMap[id].IPNets, api.CAIPNet{
IP: vms[vmi].IP.String(),
})
vmi++
}
}
for _, guest := range guestMap {
output.Guests = append(output.Guests, *guest)
}
if len(svNets) > 0 {
confs := make([]api.CANetConf, len(svNets))
for i := range confs {
confs[i].CASimpleNetConf = sConfs[i]
confs[i].CASimpleNetConf = api.CASimpleNetConf{
GuestIpStart: svNets[i].StartIp().String(),
GuestIpEnd: svNets[i].EndIp().String(),
GuestIpMask: 24,
GuestGateway: (svNets[i].StartIp().NetAddr(24) + 1).String(),
}
confs[i].Name = fmt.Sprintf("%s-guest-network-%d", input.Name, i+1)
}
output.GuestSuggestedNetworks = confs

View File

@@ -1394,8 +1394,7 @@ func (self *SCloudprovider) StartCloudproviderDeleteTask(ctx context.Context, us
params := jsonutils.NewDict()
task, err := taskman.TaskManager.NewTask(ctx, "CloudProviderDeleteTask", self, userCred, params, parentTaskId, "", nil)
if err != nil {
log.Errorf("%s", err)
return err
return errors.Wrapf(err, "NewTask")
}
self.SetStatus(userCred, api.CLOUD_PROVIDER_START_DELETE, "StartCloudproviderDeleteTask")
task.ScheduleRun(nil)

View File

@@ -426,8 +426,11 @@ func (self *SElasticip) SyncInstanceWithCloudEip(ctx context.Context, userCred m
case api.EIP_ASSOCIATE_TYPE_SERVER:
sq := HostManager.Query().SubQuery()
return q.Join(sq, sqlchemy.Equals(sq.Field("id"), q.Field("host_id"))).Filter(sqlchemy.Equals(sq.Field("manager_id"), self.ManagerId))
case api.EIP_ASSOCIATE_TYPE_NAT_GATEWAY, api.EIP_ASSOCIATE_TYPE_LOADBALANCER:
case api.EIP_ASSOCIATE_TYPE_LOADBALANCER:
return q.Equals("manager_id", self.ManagerId)
case api.EIP_ASSOCIATE_TYPE_NAT_GATEWAY:
sq := VpcManager.Query("id").Equals("manager_id", self.ManagerId)
return q.In("vpc_id", sq.SubQuery())
}
return q
})
@@ -1266,6 +1269,7 @@ func (manager *SElasticipManager) NewEipForVMOnHost(ctx context.Context, userCre
wireq := WireManager.Query().SubQuery()
hostwireq := HostwireManager.Query().SubQuery()
q := NetworkManager.Query()
q = NetworkManager.FilterByOwner(q, userCred, NetworkManager.NamespaceScope())
q = q.Join(wireq, sqlchemy.Equals(wireq.Field("id"), q.Field("wire_id")))
q = q.Join(hostwireq, sqlchemy.Equals(hostwireq.Field("wire_id"), wireq.Field("id")))
q = q.Join(hostq, sqlchemy.Equals(hostq.Field("id"), host.Id))

View File

@@ -3635,9 +3635,11 @@ func (self *SGuest) SaveRenewInfo(
guestdisks := self.GetDisks()
for i := 0; i < len(guestdisks); i += 1 {
disk := guestdisks[i].GetDisk()
err = disk.SaveRenewInfo(ctx, userCred, bc, expireAt, billingType)
if err != nil {
return err
if disk.AutoDelete {
err = disk.SaveRenewInfo(ctx, userCred, bc, expireAt, billingType)
if err != nil {
return err
}
}
}
return nil

View File

@@ -142,6 +142,8 @@ type IGuestDriver interface {
IsRebuildRootSupportChangeImage() bool
IsRebuildRootSupportChangeUEFI() bool
IsSupportdDcryptPasswordFromSecretKey() bool
RequestDeleteDetachedDisk(ctx context.Context, disk *SDisk, task taskman.ITask, isPurge bool) error
StartGuestDetachdiskTask(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, params *jsonutils.JSONDict, parentTaskId string) error
StartGuestAttachDiskTask(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, params *jsonutils.JSONDict, parentTaskId string) error

View File

@@ -4234,6 +4234,14 @@ func (self *SGuest) GetShortDesc(ctx context.Context) *jsonutils.JSONDict {
billingInfo.SCloudProviderInfo = host.getCloudProviderInfo()
}
if len(self.BackupHostId) > 0 {
backupHost := HostManager.FetchHostById(self.BackupHostId)
if backupHost != nil {
desc.Set("backup_host", jsonutils.NewString(backupHost.Name))
desc.Set("backup_host_id", jsonutils.NewString(backupHost.Id))
}
}
if priceKey := self.GetMetadata("ext:price_key", nil); len(priceKey) > 0 {
billingInfo.PriceKey = priceKey
}
@@ -4257,40 +4265,49 @@ func (self *SGuest) saveOsType(userCred mcclient.TokenCredential, osType string)
return err
}
type sDeployInfo struct {
Os string
Account string
Key string
Distro string
Version string
Arch string
Language string
}
func (self *SGuest) SaveDeployInfo(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject) {
deployInfo := sDeployInfo{}
data.Unmarshal(&deployInfo)
info := make(map[string]interface{})
if data.Contains("os") {
osName, _ := data.GetString("os")
self.saveOsType(userCred, osName)
info["os_name"] = osName
if len(deployInfo.Os) > 0 {
self.saveOsType(userCred, deployInfo.Os)
info["os_name"] = deployInfo.Os
}
if data.Contains("account") {
account, _ := data.GetString("account")
info["login_account"] = account
if data.Contains("key") {
key, _ := data.GetString("key")
info["login_key"] = key
driver := self.GetDriver()
if len(deployInfo.Account) > 0 {
info["login_account"] = deployInfo.Account
if len(deployInfo.Key) > 0 {
info["login_key"] = deployInfo.Key
if len(self.KeypairId) > 0 && !driver.IsSupportdDcryptPasswordFromSecretKey() { // Tencent Cloud does not support simultaneous setting of secret keys and passwords
info["login_key"], _ = seclib2.EncryptBase64(self.GetKeypairPublicKey(), "")
}
info["login_key_timestamp"] = timeutils.UtcNow()
} else {
info["login_key"] = "none"
info["login_key_timestamp"] = "none"
}
}
if data.Contains("distro") {
dist, _ := data.GetString("distro")
info["os_distribution"] = dist
if len(deployInfo.Distro) > 0 {
info["os_distribution"] = deployInfo.Distro
}
if data.Contains("version") {
ver, _ := data.GetString("version")
info["os_version"] = ver
if len(deployInfo.Version) > 0 {
info["os_version"] = deployInfo.Version
}
if data.Contains("arch") {
arch, _ := data.GetString("arch")
info["os_arch"] = arch
if len(deployInfo.Arch) > 0 {
info["os_arch"] = deployInfo.Arch
}
if data.Contains("language") {
lang, _ := data.GetString("language")
info["os_language"] = lang
if len(deployInfo.Language) > 0 {
info["os_language"] = deployInfo.Language
}
self.SetAllMetadata(ctx, info, userCred)
self.saveOldPassword(ctx, userCred)

View File

@@ -5450,3 +5450,15 @@ func (manager *SHostManager) ListItemExportKeys(ctx context.Context,
}
return q, nil
}
func (manager *SHostManager) FetchHostByExtId(extid string) *SHost {
host := SHost{}
host.SetModelManager(manager, &host)
err := manager.Query().Equals("external_id", extid).First(&host)
if err != nil {
log.Errorf("fetchHostByExtId fail %s", err)
return nil
} else {
return &host
}
}

View File

@@ -60,6 +60,8 @@ func InitDB() error {
ScheduledTaskActivityManager,
ExternalProjectManager,
CachedimageManager,
StoragecachedimageManager,
} {
err := manager.InitializeData()
if err != nil {

View File

@@ -355,6 +355,39 @@ func (self *SSecurityGroupCache) GetSecgroup() (*SSecurityGroup, error) {
return model.(*SSecurityGroup), nil
}
func (self *SSecurityGroupCache) syncWithCloudSecurityGroup(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, ext cloudprovider.ICloudSecurityGroup) error {
_, err := db.Update(self, func() error {
self.Status = api.SECGROUP_CACHE_STATUS_READY
self.Name = ext.GetName()
self.Description = ext.GetDescription()
self.ExternalProjectId = ext.GetProjectId()
return nil
})
if err != nil {
return errors.Wrapf(err, "db.Update")
}
secgroup, err := self.GetSecgroup()
if err != nil {
return errors.Wrapf(err, "GetSecurity")
}
cacheCount, err := secgroup.GetSecgroupCacheCount()
if err != nil {
return errors.Wrapf(err, "GetSecgroupCacheCount")
}
if cacheCount > 1 {
return nil
}
info, err := SecurityGroupManager.getRuleInfo(provider, ext)
if err != nil {
return errors.Wrapf(err, "getRuleInfo")
}
err = secgroup.SyncSecurityGroupRules(ctx, userCred, info)
if err != nil {
return errors.Wrapf(err, "SyncSecurityGroupRules")
}
return nil
}
func (manager *SSecurityGroupCacheManager) SyncSecurityGroupCaches(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, secgroups []cloudprovider.ICloudSecurityGroup, vpc *SVpc) ([]SSecurityGroup, []cloudprovider.ICloudSecurityGroup, compare.SyncResult) {
lockman.LockClass(ctx, manager, db.GetLockClassKey(manager, userCred))
defer lockman.ReleaseClass(ctx, manager, db.GetLockClassKey(manager, userCred))
@@ -415,25 +448,18 @@ func (manager *SSecurityGroupCacheManager) SyncSecurityGroupCaches(ctx context.C
}
for i := 0; i < len(commondb); i++ {
_, err = db.Update(&commondb[i], func() error {
commondb[i].Status = api.SECGROUP_CACHE_STATUS_READY
commondb[i].Name = commonext[i].GetName()
commondb[i].Description = commonext[i].GetDescription()
commondb[i].ExternalProjectId = commonext[i].GetProjectId()
return nil
})
err = commondb[i].syncWithCloudSecurityGroup(ctx, userCred, provider, commonext[i])
if err != nil {
syncResult.UpdateError(err)
} else {
syncResult.Update()
syncResult.UpdateError(errors.Wrapf(err, "syncWithCloudSecurityGroup"))
continue
}
syncResult.Update()
}
//相同的不能同步, 原因: 多个平台的安全组可能共用一个本地安全组,下面仅仅是新加的安全组
for i := 0; i < len(added); i++ {
secgroup, err := SecurityGroupManager.newFromCloudSecgroup(ctx, userCred, provider, added[i])
if err != nil {
syncResult.AddError(err)
syncResult.AddError(errors.Wrapf(err, "newFromCloudSecgroup"))
continue
}
if secgroup.ProjectId != provider.ProjectId {
@@ -450,7 +476,7 @@ func (manager *SSecurityGroupCacheManager) SyncSecurityGroupCaches(ctx context.C
}
cache, err := manager.NewCache(ctx, userCred, secgroup.Id, vpcId, vpc.CloudregionId, provider.Id, added[i].GetProjectId())
if err != nil {
syncResult.AddError(fmt.Errorf("failed to create secgroup cache for secgroup %s(%s) provider: %s: %s", secgroup.Name, secgroup.Name, provider.Name, err))
syncResult.AddError(errors.Wrapf(err, "NewCache for secgroup %s provider %s", secgroup.Name, provider.Name))
continue
}
_, err = db.Update(cache, func() error {
@@ -461,7 +487,7 @@ func (manager *SSecurityGroupCacheManager) SyncSecurityGroupCaches(ctx context.C
return nil
})
if err != nil {
syncResult.AddError(err)
syncResult.AddError(errors.Wrapf(err, "db.Update"))
continue
}
localSecgroups = append(localSecgroups, *secgroup)
@@ -560,3 +586,20 @@ func (manager *SSecurityGroupCacheManager) ListItemExportKeys(ctx context.Contex
return q, nil
}
func (self *SSecurityGroupCache) GetISecurityGroup() (cloudprovider.ICloudSecurityGroup, error) {
if len(self.ExternalId) == 0 {
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "empty externalId")
}
manager := self.GetCloudprovider()
if manager == nil {
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "failed to found manager")
}
iRegion, err := self.GetIRegion()
if err != nil {
return nil, errors.Wrapf(err, "GetIRegion")
}
return iRegion.GetISecurityGroupById(self.ExternalId)
}

View File

@@ -22,7 +22,6 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/compare"
"yunion.io/x/pkg/util/regutils"
"yunion.io/x/pkg/util/secrules"
"yunion.io/x/pkg/util/stringutils"
@@ -462,8 +461,7 @@ func (manager *SSecurityGroupRuleManager) getRulesBySecurityGroup(secgroup *SSec
return rules, nil
}
func (manager *SSecurityGroupRuleManager) SyncRules(ctx context.Context, userCred mcclient.TokenCredential, secgroup *SSecurityGroup, rules cloudprovider.SecurityRuleSet) compare.SyncResult {
syncResult := compare.SyncResult{}
func (self *SSecurityGroup) SyncRules(ctx context.Context, userCred mcclient.TokenCredential, rules cloudprovider.SecurityRuleSet) error {
priority, prePriority := 10, 0
for i := 0; i < len(rules); i++ {
// 这里避免了Rule规则优先级在 1-100之外的问题,ext.GetRules()不需要进行优先级转换
@@ -472,19 +470,17 @@ func (manager *SSecurityGroupRuleManager) SyncRules(ctx context.Context, userCre
}
prePriority = rules[i].Priority
rules[i].Priority = priority
_, err := manager.newFromCloudSecurityGroup(ctx, userCred, rules[i], secgroup)
_, err := self.newFromCloudSecurityGroupRule(ctx, userCred, rules[i])
if err != nil {
syncResult.AddError(err)
continue
return errors.Wrapf(err, "newFromCloudSecurityGroupRule")
}
syncResult.Add()
}
return syncResult
return nil
}
func (manager *SSecurityGroupRuleManager) newFromCloudSecurityGroup(ctx context.Context, userCred mcclient.TokenCredential, rule cloudprovider.SecurityRule, secgroup *SSecurityGroup) (*SSecurityGroupRule, error) {
lockman.LockClass(ctx, manager, db.GetLockClassKey(manager, userCred))
defer lockman.ReleaseClass(ctx, manager, db.GetLockClassKey(manager, userCred))
func (self *SSecurityGroup) newFromCloudSecurityGroupRule(ctx context.Context, userCred mcclient.TokenCredential, rule cloudprovider.SecurityRule) (*SSecurityGroupRule, error) {
lockman.LockObject(ctx, self)
defer lockman.ReleaseObject(ctx, self)
protocol := rule.Protocol
if len(protocol) == 0 {
@@ -505,11 +501,11 @@ func (manager *SSecurityGroupRuleManager) newFromCloudSecurityGroup(ctx context.
Action: string(rule.Action),
Description: rule.Description,
}
secrule.SecgroupId = secgroup.Id
secrule.SecgroupId = self.Id
err := manager.TableSpec().Insert(ctx, secrule)
err := SecurityGroupRuleManager.TableSpec().Insert(ctx, secrule)
if err != nil {
return nil, err
return nil, errors.Wrapf(err, "SecurityGroupRuleManager.Insert")
}
return secrule, nil
}

View File

@@ -37,6 +37,7 @@ import (
"yunion.io/x/onecloud/pkg/cloudcommon/policy"
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/options"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/auth"
@@ -539,6 +540,14 @@ func totalSecurityGroupCount(scope rbacutils.TRbacScope, ownerId mcclient.IIdent
return q.CountWithError()
}
func (self *SSecurityGroup) AllowPerformPurge(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "purge")
}
func (self *SSecurityGroup) PerformPurge(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
return nil, self.StartDeleteSecurityGroupTask(ctx, userCred, true, "")
}
func (self *SSecurityGroup) AllowPerformUncacheSecgroup(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "uncache-secgroup")
}
@@ -821,7 +830,57 @@ func (manager *SSecurityGroupManager) getSecurityGroups() ([]SSecurityGroup, err
}
}
func (manager *SSecurityGroupManager) newFromCloudSecgroup(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, extSec cloudprovider.ICloudSecurityGroup) (*SSecurityGroup, error) {
func (self *SSecurityGroup) cleanRules(ctx context.Context, userCred mcclient.TokenCredential) error {
rules := []SSecurityGroupRule{}
q := SecurityGroupRuleManager.Query().Equals("secgroup_id", self.Id)
err := db.FetchModelObjects(SecurityGroupRuleManager, q, &rules)
if err != nil {
return errors.Wrapf(err, "db.FetchModelObjects")
}
for i := range rules {
err = rules[i].Delete(ctx, userCred)
if err != nil {
return errors.Wrapf(err, "DeleteRule(%s)", rules[i].Id)
}
}
return nil
}
func (self *SSecurityGroup) SyncSecurityGroupRules(ctx context.Context, userCred mcclient.TokenCredential, info *sRuleInfo) error {
inRules := cloudprovider.AddDefaultRule(info.inRules, info.defaultInRule, "in:deny any", info.order, info.minPriority, info.maxPriority, info.onlyAllowRules)
cloudprovider.SortSecurityRule(inRules, info.order, info.onlyAllowRules)
outRules := cloudprovider.AddDefaultRule(info.outRules, info.defaultOutRule, "out:allow any", info.order, info.minPriority, info.maxPriority, info.onlyAllowRules)
cloudprovider.SortSecurityRule(outRules, info.order, info.onlyAllowRules)
err := self.cleanRules(ctx, userCred)
if err != nil {
return errors.Wrapf(err, "cleanRules")
}
err = self.SyncRules(ctx, userCred, inRules)
if err != nil {
return errors.Wrapf(err, "SyncInRules")
}
err = self.SyncRules(ctx, userCred, outRules)
if err != nil {
return errors.Wrapf(err, "SyncOutRules")
}
return nil
}
type sRuleInfo struct {
rules []cloudprovider.SecurityRule
inRules []cloudprovider.SecurityRule
outRules []cloudprovider.SecurityRule
defaultInRule cloudprovider.SecurityRule
defaultOutRule cloudprovider.SecurityRule
order cloudprovider.TPriorityOrder
onlyAllowRules bool
maxPriority int
minPriority int
}
func (manager *SSecurityGroupManager) getRuleInfo(provider *SCloudprovider, extSec cloudprovider.ICloudSecurityGroup) (*sRuleInfo, error) {
regionDriver, err := provider.GetRegionDriver()
if err != nil {
return nil, errors.Wrap(err, "provider.GetRegionDriver")
@@ -832,36 +891,48 @@ func (manager *SSecurityGroupManager) newFromCloudSecgroup(ctx context.Context,
return nil, errors.Wrap(err, "extSec.GetRules")
}
inRules := []cloudprovider.SecurityRule{}
outRules := []cloudprovider.SecurityRule{}
info := &sRuleInfo{
rules: rules,
inRules: []cloudprovider.SecurityRule{},
outRules: []cloudprovider.SecurityRule{},
defaultInRule: regionDriver.GetDefaultSecurityGroupInRule(),
defaultOutRule: regionDriver.GetDefaultSecurityGroupOutRule(),
order: regionDriver.GetSecurityGroupRuleOrder(),
onlyAllowRules: regionDriver.IsOnlySupportAllowRules(),
maxPriority: regionDriver.GetSecurityGroupRuleMaxPriority(),
minPriority: regionDriver.GetSecurityGroupRuleMinPriority(),
}
for i := range rules {
if rules[i].Direction == secrules.DIR_IN {
inRules = append(inRules, rules[i])
info.inRules = append(info.inRules, rules[i])
} else {
outRules = append(outRules, rules[i])
info.outRules = append(info.outRules, rules[i])
}
}
return info, nil
}
maxPriority := regionDriver.GetSecurityGroupRuleMaxPriority()
minPriority := regionDriver.GetSecurityGroupRuleMinPriority()
defaultInRule := regionDriver.GetDefaultSecurityGroupInRule()
defaultOutRule := regionDriver.GetDefaultSecurityGroupOutRule()
order := regionDriver.GetSecurityGroupRuleOrder()
onlyAllowRules := regionDriver.IsOnlySupportAllowRules()
// 查询与provider在同域的安全组比对寻找一个与云上安全组规则相同的安全组
secgroups := []SSecurityGroup{}
q := manager.Query().Equals("domain_id", provider.DomainId)
err = db.FetchModelObjects(manager, q, &secgroups)
func (manager *SSecurityGroupManager) newFromCloudSecgroup(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, extSec cloudprovider.ICloudSecurityGroup) (*SSecurityGroup, error) {
info, err := manager.getRuleInfo(provider, extSec)
if err != nil {
return nil, errors.Wrap(err, "db.FetchModelObjects")
return nil, errors.Wrapf(err, "getRuleInfo")
}
for i := range secgroups {
localRules := secrules.SecurityRuleSet(secgroups[i].GetSecRules(""))
_, inAdds, outAdds, inDels, outDels := cloudprovider.CompareRules(minPriority, maxPriority, order, localRules, rules, defaultInRule, defaultOutRule, onlyAllowRules, false)
if len(inAdds) == 0 && len(outAdds) == 0 && len(inDels) == 0 && len(outDels) == 0 {
return &secgroups[i], nil
if options.Options.EnableAutoMergeSecurityGroup {
// 查询与provider在同域的安全组比对寻找一个与云上安全组规则相同的安全组
secgroups := []SSecurityGroup{}
q := manager.Query().Equals("domain_id", provider.DomainId)
err = db.FetchModelObjects(manager, q, &secgroups)
if err != nil {
return nil, errors.Wrap(err, "db.FetchModelObjects")
}
for i := range secgroups {
localRules := secrules.SecurityRuleSet(secgroups[i].GetSecRules(""))
_, inAdds, outAdds, inDels, outDels := cloudprovider.CompareRules(info.minPriority, info.maxPriority, info.order, localRules, info.rules, info.defaultInRule, info.defaultOutRule, info.onlyAllowRules, false)
if len(inAdds) == 0 && len(outAdds) == 0 && len(inDels) == 0 && len(outDels) == 0 {
return &secgroups[i], nil
}
}
}
@@ -870,31 +941,26 @@ func (manager *SSecurityGroupManager) newFromCloudSecgroup(ctx context.Context,
secgroup := SSecurityGroup{}
secgroup.SetModelManager(manager, &secgroup)
newName, err := db.GenerateName(manager, userCred, extSec.GetName())
secgroup.Name, err = db.GenerateName(manager, userCred, extSec.GetName())
if err != nil {
return nil, err
}
secgroup.Name = newName
secgroup.Description = extSec.GetDescription()
secgroup.ProjectId = provider.ProjectId
secgroup.DomainId = provider.DomainId
if err := manager.TableSpec().Insert(ctx, &secgroup); err != nil {
return nil, err
err = manager.TableSpec().Insert(ctx, &secgroup)
if err != nil {
return nil, errors.Wrapf(err, "Insert")
}
//这里必须先同步下规则,不然下次对比此安全组规则为空
inRules = cloudprovider.AddDefaultRule(inRules, defaultInRule, "in:deny any", order, minPriority, maxPriority, onlyAllowRules)
cloudprovider.SortSecurityRule(inRules, order, onlyAllowRules)
outRules = cloudprovider.AddDefaultRule(outRules, defaultOutRule, "out:allow any", order, minPriority, maxPriority, onlyAllowRules)
cloudprovider.SortSecurityRule(outRules, order, onlyAllowRules)
SecurityGroupRuleManager.SyncRules(ctx, userCred, &secgroup, inRules)
SecurityGroupRuleManager.SyncRules(ctx, userCred, &secgroup, outRules)
err = secgroup.SyncSecurityGroupRules(ctx, userCred, info)
if err != nil {
return nil, errors.Wrapf(err, "SyncSecurityGroupRules")
}
db.OpsLog.LogEvent(&secgroup, db.ACT_CREATE, secgroup.GetShortDesc(ctx), userCred)
return &secgroup, nil
}
@@ -1035,10 +1101,12 @@ func (self *SSecurityGroup) GetSecurityGroupCaches() []SSecurityGroupCache {
}
func (self *SSecurityGroup) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
return self.StartDeleteSecurityGroupTask(ctx, userCred, jsonutils.NewDict(), "")
return self.StartDeleteSecurityGroupTask(ctx, userCred, false, "")
}
func (self *SSecurityGroup) StartDeleteSecurityGroupTask(ctx context.Context, userCred mcclient.TokenCredential, params *jsonutils.JSONDict, parentTaskId string) error {
func (self *SSecurityGroup) StartDeleteSecurityGroupTask(ctx context.Context, userCred mcclient.TokenCredential, isPurge bool, parentTaskId string) error {
params := jsonutils.NewDict()
params.Add(jsonutils.NewBool(isPurge), "purge")
self.SetStatus(userCred, api.SECGROUP_STATUS_DELETING, "")
task, err := taskman.TaskManager.NewTask(ctx, "SecurityGroupDeleteTask", self, userCred, params, parentTaskId, "", nil)
if err != nil {

View File

@@ -331,7 +331,7 @@ func (self *SStoragecachedimage) markDeleting(ctx context.Context, userCred mccl
}
if !isForce && !utils.IsInStringArray(self.Status,
[]string{api.CACHED_IMAGE_STATUS_READY, api.CACHED_IMAGE_STATUS_DELETING, api.CACHED_IMAGE_STATUS_CACHE_FAILED}) {
[]string{api.CACHED_IMAGE_STATUS_ACTIVE, api.CACHED_IMAGE_STATUS_DELETING, api.CACHED_IMAGE_STATUS_CACHE_FAILED}) {
return httperrors.NewInvalidStatusError("Cannot uncache in status %s", self.Status)
}
_, err = db.Update(self, func() error {
@@ -439,17 +439,17 @@ func (self *SStoragecachedimage) syncRemoveCloudImage(ctx context.Context, userC
return nil
}
func (self *SStoragecachedimage) syncWithCloudImage(ctx context.Context, userCred mcclient.TokenCredential, image cloudprovider.ICloudImage) error {
func (self *SStoragecachedimage) syncWithCloudImage(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, image cloudprovider.ICloudImage, managerId string) error {
cachedImage := self.GetCachedimage()
if len(cachedImage.ExternalId) > 0 {
self.SetStatus(userCred, image.GetStatus(), "")
return cachedImage.syncWithCloudImage(ctx, userCred, image)
return cachedImage.syncWithCloudImage(ctx, userCred, ownerId, image, managerId)
} else {
return nil
}
}
func (manager *SStoragecachedimageManager) newFromCloudImage(ctx context.Context, userCred mcclient.TokenCredential, image cloudprovider.ICloudImage, cache *SStoragecache) error {
func (manager *SStoragecachedimageManager) newFromCloudImage(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, image cloudprovider.ICloudImage, cache *SStoragecache) error {
var cachedImage *SCachedimage
imgObj, err := db.FetchByExternalId(CachedimageManager, image.GetGlobalId())
if err != nil {
@@ -472,7 +472,7 @@ func (manager *SStoragecachedimageManager) newFromCloudImage(ctx context.Context
}
if cachedImage == nil {
// no such image
cachedImage, err = CachedimageManager.newFromCloudImage(ctx, userCred, image)
cachedImage, err = CachedimageManager.newFromCloudImage(ctx, userCred, ownerId, image, cache.ManagerId)
if err != nil {
log.Errorf("CachedimageManager.newFromCloudImage fail %s", err)
return err
@@ -482,7 +482,7 @@ func (manager *SStoragecachedimageManager) newFromCloudImage(ctx context.Context
cachedImage = imgObj.(*SCachedimage)
}
if len(cachedImage.ExternalId) > 0 {
cachedImage.syncWithCloudImage(ctx, userCred, image)
cachedImage.syncWithCloudImage(ctx, userCred, ownerId, image, cache.ManagerId)
}
scimg := manager.Register(ctx, userCred, cache.GetId(), cachedImage.GetId(), image.GetStatus())
if scimg == nil {
@@ -553,3 +553,22 @@ func (manager *SStoragecachedimageManager) OrderByExtraFields(
return q, nil
}
func (manager *SStoragecachedimageManager) InitializeData() error {
images := []SStoragecachedimage{}
q := manager.Query().Equals("status", "ready")
err := db.FetchModelObjects(manager, q, &images)
if err != nil {
return errors.Wrapf(err, "db.FetchModelObjects")
}
for i := range images {
_, err := db.Update(&images[i], func() error {
images[i].Status = api.CACHED_IMAGE_STATUS_ACTIVE
return nil
})
if err != nil {
return errors.Wrapf(err, "db.Update(%d)", images[i].RowId)
}
}
return nil
}

View File

@@ -610,6 +610,13 @@ func (cache *SStoragecache) SyncCloudImages(
return syncResult
}
var syncOwnerId mcclient.IIdentityProvider
provider := cache.GetCloudprovider()
if provider != nil {
syncOwnerId = provider.GetOwnerId()
}
removed := make([]SStoragecachedimage, 0)
commondb := make([]SStoragecachedimage, 0)
commonext := make([]cloudprovider.ICloudImage, 0)
@@ -631,7 +638,7 @@ func (cache *SStoragecache) SyncCloudImages(
}
}
for i := 0; i < len(commondb); i += 1 {
err = commondb[i].syncWithCloudImage(ctx, userCred, commonext[i])
err = commondb[i].syncWithCloudImage(ctx, userCred, syncOwnerId, commonext[i], cache.ManagerId)
if err != nil {
syncResult.UpdateError(err)
} else {
@@ -639,7 +646,7 @@ func (cache *SStoragecache) SyncCloudImages(
}
}
for i := 0; i < len(added); i += 1 {
err = StoragecachedimageManager.newFromCloudImage(ctx, userCred, added[i], cache)
err = StoragecachedimageManager.newFromCloudImage(ctx, userCred, syncOwnerId, added[i], cache)
if err != nil {
syncResult.AddError(err)
} else {
@@ -662,7 +669,7 @@ func (self *SStoragecache) IsReachCapacityLimit(imageId string) bool {
log.Debugf("image %s is not a customized image, no need to cache", imageId)
return false
}
cachedImages := self.getCachedImageList(nil, cloudprovider.CachedImageTypeCustomized, []string{api.CACHED_IMAGE_STATUS_READY})
cachedImages := self.getCachedImageList(nil, cloudprovider.CachedImageTypeCustomized, []string{api.CACHED_IMAGE_STATUS_ACTIVE})
for i := range cachedImages {
if cachedImages[i].Id == imageId {
// already cached
@@ -675,7 +682,7 @@ func (self *SStoragecache) IsReachCapacityLimit(imageId string) bool {
}
func (self *SStoragecache) StartRelinquishLeastUsedCachedImageTask(ctx context.Context, userCred mcclient.TokenCredential, imageId string, parentTaskId string) error {
cachedImages := self.getCachedImageList([]string{imageId}, cloudprovider.CachedImageTypeCustomized, []string{api.CACHED_IMAGE_STATUS_READY})
cachedImages := self.getCachedImageList([]string{imageId}, cloudprovider.CachedImageTypeCustomized, []string{api.CACHED_IMAGE_STATUS_ACTIVE})
leastUsedIdx := -1
leastRefCount := -1
for i := range cachedImages {

View File

@@ -454,6 +454,7 @@ func (manager *SWireManager) totalCountQ(
) *sqlchemy.SQuery {
guestsQ := filterByScopeOwnerId(GuestManager.Query(), scope, ownerId)
guests := guestsQ.SubQuery()
hostsQ := HostManager.Query()
if len(hostTypes) > 0 {
hostsQ = hostsQ.In("host_type", hostTypes)
@@ -465,7 +466,9 @@ func (manager *SWireManager) totalCountQ(
hostsQ = RangeObjectsFilter(hostsQ, rangeObjs, nil, hostsQ.Field("zone_id"), hostsQ.Field("manager_id"), hostsQ.Field("id"), nil)
}
hosts := hostsQ.SubQuery()
groups := filterByScopeOwnerId(GroupManager.Query(), scope, ownerId).SubQuery()
lbsQ := filterByScopeOwnerId(LoadbalancerManager.Query(), scope, ownerId)
if len(providers) > 0 || len(brands) > 0 || len(cloudEnv) > 0 {
lbsQ = CloudProviderFilter(lbsQ, lbsQ.Field("manager_id"), providers, brands, cloudEnv)
@@ -610,21 +613,20 @@ func (manager *SWireManager) totalCountQ(
)
q = q.LeftJoin(netSQ, sqlchemy.Equals(wires.Field("id"), netSQ.Field("wire_id")))
if len(rangeObjs) > 0 || len(hostTypes) > 0 {
if len(hostTypes) > 0 {
hostwires := HostwireManager.Query().SubQuery()
sq := hostwires.Query(hostwires.Field("wire_id"))
sq = sq.Join(hosts, sqlchemy.Equals(hosts.Field("id"), hostwires.Field("host_id")))
sq = sq.Filter(sqlchemy.IsTrue(hosts.Field("enabled")))
sq = AttachUsageQuery(sq, hosts, hostTypes, nil, nil, nil, "", rangeObjs)
q = q.Filter(sqlchemy.In(wires.Field("id"), sq.Distinct()))
hosts := HostManager.Query().SubQuery()
q = q.Join(hostwires, sqlchemy.Equals(q.Field("id"), hostwires.Field("wire_id")))
q = q.Join(hosts, sqlchemy.Equals(hostwires.Field("host_id"), hosts.Field("id")))
q = q.Filter(sqlchemy.In(hosts.Field("host_type"), hostTypes))
}
if len(providers) > 0 || len(brands) > 0 || len(cloudEnv) > 0 {
if len(rangeObjs) > 0 || len(providers) > 0 || len(brands) > 0 || len(cloudEnv) > 0 {
vpcs := VpcManager.Query().SubQuery()
subq := vpcs.Query(vpcs.Field("id"))
subq = CloudProviderFilter(subq, vpcs.Field("manager_id"), providers, brands, cloudEnv)
q = q.Filter(sqlchemy.In(wires.Field("vpc_id"), subq.SubQuery()))
q = q.Join(vpcs, sqlchemy.Equals(q.Field("vpc_id"), vpcs.Field("id")))
q = CloudProviderFilter(q, vpcs.Field("manager_id"), providers, brands, cloudEnv)
q = RangeObjectsFilter(q, rangeObjs, vpcs.Field("cloudregion_id"), q.Field("zone_id"), vpcs.Field("manager_id"), nil, nil)
}
return q

View File

@@ -144,6 +144,8 @@ type ComputeOptions struct {
SASControllerOptions
common_options.CommonOptions
common_options.DBOptions
EnableAutoMergeSecurityGroup bool `help:"Enable auto merge secgroup when sync security group from cloud, default False" default:"false"`
}
type SCapabilityOptions struct {

View File

@@ -16,7 +16,6 @@ package tasks
import (
"context"
"database/sql"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
@@ -26,7 +25,6 @@ import (
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/util/logclient"
)
type SecurityGroupCacheDeleteTask struct {
@@ -39,10 +37,6 @@ func init() {
func (self *SecurityGroupCacheDeleteTask) taskFailed(ctx context.Context, cache *models.SSecurityGroupCache, err error) {
cache.SetStatus(self.UserCred, api.SECGROUP_CACHE_STATUS_DELETE_FAILED, err.Error())
secgroup, _ := cache.GetSecgroup()
if secgroup != nil {
logclient.AddActionLogWithStartable(self, secgroup, logclient.ACT_DELETE, err, self.UserCred, false)
}
self.SetStageFailed(ctx, err.Error())
}
@@ -54,38 +48,18 @@ func (self *SecurityGroupCacheDeleteTask) taskComplete(ctx context.Context, cach
func (self *SecurityGroupCacheDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
cache := obj.(*models.SSecurityGroupCache)
if len(cache.ExternalId) == 0 {
self.taskComplete(ctx, cache)
return
}
_, err := models.CloudproviderManager.FetchById(cache.ManagerId)
if err == sql.ErrNoRows {
self.taskComplete(ctx, cache)
return
}
iRegion, err := cache.GetIRegion()
iSecgroup, err := cache.GetISecurityGroup()
if err != nil {
if errors.Cause(err) == cloudprovider.ErrNotFound {
self.taskComplete(ctx, cache)
return
}
self.taskFailed(ctx, cache, errors.Wrap(err, "cache.GetIRegion"))
return
}
iSecgroup, err := iRegion.GetISecurityGroupById(cache.ExternalId)
if err != nil {
if err == cloudprovider.ErrNotFound {
self.taskComplete(ctx, cache)
return
}
self.taskFailed(ctx, cache, errors.Wrap(err, "iRegion.GetIStoragecacheById"))
self.taskFailed(ctx, cache, errors.Wrapf(err, "GetISecurityGroup"))
return
}
err = iSecgroup.Delete()
if err != nil {
self.taskFailed(ctx, cache, err)
self.taskFailed(ctx, cache, errors.Wrapf(err, "iSecgroup.Delete"))
return
}
self.taskComplete(ctx, cache)

View File

@@ -18,11 +18,14 @@ import (
"context"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
api "yunion.io/x/onecloud/pkg/apis/compute"
"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"
"yunion.io/x/onecloud/pkg/util/logclient"
)
type SecurityGroupDeleteTask struct {
@@ -33,37 +36,38 @@ func init() {
taskman.RegisterTask(SecurityGroupDeleteTask{})
}
func (self *SecurityGroupDeleteTask) getErrorCount() int64 {
count, _ := self.GetParams().Int("faild_count")
return count
}
func (self *SecurityGroupDeleteTask) addErrorCount() {
count := self.getErrorCount()
count += 1
self.GetParams().Set("failed_count", jsonutils.NewInt(count))
func (self *SecurityGroupDeleteTask) taskFailed(ctx context.Context, secgroup *models.SSecurityGroup, err error) {
secgroup.SetStatus(self.UserCred, api.SECGROUP_STATUS_READY, "")
logclient.AddActionLogWithContext(ctx, secgroup, logclient.ACT_DELOCATE, err, self.UserCred, false)
self.SetStageFailed(ctx, err.Error())
}
func (self *SecurityGroupDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
self.SetStage("OnSecurityGroupUncacheComplete", nil)
self.OnSecurityGroupUncacheComplete(ctx, obj, data)
}
func (self *SecurityGroupDeleteTask) OnSecurityGroupUncacheComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
secgroup := obj.(*models.SSecurityGroup)
secgroupCaches := secgroup.GetSecurityGroupCaches()
errCount := self.getErrorCount()
if len(secgroupCaches) == int(errCount) {
if errCount == 0 {
secgroup.RealDelete(ctx, self.UserCred)
}
secgroup.SetStatus(self.UserCred, api.SECGROUP_STATUS_READY, "")
self.SetStageComplete(ctx, nil)
return
}
secgroupCaches[errCount].StartSecurityGroupCacheDeleteTask(ctx, self.UserCred, self.GetTaskId())
}
caches := secgroup.GetSecurityGroupCaches()
func (self *SecurityGroupDeleteTask) OnSecurityGroupUncacheCompleteFailed(ctx context.Context, obj db.IStandaloneModel, err jsonutils.JSONObject) {
self.addErrorCount()
isPurge := jsonutils.QueryBoolean(self.Params, "purge", false)
for i := range caches {
if !isPurge {
iSecgroup, err := caches[i].GetISecurityGroup()
if err != nil {
if errors.Cause(err) == cloudprovider.ErrNotFound {
caches[i].RealDelete(ctx, self.GetUserCred())
continue
}
self.taskFailed(ctx, secgroup, errors.Wrapf(err, "GetISecurityGroup for cache %s(%s)", caches[i].Name, caches[i].Id))
return
}
err = iSecgroup.Delete()
if err != nil {
self.taskFailed(ctx, secgroup, errors.Wrapf(err, "iSecgroup.Delete"))
return
}
}
caches[i].RealDelete(ctx, self.GetUserCred())
}
secgroup.RealDelete(ctx, self.GetUserCred())
self.SetStageComplete(ctx, nil)
}

View File

@@ -57,7 +57,7 @@ func (self *StorageCacheImageTask) OnRelinquishLeastUsedCachedImageComplete(ctx
storageCache := obj.(*models.SStoragecache)
scimg := models.StoragecachedimageManager.Register(ctx, self.UserCred, storageCache.Id, imageId, "")
if scimg.Status != api.CACHED_IMAGE_STATUS_READY {
if scimg.Status != api.CACHED_IMAGE_STATUS_ACTIVE {
scimg.SetStatus(self.UserCred, api.CACHED_IMAGE_STATUS_CACHING, "storage_cache_image_task")
}
@@ -117,7 +117,7 @@ func (self *StorageCacheImageTask) OnCacheSucc(ctx context.Context, cache *model
scimg := models.StoragecachedimageManager.Register(ctx, self.UserCred, cache.Id, imageId, "")
extImgId, _ := data.GetString("image_id")
scimg.SetStatus(self.UserCred, api.CACHED_IMAGE_STATUS_READY, "cached")
scimg.SetStatus(self.UserCred, api.CACHED_IMAGE_STATUS_ACTIVE, "cached")
if len(extImgId) > 0 && scimg.ExternalId != extImgId {
scimg.SetExternalId(extImgId)
}

View File

@@ -133,7 +133,6 @@ func Start(app *appsrv.Application) error {
}
func (agent *SEsxiAgent) AddImageCacheHandler(prefix string, app *appsrv.Application) {
hostutils.InitWorkerManager()
app.AddHandler("POST",
fmt.Sprintf("%s/disks/image_cache", prefix),
auth.Authenticate(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {

View File

@@ -19,18 +19,19 @@ import common_options "yunion.io/x/onecloud/pkg/cloudcommon/options"
type EsxiOptions struct {
common_options.CommonOptions
ListenInterface string `help:"Master address of host server" default:"br0"`
ListenAddress string `help:"Host serve IP address to select when multiple address bind to ListenInterface"`
EsxiAgentPath string `default:"/opt/cloud/workspace/esxi_agent" help:"Path for esxi agent configuration files"`
ImageCachePath string `help:"Path for storing image caches"`
ImageCacheLimit int `help:"Maximal storage space for image caching, in GB" default:"20"`
AgentTempPath string `help:"Path for ESXI Agent"`
AgentTempLimit int `help:"Maximal storage space for ESXi agent, in GB" default:"20"`
LinuxDefaultRootUser bool `help:"Default account for Linux system is root" default:"false"`
WindowsDefaultAdminUser bool `help:"Default account for Windows system is Administrator" default:"true"`
DefaultImageSaveFormat string `help:"Default image save format, default is vmdk, canbe qcow2" default:"vmdk"`
Zone string `help:"Zone where the agent locates"`
DeployServerSocketPath string `help:"Deploy server listen socket path" default:"/var/run/deploy.sock"`
ListenInterface string `help:"Master address of host server" default:"br0"`
ListenAddress string `help:"Host serve IP address to select when multiple address bind to ListenInterface"`
EsxiAgentPath string `default:"/opt/cloud/workspace/esxi_agent" help:"Path for esxi agent configuration files"`
ImageCachePath string `help:"Path for storing image caches"`
ImageCacheLimit int `help:"Maximal storage space for image caching, in GB" default:"20"`
AgentTempPath string `help:"Path for ESXI Agent"`
AgentTempLimit int `help:"Maximal storage space for ESXi agent, in GB" default:"20"`
LinuxDefaultRootUser bool `help:"Default account for Linux system is root" default:"false"`
WindowsDefaultAdminUser bool `help:"Default account for Windows system is Administrator" default:"true"`
DefaultImageSaveFormat string `help:"Default image save format, default is vmdk, canbe qcow2" default:"vmdk"`
Zone string `help:"Zone where the agent locates"`
DeployServerSocketPath string `help:"Deploy server listen socket path" default:"/var/run/deploy.sock"`
HostDelayTaskWorkerCount int `default:"8" help:"Host delay worker thread count, default is 8"`
}
var (

View File

@@ -30,6 +30,7 @@ import (
"yunion.io/x/onecloud/pkg/esxi/options"
"yunion.io/x/onecloud/pkg/hostman/guestfs/fsdriver"
"yunion.io/x/onecloud/pkg/hostman/hostdeployer/deployclient"
"yunion.io/x/onecloud/pkg/hostman/hostutils"
)
type SExsiAgentService struct {
@@ -70,6 +71,7 @@ func (s *SExsiAgentService) StartService() {
fsdriver.Init(nil)
deployclient.Init(options.Options.DeployServerSocketPath)
hostutils.InitWorkerManagerWithCount(options.Options.HostDelayTaskWorkerCount)
app := app_common.InitApp(&options.Options.BaseOptions, false)
handler.InitHandlers(app)

View File

@@ -773,7 +773,7 @@ func (d *SUbuntuRootFs) GetReleaseInfo(rootFs IDiskPartition) *deployapi.Release
lines := strings.Split(string(rel), "\n")
for _, l := range lines {
if strings.HasPrefix(l, distroKey) {
version = strings.TrimSpace(l[len(distroKey) : len(l)-1])
version = strings.TrimSpace(l[len(distroKey):])
}
}
return deployapi.NewReleaseInfo(d.GetName(), version, d.GetArch(rootFs))

View File

@@ -189,7 +189,11 @@ func DelayTaskWithWorker(
}
func InitWorkerManager() {
wm = workmanager.NewWorkManger(TaskFailed, TaskComplete, options.HostOptions.DefaultRequestWorkerCount)
InitWorkerManagerWithCount(options.HostOptions.DefaultRequestWorkerCount)
}
func InitWorkerManagerWithCount(count int) {
wm = workmanager.NewWorkManger(TaskFailed, TaskComplete, count)
}
func InitK8sWorkerManager() {

View File

@@ -24,7 +24,6 @@ import (
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/hostman/hostutils"
"yunion.io/x/onecloud/pkg/hostman/options"
"yunion.io/x/onecloud/pkg/hostman/storageman/remotefile"
"yunion.io/x/onecloud/pkg/mcclient/modules"
"yunion.io/x/onecloud/pkg/util/procutils"
@@ -75,11 +74,11 @@ func (r *SRbdImageCache) Acquire(ctx context.Context, zone, srcUrl, format strin
}
r.imageName = localImageCache.GetName()
if !r.Load() {
log.Debugf("convert local image %s to rbd pool %s", r.imageId, r.Manager.GetPath())
log.Infof("convert local image %s to rbd pool %s", r.imageId, r.Manager.GetPath())
err := procutils.NewRemoteCommandAsFarAsPossible(qemutils.GetQemuImg(),
"convert", "-O", "raw", localImageCache.GetPath(), r.GetPath()).Run()
if err != nil {
log.Errorf("failed to convert image %s", options.HostOptions.ServersPath)
log.Errorf("failed to convert image %s", err)
return false
}
}

View File

@@ -225,12 +225,12 @@ func (c *SAgentImageCacheManager) perfetchTemplateVMImageCache(ctx context.Conte
if err != nil {
return nil, errors.Wrap(err, "host.GetDatacenter")
}
_, err = dc.GetTemplateVMById(data.ImageExternalId)
_, err = dc.FetchTemplateVMById(data.ImageExternalId)
if err != nil {
return nil, err
}
res := jsonutils.NewDict()
res.Add(jsonutils.NewString(data.ImageId), "image_id")
res.Add(jsonutils.NewString(data.ImageExternalId), "image_id")
return res, nil
}

View File

@@ -111,7 +111,7 @@ func (c *SRbdImageCacheManager) PrefetchImageCache(ctx context.Context, data int
if err != nil {
return nil, err
}
format := "qcow2"
format, _ := body.GetString("format")
srcUrl, _ := body.GetString("src_url")
zone, _ := body.GetString("zone")

View File

@@ -17,7 +17,6 @@ package tokens
import (
"context"
"database/sql"
"fmt"
"time"
"yunion.io/x/pkg/errors"
@@ -146,8 +145,12 @@ func authUserByIdentity(ctx context.Context, ident mcclient.SAuthenticationIdent
idp := idpObj.(*models.SIdentityProvider)
if idp.Enabled.IsFalse() {
return nil, errors.Wrap(httperrors.ErrInvalidStatus, "idp disabled")
}
if idp.Status != api.IdentityDriverStatusConnected && idp.Status != api.IdentityDriverStatusDisconnected {
return nil, errors.Error(fmt.Sprintf("invalid idp status %s", idp.Status))
return nil, errors.Wrapf(httperrors.ErrInvalidStatus, "invalid idp status %s", idp.Status)
}
conf, err := models.GetConfigs(idp, true, nil, nil)

View File

@@ -26,7 +26,7 @@ func init() {
"OS_Type", "OS_Distribution", "OS_version",
"Hypervisor", "Host_count", "Status",
"Ref_Count", "cached_count", "image_type",
"External_Id",
"External_Id", "Is_Public", "Public_Scope", "Tenant", "Tenant_Id",
},
[]string{})

View File

@@ -28,6 +28,7 @@ import (
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
"yunion.io/x/onecloud/pkg/util/imagetools"
)
@@ -57,6 +58,7 @@ const (
)
type SImage struct {
multicloud.SImageBase
storageCache *SStoragecache
Architecture string
@@ -129,7 +131,7 @@ func (self *SImage) GetStatus() string {
case ImageStatusCreating:
return api.CACHED_IMAGE_STATUS_SAVING
case ImageStatusAvailable:
return api.CACHED_IMAGE_STATUS_READY
return api.CACHED_IMAGE_STATUS_ACTIVE
case ImageStatusUnAvailable:
return api.CACHED_IMAGE_STATUS_CACHE_FAILED
case ImageStatusCreateFailed:

View File

@@ -41,4 +41,5 @@ var LatitudeAndLongitude = map[string]cloudprovider.SGeographicInfo{
"eu-west-1": {Latitude: 51.507351, Longitude: -0.127758, City: api.CITY_LONDON, CountryCode: api.COUNTRY_CODE_GB},
"me-east-1": {Latitude: 25.204849, Longitude: 55.270782, City: api.CITY_DUBAI, CountryCode: api.COUNTRY_CODE_AE},
"eu-central-1": {Latitude: 50.110924, Longitude: 8.682127, City: api.CITY_FRANKFURT, CountryCode: api.COUNTRY_CODE_DE},
"cn-wulanchabu": {Latitude: 41.0178065, Longitude: 113.094978, City: api.CITY_WU_LAN_CHA_BU, CountryCode: api.COUNTRY_CODE_CN},
}

View File

@@ -28,6 +28,7 @@ import (
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
)
type ImageStatusType string
@@ -74,6 +75,7 @@ type RootDevice struct {
}
type SImage struct {
multicloud.SImageBase
storageCache *SStoragecache
Architecture string
@@ -185,7 +187,7 @@ func (self *SImage) GetStatus() string {
case ImageStatusCreating:
return api.CACHED_IMAGE_STATUS_CACHING
case ImageStatusAvailable:
return api.CACHED_IMAGE_STATUS_READY
return api.CACHED_IMAGE_STATUS_ACTIVE
case ImageStatusCreateFailed:
return api.CACHED_IMAGE_STATUS_CACHE_FAILED
default:

View File

@@ -27,6 +27,7 @@ import (
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
)
type ImageStatusType string
@@ -80,6 +81,7 @@ type ImageProperties struct {
}
type SImage struct {
multicloud.SImageBase
storageCache *SStoragecache
Properties ImageProperties `json:"properties,omitempty"`
@@ -130,7 +132,7 @@ func (self *SImage) GetStatus() string {
case "created":
return api.CACHED_IMAGE_STATUS_CACHING
case "Succeeded":
return api.CACHED_IMAGE_STATUS_READY
return api.CACHED_IMAGE_STATUS_ACTIVE
default:
log.Errorf("Unknow image status: %s", self.Properties.ProvisioningState)
return api.CACHED_IMAGE_STATUS_CACHE_FAILED

View File

@@ -24,6 +24,7 @@ import (
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
"yunion.io/x/onecloud/pkg/util/imagetools"
)
@@ -35,6 +36,7 @@ const (
// http://ctyun-api-url/apiproxy/v3/order/getImages
type SImage struct {
multicloud.SImageBase
storageCache *SStoragecache
ID string `json:"id"`
@@ -66,7 +68,7 @@ func (self *SImage) GetGlobalId() string {
}
func (self *SImage) GetStatus() string {
return api.CACHED_IMAGE_STATUS_READY
return api.CACHED_IMAGE_STATUS_ACTIVE
}
func (self *SImage) Refresh() error {

View File

@@ -18,6 +18,8 @@ import (
"strings"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/view"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
@@ -237,32 +239,85 @@ func (dc *SDatacenter) getDcObj() *object.Datacenter {
return object.NewDatacenter(dc.manager.client.Client, dc.object.Reference())
}
// fetchVms will identify if VM is a template and return two different arrays; the latter contains all template vms.
func (dc *SDatacenter) fetchVms(vmRefs []types.ManagedObjectReference, all bool) ([]cloudprovider.ICloudVM, []*SVirtualMachine, error) {
var vms []mo.VirtualMachine
func (dc *SDatacenter) fetchVms(vmRefs []types.ManagedObjectReference, all bool) ([]*SVirtualMachine, error) {
var movms []mo.VirtualMachine
if vmRefs != nil {
err := dc.manager.references2Objects(vmRefs, VIRTUAL_MACHINE_PROPS, &vms)
err := dc.manager.references2Objects(vmRefs, VIRTUAL_MACHINE_PROPS, &movms)
if err != nil {
return nil, nil, errors.Wrap(err, "dc.manager.references2Objects")
return nil, errors.Wrap(err, "dc.manager.references2Objects")
}
}
// avoid applying new memory and copying
retVms := make([]cloudprovider.ICloudVM, 0, len(vms)/2)
templateVMs := make([]*SVirtualMachine, 0, 2)
for i := 0; i < len(vms); i += 1 {
if all || !strings.HasPrefix(vms[i].Entity().Name, api.ESXI_IMAGE_CACHE_TMP_PREFIX) {
vmObj := NewVirtualMachine(dc.manager, &vms[i], dc)
if vms[i].Config != nil && vms[i].Config.Template {
templateVMs = append(templateVMs, vmObj)
continue
}
if vmObj != nil {
retVms = append(retVms, vmObj)
}
vms := make([]*SVirtualMachine, 0, len(movms))
for i := range movms {
if all || !strings.HasPrefix(movms[i].Entity().Name, api.ESXI_IMAGE_CACHE_TMP_PREFIX) {
vms = append(vms, NewVirtualMachine(dc.manager, &movms[i], dc))
}
}
return retVms, templateVMs, nil
return vms, nil
}
func (dc *SDatacenter) FetchVMs() ([]*SVirtualMachine, error) {
return dc.fetchVMs(property.Filter{})
}
func (dc *SDatacenter) FetchNoTemplateVMs() ([]*SVirtualMachine, error) {
filter := property.Filter{}
filter["config.template"] = false
return dc.fetchVMs(filter)
}
func (dc *SDatacenter) fetchVMs(filter property.Filter) ([]*SVirtualMachine, error) {
odc := dc.getObjectDatacenter()
root := odc.Reference()
m := view.NewManager(dc.manager.client.Client)
v, err := m.CreateContainerView(dc.manager.context, root, []string{"VirtualMachine"}, true)
if err != nil {
return nil, err
}
defer func() {
_ = v.Destroy(dc.manager.context)
}()
objs, err := v.Find(dc.manager.context, []string{"VirtualMachine"}, filter)
if err != nil {
return nil, err
}
vms, err := dc.fetchVms(objs, false)
return vms, err
}
func (dc *SDatacenter) FetchTemplateVMs() ([]*SVirtualMachine, error) {
filter := property.Filter{}
filter["config.template"] = true
return dc.fetchVMs(filter)
}
func (dc *SDatacenter) FetchTemplateVMById(id string) (*SVirtualMachine, error) {
filter := property.Filter{}
filter["config.template"] = true
filter["summary.config.uuid"] = id
vms, err := dc.fetchVMs(filter)
if err != nil {
return nil, err
}
if len(vms) == 0 {
return nil, errors.ErrNotFound
}
return vms[0], nil
}
func (dc *SDatacenter) FetchVMById(id string) (*SVirtualMachine, error) {
filter := property.Filter{}
filter["summary.config.uuid"] = id
vms, err := dc.fetchVMs(filter)
if err != nil {
return nil, err
}
if len(vms) == 0 {
return nil, errors.ErrNotFound
}
return vms[0], nil
}
func (dc *SDatacenter) fetchDatastores(datastoreRefs []types.ManagedObjectReference) ([]cloudprovider.ICloudStorage, error) {
@@ -381,24 +436,3 @@ func (dc *SDatacenter) GetTemplateVMs() ([]*SVirtualMachine, error) {
}
return templateVms, nil
}
func (dc *SDatacenter) GetTemplateVMById(id string) (*SVirtualMachine, error) {
id = dc.manager.getPrivateId(id)
hosts, err := dc.GetIHosts()
if err != nil {
return nil, errors.Wrap(err, "SDatacenter.GetIHosts")
}
for _, ihost := range hosts {
host := ihost.(*SHost)
tvms, err := host.GetTemplateVMs()
if err != nil {
return nil, errors.Wrap(err, "host.GetTemplateVMs")
}
for i := range tvms {
if tvms[i].GetGlobalId() == id {
return tvms[i], nil
}
}
}
return nil, cloudprovider.ErrNotFound
}

View File

@@ -181,6 +181,7 @@ func (self *SHost) fetchVMs(all bool) error {
}
MAX_TRIES := 3
var vms []*SVirtualMachine
for tried := 0; tried < MAX_TRIES; tried += 1 {
hostVms := self.getHostSystem().Vm
if len(hostVms) == 0 {
@@ -188,15 +189,20 @@ func (self *SHost) fetchVMs(all bool) error {
return nil
}
vms, templatevms, err := dc.fetchVms(hostVms, all)
vms, err = dc.fetchVms(hostVms, all)
if err != nil {
log.Errorf("dc.fetchVms fail %s", err)
time.Sleep(time.Second)
self.Refresh()
continue
}
self.vms = vms
self.tempalteVMs = templatevms
}
for _, vm := range vms {
if vm.IsTemplate() {
self.tempalteVMs = append(self.tempalteVMs, vm)
} else {
self.vms = append(self.vms, vm)
}
}
return nil
}
@@ -702,9 +708,13 @@ func (self *SHost) CreateVM2(ctx context.Context, ds *SDatastore, params SCreate
if err != nil {
return nil, errors.Wrap(err, "SEsxiClient.FindHostByIp")
}
temvm, err := imgHost.GetTemplateVMById(imageInfo.ImageExternalId)
dc, err := imgHost.GetDatacenter()
if err != nil {
return nil, errors.Wrap(err, "SHost.GetTemplateVMById")
return nil, errors.Wrap(err, "host.GetDatacenter")
}
temvm, err := dc.FetchTemplateVMById(imageInfo.ImageExternalId)
if err != nil {
return nil, errors.Wrapf(err, "datacenter.TemplateVMById for image %q and datacenter %q", imageInfo.ImageExternalId, dc.GetId())
}
return self.CloneVM(ctx, temvm, ds, params)
}

View File

@@ -26,9 +26,11 @@ import (
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
)
type SImage struct {
multicloud.SImageBase
cache *SDatastoreImageCache
filename string
size int64
@@ -74,12 +76,12 @@ func (self *SImage) GetStatus() string {
if err != nil {
return api.CACHED_IMAGE_STATUS_CACHE_FAILED
}
return api.CACHED_IMAGE_STATUS_READY
return api.CACHED_IMAGE_STATUS_ACTIVE
}
func (self *SImage) GetImageStatus() string {
status := self.GetStatus()
if status == api.CACHED_IMAGE_STATUS_READY {
if status == api.CACHED_IMAGE_STATUS_ACTIVE {
return cloudprovider.IMAGE_STATUS_ACTIVE
}
return cloudprovider.IMAGE_STATUS_DELETED

92
pkg/multicloud/esxi/ip.go Normal file
View File

@@ -0,0 +1,92 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package esxi
import (
"github.com/vmware/govmomi/vim25/mo"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/regutils"
)
var HOST_PROPS = []string{"name", "config.network", "vm"}
var VM_PROPS = []string{"name", "guest.net", "config.template"}
func (cli *SESXiClient) AllHostIP() (map[string]string, []mo.HostSystem, error) {
var hosts []mo.HostSystem
err := cli.scanAllMObjects(HOST_PROPS, &hosts)
if err != nil {
return nil, nil, errors.Wrap(err, "scanAllMObjects")
}
ret := make(map[string]string, len(hosts))
for i := range hosts {
// find ip
host := &SHost{SManagedObject: newManagedObject(cli, &hosts[i], nil)}
ip := host.GetAccessIp()
ret[host.GetName()] = ip
}
return ret, hosts, nil
}
func (cli *SESXiClient) VMIP(host mo.HostSystem) (map[string][]string, error) {
var vms []mo.VirtualMachine
err := cli.references2Objects(host.Vm, VM_PROPS, &vms)
if err != nil {
return nil, errors.Wrap(err, "references2Objects")
}
ret := make(map[string][]string, len(vms))
for i := range vms {
vm := vms[i]
if vm.Config.Template {
continue
}
guestIps := make([]string, 0)
for _, net := range vm.Guest.Net {
for _, ip := range net.IpAddress {
if regutils.MatchIP4Addr(ip) {
guestIps = append(guestIps, ip)
}
}
}
ret[vm.Name] = guestIps
}
return ret, nil
}
func (cli *SESXiClient) VMIP2() (map[string][]string, error) {
var vms []mo.VirtualMachine
err := cli.scanAllMObjects(VM_PROPS, &vms)
if err != nil {
return nil, errors.Wrap(err, "scanAllMObjects")
}
ret := make(map[string][]string, len(vms))
for i := range vms {
vm := vms[i]
if vm.Config.Template {
continue
}
guestIps := make([]string, 0)
for _, net := range vm.Guest.Net {
for _, ip := range net.IpAddress {
if regutils.MatchIP4Addr(ip) {
guestIps = append(guestIps, ip)
}
}
}
ret[vm.Name] = guestIps
}
return ret, nil
}

View File

@@ -31,10 +31,12 @@ import (
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
"golang.org/x/sync/errgroup"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/regutils"
"yunion.io/x/pkg/utils"
api "yunion.io/x/onecloud/pkg/apis/compute"
@@ -597,3 +599,86 @@ func (cli *SESXiClient) MoveDisk(ctx context.Context, src, dst string, isForce b
}
return task.Wait(ctx)
}
var (
SIMPLE_HOST_PROPS = []string{"name", "config.network", "vm"}
SIMPLE_VM_PROPS = []string{"name", "guest.net", "config.template"}
)
type SSimpleVM struct {
Name string
IPs []string
}
func (cli *SESXiClient) HostVmIPs(ctx context.Context) (map[string]string, []SSimpleVM, error) {
var hosts []mo.HostSystem
err := cli.scanAllMObjects(SIMPLE_HOST_PROPS, &hosts)
if err != nil {
return nil, nil, errors.Wrap(err, "scanAllMObjects")
}
group, ctx := errgroup.WithContext(ctx)
collection := make([][]SSimpleVM, len(hosts))
for i := range hosts {
j := i
group.Go(func() error {
vmIps, err := cli.vmIPs(&hosts[j])
if err != nil {
return err
}
collection[j] = vmIps
return nil
})
}
hostIps := make(map[string]string, len(hosts))
for i := range hosts {
// find ip
host := &SHost{SManagedObject: newManagedObject(cli, &hosts[i], nil)}
ip := host.GetAccessIp()
hostIps[host.GetName()] = ip
}
err = group.Wait()
if err != nil {
return nil, nil, err
}
// length
length := 0
for i := range collection {
length += len(collection[i])
}
svms := make([]SSimpleVM, 0, length)
for i := range collection {
for j := range collection[i] {
svms = append(svms, collection[i][j])
}
}
return hostIps, svms, nil
}
func (cli *SESXiClient) vmIPs(host *mo.HostSystem) ([]SSimpleVM, error) {
if len(host.Vm) == 0 {
return []SSimpleVM{}, nil
}
var vms []mo.VirtualMachine
err := cli.references2Objects(host.Vm, VM_PROPS, &vms)
if err != nil {
return nil, errors.Wrap(err, "references2Objects")
}
ret := make([]SSimpleVM, 0, len(vms))
for i := range vms {
vm := vms[i]
if vm.Config.Template {
continue
}
guestIps := make([]string, 0)
for _, net := range vm.Guest.Net {
for _, ip := range net.IpAddress {
if regutils.MatchIP4Addr(ip) {
guestIps = append(guestIps, ip)
}
}
}
ret = append(ret, SSimpleVM{vm.Name, guestIps})
}
return ret, nil
}

View File

@@ -0,0 +1,55 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shell
import (
"fmt"
"yunion.io/x/onecloud/pkg/multicloud/esxi"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type IPOption struct {
Host bool
}
shellutils.R(&IPOption{}, "ip-all", "List all ip", func(cli *esxi.SESXiClient, args *IPOption) error {
hostIps, _, err := cli.AllHostIP()
if err != nil {
return err
}
for name, ip := range hostIps {
fmt.Printf("name: %s, ip: %s\n", name, ip)
}
// for i := range hosts {
// fmt.Printf("host %s: \n", hosts[i].Name)
// vmips, err := cli.VMIP(hosts[i])
// if err != nil {
// return err
// }
// for name, ip := range vmips {
// fmt.Printf("\tname: %s, ip: %s\n", name, ip)
// }
// }
vmips, err := cli.VMIP2()
if err != nil {
return err
}
for name, ip := range vmips {
fmt.Printf("\tname: %s, ip: %s\n", name, ip)
}
return nil
})
}

View File

@@ -27,28 +27,53 @@ import (
func init() {
type VirtualMachineListOptions struct {
HOSTIP string `help:"Host IP"`
Template bool `help:"Whether it is tempalte virtual machine"`
Datacenter string `help:"Datacenter"`
HostIP string `help:"HostIP"`
Template bool `help:"Whether it is tempalte virtual machine, default:false"`
}
shellutils.R(&VirtualMachineListOptions{}, "vm-list", "List vms of a host", func(cli *esxi.SESXiClient, args *VirtualMachineListOptions) error {
host, err := cli.FindHostByIp(args.HOSTIP)
if err != nil {
return err
}
if args.Template {
vms, err := host.GetTemplateVMs()
switch {
case len(args.HostIP) > 0:
host, err := cli.FindHostByIp(args.HostIP)
if err != nil {
return err
}
if args.Template {
vms, err := host.GetTemplateVMs()
if err != nil {
return err
}
printList(vms, []string{})
return nil
}
vms, err := host.GetIVMs2()
if err != nil {
return err
}
printList(vms, []string{})
return nil
case len(args.Datacenter) > 0:
dc, err := cli.FindDatacenterByMoId(args.Datacenter)
if err != nil {
return errors.Wrap(err, "FindDatacenterByMoId")
}
var vms []*esxi.SVirtualMachine
if args.Template {
vms, err = dc.FetchTemplateVMs()
if err != nil {
return errors.Wrap(err, "FetchTemplateVMs")
}
} else {
vms, err = dc.FetchNoTemplateVMs()
if err != nil {
return errors.Wrap(err, "FetchNoTemplateVMs")
}
}
printList(vms, []string{})
return nil
default:
return fmt.Errorf("Both Datacenter and HostIP cannot be empty")
}
vms, err := host.GetIVMs2()
if err != nil {
return err
}
printList(vms, []string{})
return nil
})
type VirtualMachineCloneOptions struct {
@@ -91,24 +116,45 @@ func init() {
})
type VirtualMachineShowOptions struct {
HOSTIP string `help:"Host IP"`
VMID string `help:"VM ID"`
Template bool
Datacenter string `help:"Datacenter"`
HostIP string `help:"Host IP"`
VMID string `help:"VM ID"`
}
getVM := func(cli *esxi.SESXiClient, args *VirtualMachineShowOptions) (*esxi.SVirtualMachine, error) {
var vm *esxi.SVirtualMachine
switch {
case len(args.HostIP) > 0:
host, err := cli.FindHostByIp(args.HostIP)
if err != nil {
return nil, errors.Wrap(err, "FindHostByIp")
}
ivm, err := host.GetIVMById(args.VMID)
if err != nil && errors.Cause(err) != errors.ErrNotFound {
return nil, err
}
if err != nil {
vm, err = host.GetTemplateVMById(args.VMID)
if err != nil {
return nil, errors.Wrap(err, "GetTemplateVMById")
}
}
vm = ivm.(*esxi.SVirtualMachine)
case len(args.Datacenter) > 0:
dc, err := cli.FindDatacenterByMoId(args.Datacenter)
if err != nil {
return nil, errors.Wrap(err, "FindDatacenterByMoId")
}
vm, err = dc.FetchVMById(args.VMID)
if err != nil {
return nil, errors.Wrap(err, "FetchVMById")
}
default:
return nil, fmt.Errorf("Both Datacenter and HostIP cannot be empty")
}
return vm, nil
}
shellutils.R(&VirtualMachineShowOptions{}, "vm-show", "Show vm details", func(cli *esxi.SESXiClient, args *VirtualMachineShowOptions) error {
host, err := cli.FindHostByIp(args.HOSTIP)
if err != nil {
return err
}
if args.Template {
vm, err := host.GetTemplateVMById(args.VMID)
if err != nil {
return err
}
printObject(vm)
return nil
}
vm, err := host.GetIVMById(args.VMID)
vm, err := getVM(cli, args)
if err != nil {
return err
}
@@ -117,11 +163,7 @@ func init() {
})
shellutils.R(&VirtualMachineShowOptions{}, "vm-nics", "Show vm nics details", func(cli *esxi.SESXiClient, args *VirtualMachineShowOptions) error {
host, err := cli.FindHostByIp(args.HOSTIP)
if err != nil {
return err
}
vm, err := host.GetIVMById(args.VMID)
vm, err := getVM(cli, args)
if err != nil {
return err
}
@@ -134,11 +176,7 @@ func init() {
})
shellutils.R(&VirtualMachineShowOptions{}, "vm-disks", "Show vm disks details", func(cli *esxi.SESXiClient, args *VirtualMachineShowOptions) error {
host, err := cli.FindHostByIp(args.HOSTIP)
if err != nil {
return err
}
vm, err := host.GetIVMById(args.VMID)
vm, err := getVM(cli, args)
if err != nil {
return err
}
@@ -151,17 +189,12 @@ func init() {
})
type VirtualMachineDiskResizeOptions struct {
HOSTIP string `help:"host ip"`
VMID string `help:"virtual machine UUID"`
DISKIDX int `help:"disk index"`
SIZEGB int64 `help:"new size of disk"`
VirtualMachineShowOptions
DISKIDX int `help:"disk index"`
SIZEGB int64 `help:"new size of disk"`
}
shellutils.R(&VirtualMachineDiskResizeOptions{}, "vm-disk-resize", "Resize a vm disk", func(cli *esxi.SESXiClient, args *VirtualMachineDiskResizeOptions) error {
host, err := cli.FindHostByIp(args.HOSTIP)
if err != nil {
return err
}
vm, err := host.GetIVMById(args.VMID)
vm, err := getVM(cli, &args.VirtualMachineShowOptions)
if err != nil {
return err
}
@@ -178,11 +211,7 @@ func init() {
})
shellutils.R(&VirtualMachineShowOptions{}, "vm-vnc", "Show vm VNC details", func(cli *esxi.SESXiClient, args *VirtualMachineShowOptions) error {
host, err := cli.FindHostByIp(args.HOSTIP)
if err != nil {
return err
}
vm, err := host.GetIVMById(args.VMID)
vm, err := getVM(cli, args)
if err != nil {
return err
}
@@ -195,15 +224,11 @@ func init() {
})
shellutils.R(&VirtualMachineShowOptions{}, "vm-file-status", "Show vm files details", func(cli *esxi.SESXiClient, args *VirtualMachineShowOptions) error {
host, err := cli.FindHostByIp(args.HOSTIP)
vm, err := getVM(cli, args)
if err != nil {
return err
}
vm, err := host.GetIVMById(args.VMID)
if err != nil {
return err
}
err = vm.(*esxi.SVirtualMachine).CheckFileInfo(context.Background())
err = vm.CheckFileInfo(context.Background())
if err != nil {
return err
}

View File

@@ -259,7 +259,14 @@ func (self *SDatastore) getVMs() ([]cloudprovider.ICloudVM, error) {
if len(vms) == 0 {
return nil, nil
}
ret, _, err := dc.fetchVms(vms, false)
svms, err := dc.fetchVms(vms, false)
if err != nil {
return nil, err
}
ret := make([]cloudprovider.ICloudVM, len(svms))
for i := range svms {
ret[i] = svms[i]
}
return ret, err
}

View File

@@ -24,9 +24,11 @@ import (
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
)
type SVMTemplate struct {
multicloud.SImageBase
cache *SDatastoreImageCache
vm *SVirtualMachine
uuid string
@@ -65,7 +67,7 @@ func (t *SVMTemplate) GetStatus() string {
host := ihost.(*SHost)
_, err := host.GetTemplateVMById(t.uuid)
if err == nil {
return api.CACHED_IMAGE_STATUS_READY
return api.CACHED_IMAGE_STATUS_ACTIVE
}
if errors.Cause(err) != cloudprovider.ErrNotFound {
log.Errorf("fail to find templatevm %q: %v", t.uuid, err)
@@ -123,7 +125,7 @@ func (t *SVMTemplate) GetImageType() string {
func (t *SVMTemplate) GetImageStatus() string {
status := t.GetStatus()
if status == api.CACHED_IMAGE_STATUS_READY {
if status == api.CACHED_IMAGE_STATUS_ACTIVE {
return cloudprovider.IMAGE_STATUS_ACTIVE
}
return cloudprovider.IMAGE_STATUS_DELETED

View File

@@ -43,6 +43,7 @@ import (
"yunion.io/x/onecloud/pkg/multicloud"
"yunion.io/x/onecloud/pkg/util/billing"
"yunion.io/x/onecloud/pkg/util/netutils2"
"yunion.io/x/onecloud/pkg/util/version"
)
var VIRTUAL_MACHINE_PROPS = []string{"name", "parent", "runtime", "summary", "config", "guest", "resourcePool", "layoutEx"}
@@ -74,10 +75,7 @@ func (d byDiskType) Less(i, j int) bool {
func NewVirtualMachine(manager *SESXiClient, vm *mo.VirtualMachine, dc *SDatacenter) *SVirtualMachine {
svm := &SVirtualMachine{SManagedObject: newManagedObject(manager, vm, dc)}
err := svm.fetchHardwareInfo()
if err != nil {
return nil
}
svm.fetchHardwareInfo()
return svm
}
@@ -580,11 +578,14 @@ func (self *SVirtualMachine) doDetachDisk(ctx context.Context, vdisk *SVirtualDi
}
func (self *SVirtualMachine) GetVNCInfo() (jsonutils.JSONObject, error) {
info, err := self.acquireWebmksTicket("webmks")
if err != nil {
info, err = self.acquireVmrcUrl()
hostVer := self.GetIHost().GetVersion()
if version.GE(hostVer, "6.5") {
info, err := self.acquireWebmksTicket("webmks")
if err == nil {
return info, nil
}
}
return info, err
return self.acquireVmrcUrl()
}
func (self *SVirtualMachine) acquireWebmksTicket(ticketType string) (jsonutils.JSONObject, error) {
@@ -606,14 +607,6 @@ func (self *SVirtualMachine) acquireWebmksTicket(ticketType string) (jsonutils.J
if port == 0 {
port = 443
}
/*
ret.Add(jsonutils.NewString(ticketType), "type")
ret.Add(jsonutils.NewString(ticket.Host), "host")
ret.Add(jsonutils.NewInt(int64(ticket.Port)), "port")
ret.Add(jsonutils.NewString(ticket.Ticket), "ticket")
ret.Add(jsonutils.NewString(ticket.SslThumbprint), "slThumbprint")
ret.Add(jsonutils.NewString(ticket.CfgFile), "cfgFile")
*/
url := fmt.Sprintf("wss://%s:%d/ticket/%s", host, port, ticket.Ticket)
ret.Add(jsonutils.NewString("wmks"), "protocol")
ret.Add(jsonutils.NewString(url), "url")
@@ -710,7 +703,7 @@ func (self *SVirtualMachine) UpdateUserData(userData string) error {
return nil
}
func (self *SVirtualMachine) fetchHardwareInfo() error {
func (self *SVirtualMachine) fetchHardwareInfo() {
self.vnics = make([]SVirtualNIC, 0)
self.vdisks = make([]SVirtualDisk, 0)
self.cdroms = make([]SVirtualCdrom, 0)
@@ -724,7 +717,8 @@ func (self *SVirtualMachine) fetchHardwareInfo() error {
}
if moVM == nil || moVM.Config == nil || moVM.Config.Hardware.Device == nil {
return errors.Error("invalid vm config")
log.Errorf("invalid vm config, moVM: %v", moVM)
return
}
for i := 0; i < len(moVM.Config.Hardware.Device); i += 1 {
@@ -752,7 +746,6 @@ func (self *SVirtualMachine) fetchHardwareInfo() error {
sort.Slice(self.vdisks, func(i, j int) bool {
return self.vdisks[i].GetIndex() < self.vdisks[j].GetIndex()
})
return nil
}
func (self *SVirtualMachine) getVdev(key int32) SVirtualDevice {
@@ -1220,3 +1213,8 @@ func (self *SVirtualMachine) FindMinDiffKey(limit int32) int32 {
}
return limit
}
func (self *SVirtualMachine) IsTemplate() bool {
movm := self.getVirtualMachine()
return movm.Config != nil && movm.Config.Template
}

View File

@@ -25,6 +25,7 @@ import (
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
"yunion.io/x/onecloud/pkg/util/imagetools"
)
@@ -39,6 +40,7 @@ type SDeprecated struct {
}
type SImage struct {
multicloud.SImageBase
storagecache *SStoragecache
SResourceBase
@@ -120,7 +122,7 @@ func (image *SImage) GetMinRamSizeMb() int {
func (image *SImage) GetStatus() string {
switch image.Status {
case "READY":
return api.CACHED_IMAGE_STATUS_READY
return api.CACHED_IMAGE_STATUS_ACTIVE
case "FAILED":
return api.CACHED_IMAGE_STATUS_CACHE_FAILED
case "PENDING":

View File

@@ -102,7 +102,7 @@ func (cache *SStoragecache) UploadImage(ctx context.Context, userCred mcclient.T
} else {
status := _image.GetStatus()
log.Debugf("UploadImage: Image external ID %s exists, status %s", image.ExternalId, status)
if status == api.CACHED_IMAGE_STATUS_READY {
if status == api.CACHED_IMAGE_STATUS_ACTIVE {
return image.ExternalId, nil
}
err = cache.region.Delete(image.ExternalId)

View File

@@ -26,6 +26,7 @@ import (
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
"yunion.io/x/onecloud/pkg/util/imagetools"
)
@@ -50,6 +51,7 @@ const (
// https://support.huaweicloud.com/api-ims/zh-cn_topic_0020091565.html
type SImage struct {
multicloud.SImageBase
storageCache *SStoragecache
Schema string `json:"schema"`
@@ -112,7 +114,7 @@ func (self *SImage) GetStatus() string {
case ImageStatusQueued:
return api.CACHED_IMAGE_STATUS_CACHING
case ImageStatusActive:
return api.CACHED_IMAGE_STATUS_READY
return api.CACHED_IMAGE_STATUS_ACTIVE
case ImageStatusKilled:
return api.CACHED_IMAGE_STATUS_CACHE_FAILED
default:

View File

@@ -0,0 +1,25 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package multicloud
import "yunion.io/x/onecloud/pkg/util/rbacutils"
type SImageBase struct {
SVirtualResourceBase
}
func (self *SImageBase) GetPublicScope() rbacutils.TRbacScope {
return rbacutils.ScopeSystem
}

View File

@@ -29,8 +29,10 @@ import (
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
"yunion.io/x/onecloud/pkg/util/imagetools"
"yunion.io/x/onecloud/pkg/util/qemuimg"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
const (
@@ -46,6 +48,7 @@ const (
)
type SImage struct {
multicloud.SImageBase
storageCache *SStoragecache
Status string
@@ -157,7 +160,7 @@ func (image *SImage) GetStatus() string {
case QUEUED, SAVING, UPLOADING, IMPORTING:
return api.CACHED_IMAGE_STATUS_CACHING
case ACTIVE:
return api.CACHED_IMAGE_STATUS_READY
return api.CACHED_IMAGE_STATUS_ACTIVE
case DELETED, DEACTIVATED, PENDING_DELETE, KILLED:
return api.CACHED_IMAGE_STATUS_CACHE_FAILED
default:
@@ -192,6 +195,19 @@ func (image *SImage) GetImageType() string {
return cloudprovider.CachedImageTypeSystem
}
func (image *SImage) GetPublicScope() rbacutils.TRbacScope {
switch image.Visibility {
case "private":
return rbacutils.ScopeNone
default:
return rbacutils.ScopeSystem
}
}
func (image *SImage) GetProjectId() string {
return image.Owner
}
func (image *SImage) GetSizeByte() int64 {
return int64(image.Size)
}
@@ -246,17 +262,17 @@ func (image *SImage) GetCreatedAt() time.Time {
}
func (region *SRegion) GetImage(imageId string) (*SImage, error) {
images, err := region.GetImages("", "", imageId)
resource := "/v2/images/" + imageId
resp, err := region.imageGet(resource)
if err != nil {
return nil, err
return nil, errors.Wrapf(err, "imageGet(%s)", resource)
}
if len(images) == 0 {
return nil, cloudprovider.ErrNotFound
image := &SImage{}
err = resp.Unmarshal(image)
if err != nil {
return nil, errors.Wrapf(err, "resp.Unmarshal")
}
if len(images) > 1 {
return nil, cloudprovider.ErrDuplicateId
}
return &images[0], nil
return image, nil
}
func (image *SImage) GetIStoragecache() cloudprovider.ICloudStoragecache {

View File

@@ -43,11 +43,11 @@ func init() {
}
shellutils.R(&ImageOptions{}, "image-show", "Show image", func(cli *openstack.SRegion, args *ImageOptions) error {
image, err := cli.GetImages("", "", args.ID)
image, err := cli.GetImage(args.ID)
if err != nil {
return err
}
printObject(image[0])
printObject(image)
return nil
})

View File

@@ -158,7 +158,7 @@ func (cache *SStoragecache) uploadImage(ctx context.Context, userCred mcclient.T
img.storageCache = cache
return img.Id, cloudprovider.WaitStatus(img, api.CACHED_IMAGE_STATUS_READY, 15*time.Second, 3600*time.Second)
return img.Id, cloudprovider.WaitStatus(img, api.CACHED_IMAGE_STATUS_ACTIVE, 15*time.Second, 3600*time.Second)
}
func (cache *SStoragecache) CreateIImage(snapshoutId, imageName, osType, imageDesc string) (cloudprovider.ICloudImage, error) {

View File

@@ -27,6 +27,7 @@ import (
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
"yunion.io/x/onecloud/pkg/util/imagetools"
)
@@ -42,6 +43,7 @@ const (
)
type SImage struct {
multicloud.SImageBase
storageCache *SStoragecache
ImageId string // 镜像ID
@@ -140,7 +142,7 @@ func (self *SImage) GetStatus() string {
case ImageStatusCreating, ImageStatusSycing, ImageStatusImporting:
return api.CACHED_IMAGE_STATUS_CACHING
case ImageStatusNormal, ImageStatusUsing:
return api.CACHED_IMAGE_STATUS_READY
return api.CACHED_IMAGE_STATUS_ACTIVE
default:
return api.CACHED_IMAGE_STATUS_CACHE_FAILED
}

View File

@@ -581,6 +581,9 @@ func (client *SQcloudClient) getCosClient(bucket *SBucket) (*cos.Client, error)
RequestBody: client.debug,
ResponseHeader: client.debug,
ResponseBody: client.debug,
Transport: &http.Transport{
Proxy: client.cpcfg.ProxyFunc,
},
},
},
},

View File

@@ -223,7 +223,7 @@ func (self *SStoragecache) uploadImage(ctx context.Context, userCred mcclient.To
if err != nil {
return "", err
}
err = cloudprovider.WaitStatus(img, api.CACHED_IMAGE_STATUS_READY, 15*time.Second, 3600*time.Second)
err = cloudprovider.WaitStatus(img, api.CACHED_IMAGE_STATUS_ACTIVE, 15*time.Second, 3600*time.Second)
if err != nil {
return "", err
}

View File

@@ -258,8 +258,8 @@ func (self *SHost) _createVM(name, imgId string, sysDisk cloudprovider.SDiskInfo
log.Errorf("GetImage %s fail %s", imgId, err)
return "", err
}
if img.GetStatus() != api.CACHED_IMAGE_STATUS_READY {
log.Errorf("image %s status %s, expect %s", imgId, img.GetStatus(), api.CACHED_IMAGE_STATUS_READY)
if img.GetStatus() != api.CACHED_IMAGE_STATUS_ACTIVE {
log.Errorf("image %s status %s, expect %s", imgId, img.GetStatus(), api.CACHED_IMAGE_STATUS_ACTIVE)
return "", fmt.Errorf("image not ready")
}

View File

@@ -23,10 +23,12 @@ import (
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
"yunion.io/x/onecloud/pkg/util/imagetools"
)
type SImage struct {
multicloud.SImageBase
storageCache *SStoragecache
Zone string `json:"Zone"`
@@ -65,7 +67,7 @@ func (self *SImage) GetGlobalId() string {
func (self *SImage) GetStatus() string {
switch self.State {
case "Available":
return api.CACHED_IMAGE_STATUS_READY
return api.CACHED_IMAGE_STATUS_ACTIVE
case "Making":
return api.CACHED_IMAGE_STATUS_CACHING
case "Unavailable":

View File

@@ -125,7 +125,7 @@ func (self *SStoragecache) UploadImage(ctx context.Context, userCred mcclient.To
if err != nil {
log.Errorf("GetImageStatus error %s", err)
}
if img.GetStatus() == api.CACHED_IMAGE_STATUS_READY && !isForce {
if img.GetStatus() == api.CACHED_IMAGE_STATUS_ACTIVE && !isForce {
return image.ExternalId, nil
}
} else {

View File

@@ -23,13 +23,13 @@ import (
"sort"
"time"
"github.com/pkg/errors"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
"yunion.io/x/onecloud/pkg/util/httputils"
"yunion.io/x/onecloud/pkg/util/imagetools"
"yunion.io/x/onecloud/pkg/util/multipart"
@@ -45,6 +45,7 @@ type SBackupStorageRef struct {
}
type SImage struct {
multicloud.SImageBase
storageCache *SStoragecache
BackupStorageRefs []SBackupStorageRef `json:"backupStorageRefs"`
@@ -117,7 +118,7 @@ func (image *SImage) GetStatus() string {
}
switch image.Status {
case "Ready":
return api.CACHED_IMAGE_STATUS_READY
return api.CACHED_IMAGE_STATUS_ACTIVE
case "Downloading":
return api.CACHED_IMAGE_STATUS_CACHING
case "Deleted":

View File

@@ -105,7 +105,7 @@ func (scache *SStoragecache) UploadImage(ctx context.Context, userCred mcclient.
log.Errorf("GetImageStatus error %s", err)
}
status := img.GetStatus()
if api.CACHED_IMAGE_STATUS_READY == status && !isForce {
if api.CACHED_IMAGE_STATUS_ACTIVE == status && !isForce {
return image.ExternalId, nil
}
log.Debugf("image %s status %s", image.ExternalId, status)
@@ -131,7 +131,7 @@ func (self *SStoragecache) uploadImage(ctx context.Context, userCred mcclient.To
return "", err
}
img.storageCache = self
err = cloudprovider.WaitStatus(img, api.CACHED_IMAGE_STATUS_READY, time.Second*5, time.Minute*20) //windows镜像转换比较慢等待时间稍微设长一些
err = cloudprovider.WaitStatus(img, api.CACHED_IMAGE_STATUS_ACTIVE, time.Second*5, time.Minute*20) //windows镜像转换比较慢等待时间稍微设长一些
if err != nil {
log.Errorf("waitting for image %s(%s) status ready timeout", img.Name, img.UUID)
}

View File

@@ -98,7 +98,7 @@ func buildHosts(result *core.SchedResultItemList, groups map[string]*models.SGro
// sortHost sorts the host for guest that is the backup one of the high-availability guest
// if isBackup is true and the master one if isBackup is false.
func sortHosts(hosts []*sSchedResultItem, guestInfo *sGuestInfo, isBackup *bool) {
sortIndexi, sortIndexj := make([]int64, 4), make([]int64, 4)
sortIndexi, sortIndexj := make([]int64, 5), make([]int64, 5)
sort.Slice(hosts, func(i, j int) bool {
switch {
case isBackup == nil:

View File

@@ -526,6 +526,10 @@ func (set Elasticips) NewModel() db.IModel {
func (set Elasticips) AddModel(i db.IModel) {
m := i.(*Elasticip)
if m.IpAddr == "" || m.NetworkId == "" {
// eip records can exist with network id and ip addr not set
return
}
set[m.Id] = m
}

View File

@@ -26,6 +26,7 @@ import (
"github.com/gorilla/mux"
"yunion.io/x/log"
"yunion.io/x/pkg/util/signalutils"
api "yunion.io/x/onecloud/pkg/apis/webconsole"
"yunion.io/x/onecloud/pkg/appsrv"
@@ -66,9 +67,15 @@ func StartService() {
common_options.StartOptionManager(opts, opts.ConfigSyncPeriodSeconds, api.SERVICE_TYPE, api.SERVICE_VERSION, o.OnOptionsChange)
registerSigTraps()
start()
}
func registerSigTraps() {
signalutils.SetDumpStackSignal()
signalutils.StartTrap()
}
func start() {
baseOpts := &o.Options.BaseOptions
// commonOpts := &o.Options.CommonOptions

View File

@@ -102,6 +102,10 @@ func (p *Pty) Resize(size *pty.Winsize) {
func (p *Pty) Stop() (err error) {
var errs []error
defer func() {
p.Cmd, p.Pty = nil, nil
}()
defer func() {
err = errors.NewAggregate(errs)
}()
@@ -139,8 +143,5 @@ func (p *Pty) Stop() (err error) {
}
}()
defer func() {
p.Cmd, p.Pty = nil, nil
}()
return
}