mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/yunionio/cloudpods.git
synced 2026-09-20 16:13:56 +08:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
301006e213 | ||
|
|
950a2c29fb | ||
|
|
558872db27 | ||
|
|
6386391bf4 | ||
|
|
d298c75448 | ||
|
|
28cb75f41b | ||
|
|
560a68d379 | ||
|
|
9e597db90a | ||
|
|
9c9cb17d32 | ||
|
|
cc96c01c00 | ||
|
|
cb22077722 | ||
|
|
8e3c173373 | ||
|
|
45e092bd2d | ||
|
|
4b2d67de42 | ||
|
|
6677c30a5d | ||
|
|
64593fc882 |
2
Makefile
2
Makefile
@@ -313,7 +313,7 @@ REGISTRY ?= "registry.cn-beijing.aliyuncs.com/yunionio"
|
||||
VERSION ?= $(shell git describe --exact-match 2> /dev/null || \
|
||||
git describe --match=$(git rev-parse --short=8 HEAD) --always --dirty --abbrev=8)
|
||||
|
||||
image: clean
|
||||
image:
|
||||
mkdir -p $(ROOT_DIR)/_output
|
||||
DEBUG=$(DEBUG) ARCH=$(ARCH) TAG=$(VERSION) REGISTRY=$(REGISTRY) $(ROOT_DIR)/scripts/docker_push.sh $(filter-out $@,$(MAKECMDGOALS))
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ func init() {
|
||||
Schedtag string `help:"filter storage by schedtag"`
|
||||
|
||||
HostSchedtagId string `help:"filter storage by host schedtag"`
|
||||
ImageId string `help:"filter storage by image"`
|
||||
}
|
||||
R(&StorageListOptions{}, "storage-list", "List storages", func(s *mcclient.ClientSession, opts *StorageListOptions) error {
|
||||
params, err := options.ListStructToParams(opts)
|
||||
|
||||
@@ -186,4 +186,7 @@ type StorageListInput struct {
|
||||
|
||||
// filter by host schedtag
|
||||
HostSchedtagId string `json:"host_schedtag_id"`
|
||||
|
||||
// filter by cachedimage
|
||||
ImageId string `json:"image_id"`
|
||||
}
|
||||
|
||||
@@ -199,12 +199,15 @@ type MetadataResourceListInput struct {
|
||||
// 返回资源的标签不包含用户标签
|
||||
WithoutUserMeta *bool `json:"without_user_meta"`
|
||||
|
||||
// 返回资源的标签包含用户标签
|
||||
// 返回包含用户标签的资源
|
||||
WithUserMeta *bool `json:"with_user_meta"`
|
||||
|
||||
// 返回资源的标签包含外部标签
|
||||
// 返回包含外部标签的资源
|
||||
WithCloudMeta *bool `json:"with_cloud_meta"`
|
||||
|
||||
// 返回包含任意标签的资源
|
||||
WithAnyMeta *bool `json:"with_any_meta"`
|
||||
|
||||
// 返回列表数据中包含资源的标签数据(Metadata)
|
||||
WithMeta *bool `json:"with_meta"`
|
||||
}
|
||||
|
||||
@@ -107,12 +107,7 @@ func (manager *SDomainizedResourceBaseManager) ListItemFilter(
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
if len(query.ProjectDomainIds) > 0 {
|
||||
// make sure ids are not utf8 string
|
||||
idList := make([]string, 0)
|
||||
for _, pid := range query.ProjectDomainIds {
|
||||
if !stringutils2.IsUtf8(pid) {
|
||||
idList = append(idList, pid)
|
||||
}
|
||||
}
|
||||
idList := stringutils2.RemoveUtf8Strings(query.ProjectDomainIds)
|
||||
tenants := TenantCacheManager.GetDomainQuery().SubQuery()
|
||||
subq := tenants.Query(tenants.Field("id")).Filter(sqlchemy.OR(
|
||||
sqlchemy.In(tenants.Field("id"), idList),
|
||||
|
||||
@@ -90,10 +90,10 @@ func (meta *SMetadataResourceBaseModelManager) ListItemFilter(
|
||||
}
|
||||
}
|
||||
|
||||
if input.WithMeta != nil {
|
||||
if input.WithAnyMeta != nil {
|
||||
metadatas := Metadata.Query().Equals("obj_type", manager.Keyword()).SubQuery()
|
||||
sq := metadatas.Query(metadatas.Field("obj_id")).Distinct().SubQuery()
|
||||
if *input.WithMeta {
|
||||
if *input.WithAnyMeta {
|
||||
q = q.Filter(sqlchemy.In(q.Field("id"), sq))
|
||||
} else {
|
||||
q = q.Filter(sqlchemy.NotIn(q.Field("id"), sq))
|
||||
|
||||
@@ -102,12 +102,7 @@ func (manager *SProjectizedResourceBaseManager) ListItemFilter(
|
||||
}
|
||||
if len(query.ProjectIds) > 0 {
|
||||
// make sure ids are not utf8 string
|
||||
idList := make([]string, 0)
|
||||
for _, pid := range query.ProjectIds {
|
||||
if !stringutils2.IsUtf8(pid) {
|
||||
idList = append(idList, pid)
|
||||
}
|
||||
}
|
||||
idList := stringutils2.RemoveUtf8Strings(query.ProjectIds)
|
||||
tenants := TenantCacheManager.GetTenantQuery().SubQuery()
|
||||
subq := tenants.Query(tenants.Field("id")).Filter(sqlchemy.OR(
|
||||
sqlchemy.In(tenants.Field("id"), idList),
|
||||
|
||||
@@ -518,7 +518,7 @@ func _managedResourceFilterByAccount(managerIdFieldName string, q *sqlchemy.SQue
|
||||
if len(cloudaccountArr) > 0 {
|
||||
cpq := CloudaccountManager.Query().SubQuery()
|
||||
subcpq := cpq.Query(cpq.Field("id")).Filter(sqlchemy.OR(
|
||||
sqlchemy.In(cpq.Field("id"), cloudaccountArr),
|
||||
sqlchemy.In(cpq.Field("id"), stringutils2.RemoveUtf8Strings(cloudaccountArr)),
|
||||
sqlchemy.In(cpq.Field("name"), cloudaccountArr),
|
||||
)).SubQuery()
|
||||
subq := CloudproviderManager.Query("id").In("cloudaccount_id", subcpq).SubQuery()
|
||||
|
||||
@@ -1399,6 +1399,17 @@ func (manager *SStorageManager) ListItemFilter(
|
||||
q = q.In("id", subq.SubQuery())
|
||||
}
|
||||
|
||||
if len(query.ImageId) > 0 {
|
||||
image, err := CachedimageManager.getImageInfo(ctx, userCred, query.ImageId, false)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "CachedimageManager.getImageInfo")
|
||||
}
|
||||
subq := StorageManager.Query("id")
|
||||
storagecaches := StoragecachedimageManager.Query("storagecache_id").Equals("cachedimage_id", image.Id).SubQuery()
|
||||
subq = subq.Join(storagecaches, sqlchemy.Equals(subq.Field("storagecache_id"), storagecaches.Field("storagecache_id")))
|
||||
q = q.In("id", subq.SubQuery())
|
||||
}
|
||||
|
||||
return q, err
|
||||
}
|
||||
|
||||
|
||||
@@ -26,9 +26,10 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
syncAccountWorker *appsrv.SWorkerManager
|
||||
syncWorkers []*appsrv.SWorkerManager
|
||||
syncWorkerRing *hashring.HashRing
|
||||
syncSecgroupWorker *appsrv.SWorkerManager
|
||||
syncAccountWorker *appsrv.SWorkerManager
|
||||
syncWorkers []*appsrv.SWorkerManager
|
||||
syncWorkerRing *hashring.HashRing
|
||||
)
|
||||
|
||||
func InitSyncWorkers(count int) {
|
||||
@@ -50,6 +51,12 @@ func InitSyncWorkers(count int) {
|
||||
2048,
|
||||
true,
|
||||
)
|
||||
syncSecgroupWorker = appsrv.NewWorkerManager(
|
||||
"syncSecgroupProbeWorkerManager",
|
||||
1,
|
||||
2048,
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
func RunSyncCloudproviderRegionTask(key string, syncFunc func()) {
|
||||
@@ -62,3 +69,7 @@ func RunSyncCloudproviderRegionTask(key string, syncFunc func()) {
|
||||
func RunSyncCloudAccountTask(probeFunc func()) {
|
||||
syncAccountWorker.Run(probeFunc, nil, nil)
|
||||
}
|
||||
|
||||
func RunSyncSecgroupTask(syncFunc func()) {
|
||||
syncAccountWorker.Run(syncFunc, nil, nil)
|
||||
}
|
||||
|
||||
@@ -1480,95 +1480,109 @@ func (self *SManagedVirtualizationRegionDriver) RequestSyncSecurityGroup(ctx con
|
||||
return "", errors.Wrap(err, "SSecurityGroupCache.Register")
|
||||
}
|
||||
|
||||
iRegion, err := vpc.GetIRegion()
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "vpc.GetIRegion")
|
||||
}
|
||||
waitChan := make(chan error)
|
||||
|
||||
var iSecgroup cloudprovider.ICloudSecurityGroup = nil
|
||||
if len(cache.ExternalId) > 0 {
|
||||
iSecgroup, err = iRegion.GetISecurityGroupById(cache.ExternalId)
|
||||
if err != nil {
|
||||
if errors.Cause(err) != cloudprovider.ErrNotFound {
|
||||
return "", errors.Wrap(err, "iRegion.GetSecurityGroupById")
|
||||
}
|
||||
cache.ExternalId = ""
|
||||
}
|
||||
}
|
||||
|
||||
if len(cache.ExternalId) == 0 {
|
||||
if strings.ToLower(secgroup.Name) == "default" { //避免有些云不支持default关键字
|
||||
secgroup.Name = "DefaultGroup"
|
||||
}
|
||||
// 避免有的云不支持重名安全组
|
||||
randomString := func(prefix string, length int) string {
|
||||
return fmt.Sprintf("%s-%s", prefix, rand.String(length))
|
||||
}
|
||||
opts := &cloudprovider.SecurityGroupFilterOptions{
|
||||
Name: randomString(secgroup.Name, 1),
|
||||
VpcId: vpcId,
|
||||
ProjectId: remoteProjectId,
|
||||
}
|
||||
for i := 2; i < 30; i++ {
|
||||
_, err := iRegion.GetISecurityGroupByName(opts)
|
||||
models.RunSyncSecgroupTask(func() {
|
||||
err := func() error {
|
||||
iRegion, err := vpc.GetIRegion()
|
||||
if err != nil {
|
||||
if errors.Cause(err) == cloudprovider.ErrNotFound {
|
||||
break
|
||||
}
|
||||
if errors.Cause(err) != cloudprovider.ErrDuplicateId {
|
||||
return "", err
|
||||
return errors.Wrap(err, "vpc.GetIRegion")
|
||||
}
|
||||
|
||||
var iSecgroup cloudprovider.ICloudSecurityGroup = nil
|
||||
if len(cache.ExternalId) > 0 {
|
||||
iSecgroup, err = iRegion.GetISecurityGroupById(cache.ExternalId)
|
||||
if err != nil {
|
||||
if errors.Cause(err) != cloudprovider.ErrNotFound {
|
||||
return errors.Wrap(err, "iRegion.GetSecurityGroupById")
|
||||
}
|
||||
cache.ExternalId = ""
|
||||
}
|
||||
}
|
||||
opts.Name = randomString(secgroup.Name, i)
|
||||
}
|
||||
conf := &cloudprovider.SecurityGroupCreateInput{
|
||||
Name: opts.Name,
|
||||
Desc: secgroup.Description,
|
||||
VpcId: vpcId,
|
||||
ProjectId: remoteProjectId,
|
||||
Rules: secgroup.GetSecRules(""),
|
||||
}
|
||||
iSecgroup, err = iRegion.CreateISecurityGroup(conf)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "iRegion.CreateISecurityGroup")
|
||||
}
|
||||
}
|
||||
|
||||
_, err = db.Update(cache, func() error {
|
||||
cache.ExternalId = iSecgroup.GetGlobalId()
|
||||
cache.Name = iSecgroup.GetName()
|
||||
cache.Status = api.SECGROUP_CACHE_STATUS_READY
|
||||
return nil
|
||||
if len(cache.ExternalId) == 0 {
|
||||
if strings.ToLower(secgroup.Name) == "default" { //避免有些云不支持default关键字
|
||||
secgroup.Name = "DefaultGroup"
|
||||
}
|
||||
// 避免有的云不支持重名安全组
|
||||
randomString := func(prefix string, length int) string {
|
||||
return fmt.Sprintf("%s-%s", prefix, rand.String(length))
|
||||
}
|
||||
opts := &cloudprovider.SecurityGroupFilterOptions{
|
||||
Name: randomString(secgroup.Name, 1),
|
||||
VpcId: vpcId,
|
||||
ProjectId: remoteProjectId,
|
||||
}
|
||||
for i := 2; i < 30; i++ {
|
||||
_, err := iRegion.GetISecurityGroupByName(opts)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == cloudprovider.ErrNotFound {
|
||||
break
|
||||
}
|
||||
if errors.Cause(err) != cloudprovider.ErrDuplicateId {
|
||||
return errors.Wrapf(err, "GetISecurityGroupByName")
|
||||
}
|
||||
}
|
||||
opts.Name = randomString(secgroup.Name, i)
|
||||
}
|
||||
conf := &cloudprovider.SecurityGroupCreateInput{
|
||||
Name: opts.Name,
|
||||
Desc: secgroup.Description,
|
||||
VpcId: vpcId,
|
||||
ProjectId: remoteProjectId,
|
||||
Rules: secgroup.GetSecRules(""),
|
||||
}
|
||||
iSecgroup, err = iRegion.CreateISecurityGroup(conf)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "iRegion.CreateISecurityGroup")
|
||||
}
|
||||
}
|
||||
|
||||
_, err = db.Update(cache, func() error {
|
||||
cache.ExternalId = iSecgroup.GetGlobalId()
|
||||
cache.Name = iSecgroup.GetName()
|
||||
cache.Status = api.SECGROUP_CACHE_STATUS_READY
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "db.Update")
|
||||
}
|
||||
|
||||
rules, err := iSecgroup.GetRules()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "iSecgroup.GetRules")
|
||||
}
|
||||
|
||||
maxPriority := region.GetDriver().GetSecurityGroupRuleMaxPriority()
|
||||
minPriority := region.GetDriver().GetSecurityGroupRuleMinPriority()
|
||||
|
||||
defaultInRule := region.GetDriver().GetDefaultSecurityGroupInRule()
|
||||
defaultOutRule := region.GetDriver().GetDefaultSecurityGroupOutRule()
|
||||
order := region.GetDriver().GetSecurityGroupRuleOrder()
|
||||
onlyAllowRules := region.GetDriver().IsOnlySupportAllowRules()
|
||||
|
||||
localRules := secrules.SecurityRuleSet(secgroup.GetSecRules(""))
|
||||
|
||||
common, inAdds, outAdds, inDels, outDels := cloudprovider.CompareRules(minPriority, maxPriority, order, localRules, rules, defaultInRule, defaultOutRule, onlyAllowRules, false)
|
||||
|
||||
if len(inAdds) == 0 && len(inDels) == 0 && len(outAdds) == 0 && len(outDels) == 0 {
|
||||
return nil
|
||||
}
|
||||
return iSecgroup.SyncRules(common, inAdds, outAdds, inDels, outDels)
|
||||
}()
|
||||
|
||||
waitChan <- err
|
||||
})
|
||||
|
||||
err = <-waitChan
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "db.Update")
|
||||
return "", err
|
||||
}
|
||||
|
||||
rules, err := iSecgroup.GetRules()
|
||||
cache, err = models.SecurityGroupCacheManager.Register(ctx, userCred, secgroup.Id, vpcId, region.Id, vpc.ManagerId, remoteProjectId)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "iSecgroup.GetRules")
|
||||
}
|
||||
|
||||
maxPriority := region.GetDriver().GetSecurityGroupRuleMaxPriority()
|
||||
minPriority := region.GetDriver().GetSecurityGroupRuleMinPriority()
|
||||
|
||||
defaultInRule := region.GetDriver().GetDefaultSecurityGroupInRule()
|
||||
defaultOutRule := region.GetDriver().GetDefaultSecurityGroupOutRule()
|
||||
order := region.GetDriver().GetSecurityGroupRuleOrder()
|
||||
onlyAllowRules := region.GetDriver().IsOnlySupportAllowRules()
|
||||
|
||||
localRules := secrules.SecurityRuleSet(secgroup.GetSecRules(""))
|
||||
|
||||
common, inAdds, outAdds, inDels, outDels := cloudprovider.CompareRules(minPriority, maxPriority, order, localRules, rules, defaultInRule, defaultOutRule, onlyAllowRules, false)
|
||||
|
||||
if len(inAdds) == 0 && len(inDels) == 0 && len(outAdds) == 0 && len(outDels) == 0 {
|
||||
return cache.ExternalId, nil
|
||||
}
|
||||
|
||||
err = iSecgroup.SyncRules(common, inAdds, outAdds, inDels, outDels)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "iSecgroup.SyncRules")
|
||||
return "", errors.Wrap(err, "SSecurityGroupCache.Register")
|
||||
}
|
||||
|
||||
return cache.ExternalId, nil
|
||||
|
||||
@@ -133,12 +133,7 @@ func (manager *SIdentityBaseResourceManager) ListItemFilter(
|
||||
// override manager.SDomainizedResourceBaseManager.ListItemFilter()
|
||||
if len(query.ProjectDomainIds) > 0 {
|
||||
// make sure ids are not utf8 string
|
||||
idList := make([]string, 0)
|
||||
for _, pid := range query.ProjectDomainIds {
|
||||
if !stringutils2.IsUtf8(pid) {
|
||||
idList = append(idList, pid)
|
||||
}
|
||||
}
|
||||
idList := stringutils2.RemoveUtf8Strings(query.ProjectDomainIds)
|
||||
domains := DomainManager.Query().SubQuery()
|
||||
subq := domains.Query(domains.Field("id")).Filter(sqlchemy.OR(
|
||||
sqlchemy.In(domains.Field("id"), idList),
|
||||
|
||||
@@ -93,6 +93,12 @@ func (this *ImageManager) GetByName(session *mcclient.ClientSession, id string,
|
||||
}
|
||||
|
||||
func (this *ImageManager) Get(session *mcclient.ClientSession, id string, params jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
// hack: some GetPropertiesMethod must use HTTP GET action like:
|
||||
// - GET /images/distinct-field
|
||||
// hard code this id currently, should found a better solution
|
||||
if ok, _ := utils.InStringArray(id, []string{"distinct-field"}); ok {
|
||||
return this.ResourceManager.Get(session, id, params)
|
||||
}
|
||||
r, e := this.GetById(session, id, params)
|
||||
if e == nil {
|
||||
return r, e
|
||||
|
||||
@@ -179,7 +179,7 @@ func (self *SHost) GetInstanceById(instanceId string) (*SInstance, error) {
|
||||
}
|
||||
|
||||
func (self *SHost) CreateVM(desc *cloudprovider.SManagedVMCreateConfig) (cloudprovider.ICloudVM, error) {
|
||||
vmId, err := self._createVM(desc.Name, desc.ExternalImageId, desc.SysDisk, desc.Cpu, desc.MemoryMB, desc.InstanceType, desc.ExternalNetworkId, desc.IpAddr, desc.Description, desc.Password, desc.DataDisks, desc.PublicKey, desc.ExternalSecgroupId, desc.UserData, desc.BillingCycle, desc.ProjectId)
|
||||
vmId, err := self._createVM(desc.Name, desc.ExternalImageId, desc.SysDisk, desc.Cpu, desc.MemoryMB, desc.InstanceType, desc.ExternalNetworkId, desc.IpAddr, desc.Description, desc.Password, desc.DataDisks, desc.PublicKey, desc.ExternalSecgroupId, desc.UserData, desc.BillingCycle, desc.ProjectId, desc.OsType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -194,7 +194,7 @@ func (self *SHost) CreateVM(desc *cloudprovider.SManagedVMCreateConfig) (cloudpr
|
||||
func (self *SHost) _createVM(name string, imgId string, sysDisk cloudprovider.SDiskInfo, cpu int, memMB int, instanceType string,
|
||||
vswitchId string, ipAddr string, desc string, passwd string,
|
||||
dataDisks []cloudprovider.SDiskInfo, publicKey string, secgroupId string,
|
||||
userData string, bc *billing.SBillingCycle, projectId string) (string, error) {
|
||||
userData string, bc *billing.SBillingCycle, projectId, osType string) (string, error) {
|
||||
net := self.zone.getNetworkById(vswitchId)
|
||||
if net == nil {
|
||||
return "", fmt.Errorf("invalid switch ID %s", vswitchId)
|
||||
@@ -249,7 +249,7 @@ func (self *SHost) _createVM(name string, imgId string, sysDisk cloudprovider.SD
|
||||
|
||||
if len(instanceType) > 0 {
|
||||
log.Debugf("Try instancetype : %s", instanceType)
|
||||
vmId, err := self.zone.region.CreateInstance(name, imgId, instanceType, secgroupId, self.zone.ZoneId, desc, passwd, disks, vswitchId, ipAddr, keypair, userData, bc, projectId)
|
||||
vmId, err := self.zone.region.CreateInstance(name, imgId, instanceType, secgroupId, self.zone.ZoneId, desc, passwd, disks, vswitchId, ipAddr, keypair, userData, bc, projectId, osType)
|
||||
if err != nil {
|
||||
log.Errorf("Failed for %s: %s", instanceType, err)
|
||||
return "", fmt.Errorf("Failed to create specification %s.%s", instanceType, err.Error())
|
||||
@@ -269,7 +269,7 @@ func (self *SHost) _createVM(name string, imgId string, sysDisk cloudprovider.SD
|
||||
for _, instType := range instanceTypes {
|
||||
instanceTypeId := instType.InstanceTypeId
|
||||
log.Debugf("Try instancetype : %s", instanceTypeId)
|
||||
vmId, err = self.zone.region.CreateInstance(name, imgId, instanceTypeId, secgroupId, self.zone.ZoneId, desc, passwd, disks, vswitchId, ipAddr, keypair, userData, bc, projectId)
|
||||
vmId, err = self.zone.region.CreateInstance(name, imgId, instanceTypeId, secgroupId, self.zone.ZoneId, desc, passwd, disks, vswitchId, ipAddr, keypair, userData, bc, projectId, osType)
|
||||
if err != nil {
|
||||
log.Errorf("Failed for %s: %s", instanceTypeId, err)
|
||||
} else {
|
||||
|
||||
@@ -32,6 +32,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/multicloud"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -480,7 +481,7 @@ func (self *SInstance) GetVNCInfo() (jsonutils.JSONObject, error) {
|
||||
}
|
||||
|
||||
func (self *SInstance) UpdateVM(ctx context.Context, name string) error {
|
||||
return self.host.zone.region.UpdateVM(self.InstanceId, name)
|
||||
return self.host.zone.region.UpdateVM(self.InstanceId, name, self.OSType)
|
||||
}
|
||||
|
||||
func (self *SInstance) DeployVM(ctx context.Context, name string, username string, password string, publicKey string, deleteKeypair bool, description string) error {
|
||||
@@ -548,7 +549,7 @@ func (self *SRegion) GetInstance(instanceId string) (*SInstance, error) {
|
||||
|
||||
func (self *SRegion) CreateInstance(name string, imageId string, instanceType string, securityGroupId string,
|
||||
zoneId string, desc string, passwd string, disks []SDisk, vSwitchId string, ipAddr string,
|
||||
keypair string, userData string, bc *billing.SBillingCycle, projectId string) (string, error) {
|
||||
keypair string, userData string, bc *billing.SBillingCycle, projectId, osType string) (string, error) {
|
||||
params := make(map[string]string)
|
||||
params["RegionId"] = self.RegionId
|
||||
params["ImageId"] = imageId
|
||||
@@ -560,7 +561,7 @@ func (self *SRegion) CreateInstance(name string, imageId string, instanceType st
|
||||
params["InternetChargeType"] = "PayByTraffic"
|
||||
params["InternetMaxBandwidthIn"] = "200"
|
||||
params["InternetMaxBandwidthOut"] = "100"
|
||||
params["HostName"] = name
|
||||
params["HostName"] = stringutils2.GenerateHostName(name, osType)
|
||||
if len(passwd) > 0 {
|
||||
params["Password"] = passwd
|
||||
} else {
|
||||
@@ -776,7 +777,7 @@ func (self *SRegion) DeployVM(instanceId string, name string, password string, k
|
||||
|
||||
if len(name) > 0 && instance.InstanceName != name {
|
||||
params["InstanceName"] = name
|
||||
params["HostName"] = name
|
||||
params["HostName"] = stringutils2.GenerateHostName(name, instance.OSType)
|
||||
}
|
||||
|
||||
if len(description) > 0 && instance.Description != description {
|
||||
@@ -808,14 +809,14 @@ func (self *SInstance) DeleteVM(ctx context.Context) error {
|
||||
return cloudprovider.WaitDeleted(self, 10*time.Second, 300*time.Second) // 5minutes
|
||||
}
|
||||
|
||||
func (self *SRegion) UpdateVM(instanceId string, hostname string) error {
|
||||
func (self *SRegion) UpdateVM(instanceId string, name, osType string) error {
|
||||
/*
|
||||
api: ModifyInstanceAttribute
|
||||
https://help.aliyun.com/document_detail/25503.html?spm=a2c4g.11186623.4.1.DrgpjW
|
||||
*/
|
||||
params := make(map[string]string)
|
||||
params["HostName"] = hostname
|
||||
params["InstanceName"] = hostname
|
||||
params["HostName"] = stringutils2.GenerateHostName(name, osType)
|
||||
params["InstanceName"] = name
|
||||
return self.modifyInstanceAttribute(instanceId, params)
|
||||
}
|
||||
|
||||
|
||||
@@ -173,18 +173,23 @@ func NewVNICDev(host *SHost, mac, driver string, bridge string, vlanId int32, ke
|
||||
var backing types.BaseVirtualDeviceBackingInfo
|
||||
switch inet.(type) {
|
||||
case *SDistributedVirtualPortgroup:
|
||||
// net := inet.(*SDistributedVirtualPortgroup)
|
||||
// port, err := net.FindPort()
|
||||
//if err != nil {
|
||||
// return nil, errors.Wrap(err, "net.FindPort")
|
||||
// }
|
||||
// if port == nil {
|
||||
// return nil, fmt.Errorf("no active port for dvportgroup %q", net.GetName())
|
||||
// }
|
||||
net := inet.(*SDistributedVirtualPortgroup)
|
||||
port, err := net.FindPort()
|
||||
dvpg := net.getMODVPortgroup()
|
||||
uuid, err := net.GetDVSUuid()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "net.FindPort")
|
||||
}
|
||||
if port == nil {
|
||||
return nil, errors.Error("no valid port on DVS, exhausted")
|
||||
return nil, errors.Wrap(err, "GetDVSUuid")
|
||||
}
|
||||
portCon := types.DistributedVirtualSwitchPortConnection{
|
||||
PortgroupKey: port.PortgroupKey,
|
||||
SwitchUuid: port.DvsUuid,
|
||||
PortKey: port.Key,
|
||||
PortgroupKey: dvpg.Key,
|
||||
SwitchUuid: uuid,
|
||||
}
|
||||
backing = &types.VirtualEthernetCardDistributedVirtualPortBackingInfo{Port: portCon}
|
||||
case *SNetwork:
|
||||
|
||||
@@ -44,7 +44,7 @@ const (
|
||||
)
|
||||
|
||||
var NETWORK_PROPS = []string{"name", "parent", "summary", "host", "vm"}
|
||||
var DVPORTGROUP_PROPS = []string{"name", "parent", "summary", "host", "vm", "config"}
|
||||
var DVPORTGROUP_PROPS = []string{"name", "parent", "summary", "host", "vm", "config", "key"}
|
||||
|
||||
type SNetwork struct {
|
||||
SManagedObject
|
||||
@@ -185,6 +185,16 @@ func (net *SDistributedVirtualPortgroup) Uplink() bool {
|
||||
return *dvpg.Config.Uplink
|
||||
}
|
||||
|
||||
func (net *SDistributedVirtualPortgroup) GetDVSUuid() (string, error) {
|
||||
dvgp := net.getMODVPortgroup()
|
||||
var dvs mo.DistributedVirtualSwitch
|
||||
err := net.manager.reference2Object(*dvgp.Config.DistributedVirtualSwitch, []string{"uuid"}, &dvs)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "reference2Object")
|
||||
}
|
||||
return dvs.Uuid, nil
|
||||
}
|
||||
|
||||
func (net *SDistributedVirtualPortgroup) FindPort() (*types.DistributedVirtualPort, error) {
|
||||
dvgp := net.getMODVPortgroup()
|
||||
odvs := object.NewDistributedVirtualSwitch(net.manager.client.Client, *dvgp.Config.DistributedVirtualSwitch)
|
||||
|
||||
@@ -64,7 +64,7 @@ func (self *SHost) CreateVM(desc *cloudprovider.SManagedVMCreateConfig) (cloudpr
|
||||
desc.InstanceType, desc.ExternalNetworkId,
|
||||
desc.IpAddr, desc.Description, desc.Password,
|
||||
desc.DataDisks, desc.PublicKey, desc.ExternalSecgroupId,
|
||||
desc.UserData, desc.BillingCycle, desc.ProjectId, desc.PublicIpBw, desc.PublicIpChargeType, desc.Tags)
|
||||
desc.UserData, desc.BillingCycle, desc.ProjectId, desc.PublicIpBw, desc.PublicIpChargeType, desc.Tags, desc.OsType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -79,7 +79,7 @@ func (self *SHost) _createVM(name string, imgId string, sysDisk cloudprovider.SD
|
||||
networkId string, ipAddr string, desc string, passwd string,
|
||||
diskSizes []cloudprovider.SDiskInfo, publicKey string, secgroupId string, userData string, bc *billing.SBillingCycle, projectId string,
|
||||
publicIpBw int, publicIpChargeType cloudprovider.TElasticipChargeType,
|
||||
tags map[string]string,
|
||||
tags map[string]string, osType string,
|
||||
) (string, error) {
|
||||
net := self.zone.getNetworkById(networkId)
|
||||
if net == nil {
|
||||
@@ -130,7 +130,7 @@ func (self *SHost) _createVM(name string, imgId string, sysDisk cloudprovider.SD
|
||||
|
||||
if len(instanceType) > 0 {
|
||||
log.Debugf("Try instancetype : %s", instanceType)
|
||||
vmId, err := self.zone.region.CreateInstance(name, imgId, instanceType, secgroupId, self.zone.Zone, desc, passwd, disks, networkId, ipAddr, keypair, userData, bc, projectId, publicIpBw, publicIpChargeType, tags)
|
||||
vmId, err := self.zone.region.CreateInstance(name, imgId, instanceType, secgroupId, self.zone.Zone, desc, passwd, disks, networkId, ipAddr, keypair, userData, bc, projectId, publicIpBw, publicIpChargeType, tags, osType)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "Failed to create specification %s", instanceType)
|
||||
}
|
||||
@@ -149,7 +149,7 @@ func (self *SHost) _createVM(name string, imgId string, sysDisk cloudprovider.SD
|
||||
for _, instType := range instanceTypes {
|
||||
instanceTypeId := instType.InstanceType
|
||||
log.Debugf("Try instancetype : %s", instanceTypeId)
|
||||
vmId, err = self.zone.region.CreateInstance(name, imgId, instanceTypeId, secgroupId, self.zone.Zone, desc, passwd, disks, networkId, ipAddr, keypair, userData, bc, projectId, publicIpBw, publicIpChargeType, tags)
|
||||
vmId, err = self.zone.region.CreateInstance(name, imgId, instanceTypeId, secgroupId, self.zone.Zone, desc, passwd, disks, networkId, ipAddr, keypair, userData, bc, projectId, publicIpBw, publicIpChargeType, tags, osType)
|
||||
if err != nil {
|
||||
log.Errorf("Failed for %s: %s", instanceTypeId, err)
|
||||
} else {
|
||||
|
||||
@@ -31,6 +31,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/multicloud"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -419,7 +420,7 @@ func (self *SInstance) GetVNCInfo() (jsonutils.JSONObject, error) {
|
||||
}
|
||||
|
||||
func (self *SInstance) UpdateVM(ctx context.Context, name string) error {
|
||||
return self.host.zone.region.UpdateVM(self.InstanceId, name)
|
||||
return self.host.zone.region.UpdateVM(self.InstanceId, name, self.GetOSType())
|
||||
}
|
||||
|
||||
func (self *SInstance) DeployVM(ctx context.Context, name string, username string, password string, publicKey string, deleteKeypair bool, description string) error {
|
||||
@@ -496,7 +497,7 @@ func (self *SRegion) CreateInstance(name string, imageId string, instanceType st
|
||||
zoneId string, desc string, passwd string, disks []SDisk, networkId string, ipAddr string,
|
||||
keypair string, userData string, bc *billing.SBillingCycle, projectId string,
|
||||
publicIpBw int, publicIpChargeType cloudprovider.TElasticipChargeType,
|
||||
tags map[string]string,
|
||||
tags map[string]string, osType string,
|
||||
) (string, error) {
|
||||
params := make(map[string]string)
|
||||
params["Region"] = self.Region
|
||||
@@ -508,7 +509,7 @@ func (self *SRegion) CreateInstance(name string, imageId string, instanceType st
|
||||
params["Placement.ProjectId"] = projectId
|
||||
}
|
||||
params["InstanceName"] = name
|
||||
params["HostName"] = name
|
||||
params["HostName"] = stringutils2.GenerateHostName(name, osType)
|
||||
|
||||
bandwidth := publicIpBw
|
||||
if publicIpBw == 0 {
|
||||
@@ -717,9 +718,9 @@ func (self *SInstance) DeleteVM(ctx context.Context) error {
|
||||
return cloudprovider.WaitDeleted(self, 10*time.Second, 300*time.Second) // 5minutes
|
||||
}
|
||||
|
||||
func (self *SRegion) UpdateVM(instanceId string, hostname string) error {
|
||||
func (self *SRegion) UpdateVM(instanceId string, name, osType string) error {
|
||||
params := make(map[string]string)
|
||||
params["HostName"] = hostname
|
||||
params["HostName"] = stringutils2.GenerateHostName(name, osType)
|
||||
return self.modifyInstanceAttribute(instanceId, params)
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,16 @@ func IsUtf8(str string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func RemoveUtf8Strings(idOrNames []string) []string {
|
||||
ids := make([]string, 0)
|
||||
for _, idOrName := range idOrNames {
|
||||
if !IsUtf8(idOrName) {
|
||||
ids = append(ids, idOrName)
|
||||
}
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
func IsPrintableAscii(b byte) bool {
|
||||
if b >= 32 && b <= 126 {
|
||||
return true
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package stringutils2
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -34,6 +35,31 @@ func TestIsUtf8(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveUtf8Strings(t *testing.T) {
|
||||
cases := []struct {
|
||||
in []string
|
||||
want []string
|
||||
}{
|
||||
{
|
||||
in: []string{},
|
||||
want: []string{},
|
||||
},
|
||||
{
|
||||
in: []string{"en", "中文"},
|
||||
want: []string{"en"},
|
||||
},
|
||||
{
|
||||
in: []string{"中文"},
|
||||
want: []string{},
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
if got := RemoveUtf8Strings(c.in); !reflect.DeepEqual(got, c.want) {
|
||||
t.Errorf("RemoveUtf8Strings %s got %v want %v", c.in, got, c.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsPrintableAscii(t *testing.T) {
|
||||
cases := []struct {
|
||||
in string
|
||||
|
||||
@@ -18,7 +18,11 @@ import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"yunion.io/x/pkg/util/osprofile"
|
||||
)
|
||||
|
||||
func GetMD5Hash(text string) string {
|
||||
@@ -120,3 +124,64 @@ func SplitByQuotation(line string) ([]string, error) {
|
||||
}
|
||||
return segs, nil
|
||||
}
|
||||
|
||||
func GenerateHostName(name string, osType string) string {
|
||||
if len(name) < 2 {
|
||||
name = fmt.Sprintf("hostname-for-%s-%s", name, osType)
|
||||
}
|
||||
// ()英文句号(.)和短横线(-)不能作为首尾字符,更不能连续使用。
|
||||
// 点号(.)和短横线(-)不能作为 HostName 的首尾字符,不能连续使用。
|
||||
var init = func(s string) string {
|
||||
for {
|
||||
if strings.Contains(s, "..") || strings.Contains(s, "--") {
|
||||
s = strings.ReplaceAll(s, "..", ".")
|
||||
s = strings.ReplaceAll(s, "--", "-")
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(s, ".") || strings.HasPrefix(s, "-") {
|
||||
s = strings.TrimPrefix(s, ".")
|
||||
s = strings.TrimPrefix(s, "-")
|
||||
continue
|
||||
}
|
||||
if strings.HasSuffix(s, ".") || strings.HasSuffix(s, "-") {
|
||||
s = strings.TrimSuffix(s, ".")
|
||||
s = strings.TrimSuffix(s, "-")
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
return s
|
||||
}
|
||||
name = init(name)
|
||||
// (阿里云)Windows实例:字符长度为2~15,不支持英文句号(.),不能全是数字。允许大小写英文字母、数字和短横线(-)。
|
||||
// (腾讯云)Windows 实例:名字符长度为[2, 15],允许字母(不限制大小写)、数字和短横线(-)组成,不支持点号(.),不能全是数字
|
||||
var forWindows = func(s string) string {
|
||||
s = strings.ReplaceAll(s, ".", "")
|
||||
ret := ""
|
||||
for _, c := range s {
|
||||
if unicode.IsLetter(c) || unicode.IsNumber(c) || c == '-' {
|
||||
ret += string(c)
|
||||
}
|
||||
}
|
||||
_, err := strconv.Atoi(ret)
|
||||
if err == nil {
|
||||
ret = "host-" + ret
|
||||
}
|
||||
if len(ret) > 15 {
|
||||
ret = init(ret[:15])
|
||||
}
|
||||
return ret
|
||||
}
|
||||
// (阿里云)其他类型实例(Linux等):字符长度为2~64,支持多个英文句号(.),英文句号之间为一段,每段允许大小写英文字母、数字和短横线(-)。
|
||||
// (腾讯云)其他类型(Linux 等)实例:字符长度为[2, 60],允许支持多个点号,点之间为一段,每段允许字母(不限制大小写)、数字和短横线(-)组成。
|
||||
var forOther = func(s string) string {
|
||||
if len(s) > 60 {
|
||||
return init(s[:60])
|
||||
}
|
||||
return s
|
||||
}
|
||||
if strings.ToLower(osType) == strings.ToLower(osprofile.OS_TYPE_WINDOWS) {
|
||||
return forWindows(name)
|
||||
}
|
||||
return forOther(name)
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ package stringutils2
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"yunion.io/x/pkg/util/osprofile"
|
||||
)
|
||||
|
||||
func TestEscapeString(t *testing.T) {
|
||||
@@ -120,3 +122,47 @@ func TestEscapeEchoString(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateHostName(t *testing.T) {
|
||||
type input struct {
|
||||
name string
|
||||
osType string
|
||||
hostName string
|
||||
}
|
||||
for _, pair := range []input{
|
||||
input{
|
||||
name: "--test-host-name.......",
|
||||
hostName: "test-host-name",
|
||||
},
|
||||
input{
|
||||
name: "--test-host-1234567890-name.......",
|
||||
osType: osprofile.OS_TYPE_WINDOWS,
|
||||
hostName: "test-host-12345",
|
||||
},
|
||||
input{
|
||||
name: "--test-host-1234-67890-name.......",
|
||||
osType: osprofile.OS_TYPE_WINDOWS,
|
||||
hostName: "test-host-1234",
|
||||
},
|
||||
input{
|
||||
name: "1234567890123456",
|
||||
osType: osprofile.OS_TYPE_WINDOWS,
|
||||
hostName: "host-1234567890",
|
||||
},
|
||||
input{
|
||||
name: "001234567890123456",
|
||||
osType: osprofile.OS_TYPE_WINDOWS,
|
||||
hostName: "host-0012345678",
|
||||
},
|
||||
|
||||
input{
|
||||
name: "",
|
||||
hostName: "hostname-for",
|
||||
},
|
||||
} {
|
||||
hostName := GenerateHostName(pair.name, pair.osType)
|
||||
if hostName != pair.hostName {
|
||||
t.Fatalf("%s hostName should be %s, current is %s", pair.name, pair.hostName, hostName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user