diff --git a/cmd/climc/shell/compute/cloudproviderregions.go b/cmd/climc/shell/compute/cloudproviderregions.go index 95c5fe9810..53ad8304cc 100644 --- a/cmd/climc/shell/compute/cloudproviderregions.go +++ b/cmd/climc/shell/compute/cloudproviderregions.go @@ -42,8 +42,8 @@ func init() { } var result *printutils.ListResult var err error - if len(args.Manager) > 0 { - result, err = modules.CloudproviderregionManager.ListDescendent(s, args.Manager, params) + if len(args.Manager) == 1 { + result, err = modules.CloudproviderregionManager.ListDescendent(s, args.Manager[0], params) } else if len(args.Region) > 0 { result, err = modules.CloudproviderregionManager.ListDescendent2(s, args.Region, params) } else { diff --git a/pkg/apis/compute/cloudprovider.go b/pkg/apis/compute/cloudprovider.go index a2bd07a966..aceeb5e0e4 100644 --- a/pkg/apis/compute/cloudprovider.go +++ b/pkg/apis/compute/cloudprovider.go @@ -165,11 +165,29 @@ type CloudproviderResourceInput struct { Cloudprovider string `json:"cloudprovider" yunion-deprecated-by:"cloudprovider_id"` } +type CloudproviderResourceListInput struct { + // 列出关联指定云订阅(ID或Name)的资源 + CloudproviderId []string `json:"cloudprovider_id"` + // List objects belonging to the cloud provider + // swagger:ignore + // Deprecated + // description: this param will be deprecate at 3.0 + Manager string `json:"manager" yunion-deprecated-by:"cloudprovider_id"` + // swagger:ignore + // Deprecated + // description: this param will be deprecate at 3.0 + ManagerId string `json:"manager_id" yunion-deprecated-by:"cloudprovider_id"` + // swagger:ignore + // Deprecated + // description: this param will be deprecate at 3.0 + Cloudprovider string `json:"cloudprovider" yunion-deprecated-by:"cloudprovider_id"` +} + type ManagedResourceListInput struct { apis.DomainizedResourceListInput CloudenvResourceListInput - CloudproviderResourceInput + CloudproviderResourceListInput // 列出关联指定云账号(ID或Name)的资源 CloudaccountId []string `json:"cloudaccount_id"` diff --git a/pkg/apis/compute/dbinstance.go b/pkg/apis/compute/dbinstance.go index 42e964f65a..d3168bf374 100644 --- a/pkg/apis/compute/dbinstance.go +++ b/pkg/apis/compute/dbinstance.go @@ -220,7 +220,7 @@ type DBInstanceListInput struct { InstanceType string `json:"instance_type"` // 通过IP搜索RDS实例 - IpAddr string `json:"ip_addr"` + IpAddr []string `json:"ip_addr"` } type DBInstanceBackupListInput struct { diff --git a/pkg/apis/compute/elasticips_const.go b/pkg/apis/compute/elasticips_const.go index ce227b5c5d..cce0b7e3b7 100644 --- a/pkg/apis/compute/elasticips_const.go +++ b/pkg/apis/compute/elasticips_const.go @@ -88,7 +88,7 @@ type ElasticipListInput struct { Mode string `json:"mode"` // IP地址 - IpAddr string `json:"ip_addr"` + IpAddr []string `json:"ip_addr"` // 绑定资源类型 AssociateType string `json:"associate_type"` diff --git a/pkg/apis/compute/geo_input.go b/pkg/apis/compute/geo_input.go index b3eb96ea13..58fe3c9818 100644 --- a/pkg/apis/compute/geo_input.go +++ b/pkg/apis/compute/geo_input.go @@ -18,6 +18,23 @@ import ( "yunion.io/x/onecloud/pkg/apis" ) +type CloudregionResourceListInput struct { + // 区域名称或ID + CloudregionId []string `json:"cloudregion_id"` + // swagger:ignore + // Deprecated + // description: this param will be deprecate at 3.0 + Cloudregion string `json:"cloudregion" yunion-deprecated-by:"cloudregion_id"` + // swagger:ignore + // Deprecated + // description: this param will be deprecate at 3.0 + Region string `json:"region" yunion-deprecated-by:"cloudregion_id"` + // swagger:ignore + // Deprecated + // description: this param will be deprecate at 3.0 + RegionId string `json:"region_id" yunion-deprecated-by:"cloudregion_id"` +} + type CloudregionResourceInput struct { // 区域名称或ID CloudregionId string `json:"cloudregion_id"` @@ -39,7 +56,7 @@ type RegionalFilterListInput struct { // 过滤位于指定城市区域的资源 City string `json:"city"` - CloudregionResourceInput + CloudregionResourceListInput // 按区域名称过滤 OrderByRegion string `json:"order_by_region"` diff --git a/pkg/apis/compute/guests.go b/pkg/apis/compute/guests.go index 705eabbc25..615039278c 100644 --- a/pkg/apis/compute/guests.go +++ b/pkg/apis/compute/guests.go @@ -60,7 +60,7 @@ type ServerListInput struct { Backup *bool `json:"bakcup"` // 列出指定类型的主机 // enum: normal,gpu,usb,backup - ServerType string `json:"server_type"` + ServerType []string `json:"server_type"` // 列出管理安全组为指定安全组的主机 AdminSecgroup string `json:"admin_security"` // 列出Hypervisor为指定值的主机 diff --git a/pkg/apis/compute/host.go b/pkg/apis/compute/host.go index 894f6bfcb6..c0b9f18fd6 100644 --- a/pkg/apis/compute/host.go +++ b/pkg/apis/compute/host.go @@ -124,7 +124,7 @@ type HostListInput struct { ServerIdForNetwork string `json:"server_id_for_network"` // 宿主机 cpu 架构 CpuArchitecture []string `json:"cpu_architecture"` - OsArch string `json:"os_arch"` + OsArch []string `json:"os_arch"` // 按虚拟机数量排序 // enum: asc,desc diff --git a/pkg/apis/compute/network.go b/pkg/apis/compute/network.go index e7c7b52ae9..c761d24e78 100644 --- a/pkg/apis/compute/network.go +++ b/pkg/apis/compute/network.go @@ -93,11 +93,11 @@ type NetworkListInput struct { // description: Exact matching ip address in network. // example: 10.168.222.1 - Ip string `json:"ip"` + Ip []string `json:"ip"` // description: Fuzzy matching ip address in network. // example: 10.168.222.1 - IpMatch string `json:"ip_match"` + IpMatch []string `json:"ip_match"` IfnameHint []string `json:"ifname_hint"` // 起始IP地址 diff --git a/pkg/apis/compute/vpc.go b/pkg/apis/compute/vpc.go index 3a23f0e8e5..44767c1020 100644 --- a/pkg/apis/compute/vpc.go +++ b/pkg/apis/compute/vpc.go @@ -111,8 +111,20 @@ type VpcResourceInput struct { ExternalAccessMode string `json:"external_access_mode"` } +type VpcListItemInput struct { + // 关联VPC(ID或Name) + VpcId []string `json:"vpc_id"` + // swagger:ignore + // Deprecated + // filter by vpc Id + Vpc []string `json:"vpc" yunion-deprecated-by:"vpc_id"` + + // Vpc外网访问模式 + ExternalAccessMode string `json:"external_access_mode"` +} + type VpcFilterListInputBase struct { - VpcResourceInput + VpcListItemInput // 按VPC名称排序 // pattern:asc|desc diff --git a/pkg/apis/list.go b/pkg/apis/list.go index 43db6d0475..e9e738aaa2 100644 --- a/pkg/apis/list.go +++ b/pkg/apis/list.go @@ -355,7 +355,7 @@ type MultiArchResourceBaseListInput struct { // arm会过滤出os_arch=aarch64或os_arch=aarch32或者以arm开头的资源 // 其他的输入会过滤出以输入字符开头的资源 // enmu: x86, arm - OsArch string `json:"os_arch"` + OsArch []string `json:"os_arch"` } type AutoDeleteResourceBaseListInput struct { diff --git a/pkg/cloudcommon/db/archs.go b/pkg/cloudcommon/db/archs.go index 3e6a3fc697..28d25796fc 100644 --- a/pkg/cloudcommon/db/archs.go +++ b/pkg/cloudcommon/db/archs.go @@ -41,24 +41,30 @@ func (manager *SMultiArchResourceBaseManager) ListItemFilter( return ListQueryByArchitecture(q, "os_arch", query.OsArch), nil } -func ListQueryByArchitecture(q *sqlchemy.SQuery, fieldKey string, arch string) *sqlchemy.SQuery { - if len(arch) == 0 { +func ListQueryByArchitecture(q *sqlchemy.SQuery, fieldKey string, archs []string) *sqlchemy.SQuery { + if len(archs) == 0 { return q } - if arch == apis.OS_ARCH_X86 { - q = q.Filter(sqlchemy.OR( - sqlchemy.Startswith(q.Field(fieldKey), arch), - sqlchemy.Equals(q.Field(fieldKey), apis.OS_ARCH_I386), - sqlchemy.IsNullOrEmpty(q.Field(fieldKey)), - )) - } else if arch == apis.OS_ARCH_ARM { - q = q.Filter(sqlchemy.OR( - sqlchemy.Startswith(q.Field(fieldKey), arch), - sqlchemy.Equals(q.Field(fieldKey), apis.OS_ARCH_AARCH32), - sqlchemy.Equals(q.Field(fieldKey), apis.OS_ARCH_AARCH64), - )) - } else { - q = q.Startswith(fieldKey, arch) + conditions := []sqlchemy.ICondition{} + for _, arch := range archs { + if arch == apis.OS_ARCH_X86 { + conditions = append(conditions, sqlchemy.OR( + sqlchemy.Startswith(q.Field(fieldKey), arch), + sqlchemy.Equals(q.Field(fieldKey), apis.OS_ARCH_I386), + sqlchemy.IsNullOrEmpty(q.Field(fieldKey)), + )) + } else if arch == apis.OS_ARCH_ARM { + conditions = append(conditions, sqlchemy.OR( + sqlchemy.Startswith(q.Field(fieldKey), arch), + sqlchemy.Equals(q.Field(fieldKey), apis.OS_ARCH_AARCH32), + sqlchemy.Equals(q.Field(fieldKey), apis.OS_ARCH_AARCH64), + )) + } else { + conditions = append(conditions, sqlchemy.Startswith(q.Field(fieldKey), arch)) + } + } + if len(conditions) > 0 { + q = q.Filter(sqlchemy.OR(conditions...)) } return q } diff --git a/pkg/compute/models/cloudaccounts.go b/pkg/compute/models/cloudaccounts.go index 01261d3ded..ce857d50a1 100644 --- a/pkg/compute/models/cloudaccounts.go +++ b/pkg/compute/models/cloudaccounts.go @@ -1700,9 +1700,10 @@ func (manager *SCloudaccountManager) ListItemFilter( q = q.Equals("proxy_setting_id", proxy.GetId()) } - managerStr := query.CloudproviderId - if len(managerStr) > 0 { - providerObj, err := CloudproviderManager.FetchByIdOrName(userCred, managerStr) + managerStrs := query.CloudproviderId + conditions := []sqlchemy.ICondition{} + for _, managerStr := range managerStrs { + providerObj, err := manager.FetchByIdOrName(userCred, managerStr) if err != nil { if err == sql.ErrNoRows { return nil, httperrors.NewResourceNotFoundError2(CloudproviderManager.Keyword(), managerStr) @@ -1711,7 +1712,10 @@ func (manager *SCloudaccountManager) ListItemFilter( } } provider := providerObj.(*SCloudprovider) - q = q.Equals("id", provider.CloudaccountId) + conditions = append(conditions, sqlchemy.Equals(q.Field("id"), provider.CloudaccountId)) + } + if len(conditions) > 0 { + q = q.Filter(sqlchemy.OR(conditions...)) } cloudEnvStr := query.CloudEnv diff --git a/pkg/compute/models/cloudproviders.go b/pkg/compute/models/cloudproviders.go index cf7f0cef2e..946a10fe06 100644 --- a/pkg/compute/models/cloudproviders.go +++ b/pkg/compute/models/cloudproviders.go @@ -1325,8 +1325,9 @@ func (manager *SCloudproviderManager) ListItemFilter( return nil, errors.Wrap(err, "SSyncableBaseResourceManager.ListItemFilter") } - managerStr := query.CloudproviderId - if len(managerStr) > 0 { + managerStrs := query.CloudproviderId + conditions := []sqlchemy.ICondition{} + for _, managerStr := range managerStrs { providerObj, err := manager.FetchByIdOrName(userCred, managerStr) if err != nil { if err == sql.ErrNoRows { @@ -1335,7 +1336,10 @@ func (manager *SCloudproviderManager) ListItemFilter( return nil, httperrors.NewGeneralError(err) } } - q = q.Equals("id", providerObj.GetId()) + conditions = append(conditions, sqlchemy.Equals(q.Field("id"), providerObj.GetId())) + } + if len(conditions) > 0 { + q = q.Filter(sqlchemy.OR(conditions...)) } cloudEnvStr := query.CloudEnv diff --git a/pkg/compute/models/cloudregionresource.go b/pkg/compute/models/cloudregionresource.go index 1c7f009ff0..cf5181ed78 100644 --- a/pkg/compute/models/cloudregionresource.go +++ b/pkg/compute/models/cloudregionresource.go @@ -52,6 +52,18 @@ func ValidateCloudregionResourceInput(userCred mcclient.TokenCredential, input a return regionObj.(*SCloudregion), input, nil } +func ValidateCloudregionId(userCred mcclient.TokenCredential, regionId string) (*SCloudregion, error) { + regionObj, err := CloudregionManager.FetchByIdOrName(userCred, regionId) + if err != nil { + if errors.Cause(err) == sql.ErrNoRows { + return nil, errors.Wrapf(httperrors.ErrResourceNotFound, "%s %s", CloudregionManager.Keyword(), regionId) + } else { + return nil, errors.Wrap(err, "CloudregionManager.FetchByIdOrName") + } + } + return regionObj.(*SCloudregion), nil +} + func (self *SCloudregionResourceBase) GetRegion() (*SCloudregion, error) { region, err := CloudregionManager.FetchById(self.CloudregionId) if err != nil { diff --git a/pkg/compute/models/cloudregions.go b/pkg/compute/models/cloudregions.go index 40cf4c3d91..723af6af75 100644 --- a/pkg/compute/models/cloudregions.go +++ b/pkg/compute/models/cloudregions.go @@ -887,7 +887,7 @@ func (manager *SCloudregionManager) ListItemFilter( managerStr := query.CloudproviderId if len(managerStr) > 0 { - subq := CloudproviderRegionManager.QueryRelatedRegionIds(nil, managerStr) + subq := CloudproviderRegionManager.QueryRelatedRegionIds(nil, managerStr...) q = q.In("id", subq) } accountArr := query.CloudaccountId diff --git a/pkg/compute/models/dbinstances.go b/pkg/compute/models/dbinstances.go index 1bdaa9c16e..b5a423c4ef 100644 --- a/pkg/compute/models/dbinstances.go +++ b/pkg/compute/models/dbinstances.go @@ -235,7 +235,15 @@ func (man *SDBInstanceManager) ListItemFilter( } if len(query.IpAddr) > 0 { - dn := DBInstanceNetworkManager.Query("dbinstance_id").Contains("ip_addr", query.IpAddr) + dn := DBInstanceNetworkManager.Query("dbinstance_id") + conditions := []sqlchemy.ICondition{} + for _, ipAddr := range query.IpAddr { + condition := sqlchemy.Contains(dn.Field("ip_addr"), ipAddr) + conditions = append(conditions, condition) + } + if len(conditions) > 0 { + dn = dn.Filter(sqlchemy.OR(conditions...)) + } q = q.Filter(sqlchemy.In(q.Field("id"), dn.SubQuery())) } diff --git a/pkg/compute/models/external_projects.go b/pkg/compute/models/external_projects.go index 706e66343d..8e39811635 100644 --- a/pkg/compute/models/external_projects.go +++ b/pkg/compute/models/external_projects.go @@ -574,17 +574,22 @@ func (manager *SExternalProjectManager) ListItemFilter( return nil, errors.Wrap(err, "SExternalizedResourceBaseManager.ListItemFilter") } - if len(query.CloudproviderId) > 0 { - p, err := CloudproviderManager.FetchByIdOrName(userCred, query.CloudproviderId) + managerStrs := query.CloudproviderId + conditions := []sqlchemy.ICondition{} + for _, managerStr := range managerStrs { + providerObj, err := manager.FetchByIdOrName(userCred, managerStr) if err != nil { - if errors.Cause(err) == sql.ErrNoRows { - return nil, httperrors.NewResourceNotFoundError2("cloudprovider", query.CloudproviderId) + if err == sql.ErrNoRows { + return nil, httperrors.NewResourceNotFoundError2(CloudproviderManager.Keyword(), managerStr) + } else { + return nil, httperrors.NewGeneralError(err) } - return nil, httperrors.NewGeneralError(err) } - q = q.Equals("manager_id", p.GetId()) - provider := p.(*SCloudprovider) - query.CloudaccountId = []string{provider.CloudaccountId} + provider := providerObj.(*SCloudprovider) + conditions = append(conditions, sqlchemy.Equals(q.Field("id"), provider.CloudaccountId)) + } + if len(conditions) > 0 { + q = q.Filter(sqlchemy.OR(conditions...)) } if len(query.CloudaccountId) > 0 { diff --git a/pkg/compute/models/guests.go b/pkg/compute/models/guests.go index 69fce8fb61..631291a20c 100644 --- a/pkg/compute/models/guests.go +++ b/pkg/compute/models/guests.go @@ -244,6 +244,7 @@ func (manager *SGuestManager) ListItemFilter( if err != nil { return nil, errors.Wrap(err, "SVirtualResourceBaseManager.ListItemFilter") } + q, err = manager.SMultiArchResourceBaseManager.ListItemFilter(ctx, q, userCred, query.MultiArchResourceBaseListInput) if err != nil { return nil, errors.Wrap(err, "MultiArchResourceBaseListInput.ListItemFilter") @@ -519,21 +520,26 @@ func (manager *SGuestManager) ListItemFilter( if len(query.ServerType) > 0 { var trueVal, falseVal = true, false - switch query.ServerType { - case "normal": - query.Normal = &falseVal - query.Backup = &falseVal - case "gpu": - query.Gpu = &trueVal - query.Backup = &falseVal - case "backup": - query.Gpu = &falseVal - query.Backup = &trueVal - case "usb": - query.Usb = &trueVal - query.Backup = &falseVal - default: - query.CustomDevType = query.ServerType + for _, serverType := range query.ServerType { + switch serverType { + case "normal": + query.Normal = &falseVal + query.Backup = &falseVal + case "gpu": + query.Gpu = &trueVal + query.Backup = &falseVal + case "backup": + query.Gpu = &falseVal + query.Backup = &trueVal + case "usb": + query.Usb = &trueVal + query.Backup = &falseVal + default: + query.CustomDevType = serverType + query.Backup = &falseVal + } + } + if query.Backup == nil { query.Backup = &falseVal } } @@ -545,12 +551,9 @@ func (manager *SGuestManager) ListItemFilter( q = q.IsEmpty("backup_host_id") } } - - devTypeQ := func(q *sqlchemy.SQuery, checkType *bool, dType string) *sqlchemy.SQuery { + devTypeQ := func(q *sqlchemy.SQuery, checkType *bool, dType string, conditions []sqlchemy.ICondition) []sqlchemy.ICondition { if checkType != nil { - conditions := []sqlchemy.ICondition{} isodev := IsolatedDeviceManager.Query().SubQuery() - isodevCons := []sqlchemy.ICondition{sqlchemy.IsNotNull(isodev.Field("guest_id"))} if len(dType) > 0 { isodevCons = append(isodevCons, sqlchemy.Startswith(isodev.Field("dev_type"), dType)) @@ -565,17 +568,22 @@ func (manager *SGuestManager) ListItemFilter( conditions = append(conditions, cond(q.Field("instance_type"), sq)) } conditions = append(conditions, cond(q.Field("id"), sgq)) - return q.Filter(sqlchemy.OR(conditions...)) + return conditions } - return q + return conditions } - q = devTypeQ(q, query.Normal, "") - q = devTypeQ(q, query.Gpu, "GPU") - q = devTypeQ(q, query.Usb, api.USB_TYPE) + conditions := []sqlchemy.ICondition{} + + conditions = devTypeQ(q, query.Normal, "", conditions) + conditions = devTypeQ(q, query.Gpu, "GPU", conditions) + conditions = devTypeQ(q, query.Usb, api.USB_TYPE, conditions) if len(query.CustomDevType) > 0 { ct := true - q = devTypeQ(q, &ct, query.CustomDevType) + conditions = devTypeQ(q, &ct, query.CustomDevType, conditions) + } + if len(conditions) > 0 { + q = q.Filter(sqlchemy.OR(conditions...)) } groupFilter := query.GroupId diff --git a/pkg/compute/models/managedresource.go b/pkg/compute/models/managedresource.go index 8705f386db..6fa72fabb3 100644 --- a/pkg/compute/models/managedresource.go +++ b/pkg/compute/models/managedresource.go @@ -490,8 +490,9 @@ func managedResourceFilterByAccount(q *sqlchemy.SQuery, input api.ManagedResourc } func _managedResourceFilterByAccount(managerIdFieldName string, q *sqlchemy.SQuery, input api.ManagedResourceListInput, filterField string, subqFunc func() *sqlchemy.SQuery) (*sqlchemy.SQuery, error) { - cloudproviderStr := input.CloudproviderId - if len(cloudproviderStr) > 0 { + cloudproviderStrs := input.CloudproviderId + managerIds := []string{} + for _, cloudproviderStr := range cloudproviderStrs { provider, err := CloudproviderManager.FetchByIdOrName(nil, cloudproviderStr) if err != nil { if err == sql.ErrNoRows { @@ -500,7 +501,7 @@ func _managedResourceFilterByAccount(managerIdFieldName string, q *sqlchemy.SQue return nil, httperrors.NewGeneralError(err) } if len(filterField) == 0 { - q = q.Filter(sqlchemy.Equals(q.Field(managerIdFieldName), provider.GetId())) + managerIds = append(managerIds, provider.GetId()) } else { sq := subqFunc() sq = sq.Filter(sqlchemy.Equals(sq.Field(managerIdFieldName), provider.GetId())) @@ -508,6 +509,10 @@ func _managedResourceFilterByAccount(managerIdFieldName string, q *sqlchemy.SQue } } + if len(managerIds) > 0 { + q = q.In(managerIdFieldName, managerIds) + } + cloudaccountArr := input.CloudaccountId if len(cloudaccountArr) > 0 { cpq := CloudaccountManager.Query().SubQuery() @@ -584,20 +589,26 @@ func managedResourceFilterByZone(q *sqlchemy.SQuery, query api.ZonalFilterListIn } func managedResourceFilterByRegion(q *sqlchemy.SQuery, query api.RegionalFilterListInput, filterField string, subqFunc func() *sqlchemy.SQuery) (*sqlchemy.SQuery, error) { - regionStr := query.CloudregionId - if len(regionStr) > 0 { - regionObj, _, err := ValidateCloudregionResourceInput(nil, query.CloudregionResourceInput) + regionIds := []string{} + for _, region := range query.CloudregionId { + regionObj, err := ValidateCloudregionId(nil, region) if err != nil { return nil, errors.Wrap(err, "ValidateCloudregionResourceInput") } - if len(filterField) == 0 { - q = q.Filter(sqlchemy.Equals(q.Field("cloudregion_id"), regionObj.GetId())) - } else { + regionIds = append(regionIds, regionObj.GetId()) + } + if len(filterField) == 0 { + if len(regionIds) > 0 { + q = q.In("cloudregion_id", regionIds) + } + } else { + if len(regionIds) > 0 { sq := subqFunc() - sq = sq.Filter(sqlchemy.Equals(sq.Field("cloudregion_id"), regionObj.GetId())) + sq = sq.Filter(sqlchemy.In(sq.Field("cloudregion_id"), regionIds)) q = q.Filter(sqlchemy.In(q.Field(filterField), sq.SubQuery())) } } + if len(query.City) > 0 { subq := CloudregionManager.Query("id").Equals("city", query.City).SubQuery() if len(filterField) == 0 { diff --git a/pkg/compute/models/networks.go b/pkg/compute/models/networks.go index 9180a0780f..9f5ad4314e 100644 --- a/pkg/compute/models/networks.go +++ b/pkg/compute/models/networks.go @@ -2139,39 +2139,42 @@ func (manager *SNetworkManager) ListItemFilter( } } - ip := "" + ips := []string{} exactIpMatch := false if len(input.Ip) > 0 { exactIpMatch = true - ip = input.Ip + ips = input.Ip } else if len(input.IpMatch) > 0 { - ip = input.IpMatch + ips = input.IpMatch } - if len(ip) > 0 { - ipIa, err := parseIpToIntArray(ip) - if err != nil { - return nil, err + if len(ips) > 0 { + conditions := []sqlchemy.ICondition{} + for _, ip := range ips { + ipIa, err := parseIpToIntArray(ip) + if err != nil { + return nil, err + } + + ipSa := []string{"0", "0", "0", "0"} + for i := range ipIa { + ipSa[i] = strconv.Itoa(ipIa[i]) + } + fullIp := strings.Join(ipSa, ".") + + ipField := sqlchemy.INET_ATON(sqlchemy.NewStringField(fullIp)) + ipStart := sqlchemy.INET_ATON(q.Field("guest_ip_start")) + ipEnd := sqlchemy.INET_ATON(q.Field("guest_ip_end")) + + var ipCondtion sqlchemy.ICondition + if exactIpMatch { + ipCondtion = sqlchemy.Between(ipField, ipStart, ipEnd) + } else { + ipCondtion = sqlchemy.OR(sqlchemy.Between(ipField, ipStart, ipEnd), sqlchemy.Contains(q.Field("guest_ip_start"), ip), sqlchemy.Contains(q.Field("guest_ip_end"), ip)) + } + conditions = append(conditions, ipCondtion) } - - ipSa := []string{"0", "0", "0", "0"} - for i := range ipIa { - ipSa[i] = strconv.Itoa(ipIa[i]) - } - fullIp := strings.Join(ipSa, ".") - - ipField := sqlchemy.INET_ATON(sqlchemy.NewStringField(fullIp)) - ipStart := sqlchemy.INET_ATON(q.Field("guest_ip_start")) - ipEnd := sqlchemy.INET_ATON(q.Field("guest_ip_end")) - - var ipCondtion sqlchemy.ICondition - if exactIpMatch { - ipCondtion = sqlchemy.Between(ipField, ipStart, ipEnd) - } else { - ipCondtion = sqlchemy.OR(sqlchemy.Between(ipField, ipStart, ipEnd), sqlchemy.Contains(q.Field("guest_ip_start"), ip), sqlchemy.Contains(q.Field("guest_ip_end"), ip)) - } - - q = q.Filter(ipCondtion) + q = q.Filter(sqlchemy.OR(conditions...)) } if len(input.SchedtagId) > 0 { diff --git a/pkg/compute/models/vpcresource.go b/pkg/compute/models/vpcresource.go index b181ed7d1a..8e899cc474 100644 --- a/pkg/compute/models/vpcresource.go +++ b/pkg/compute/models/vpcresource.go @@ -161,18 +161,23 @@ func (manager *SVpcResourceBaseManager) ListItemFilter( query api.VpcFilterListInput, ) (*sqlchemy.SQuery, error) { var err error - if len(query.VpcId) > 0 { - switch query.VpcId { + conditions := []sqlchemy.ICondition{} + for _, vpcId := range query.VpcId { + switch vpcId { case api.CLASSIC_VPC_NAME: - q = q.Equals("name", api.CLASSIC_VPC_NAME) + conditions = append(conditions, sqlchemy.Equals(q.Field("name"), api.CLASSIC_VPC_NAME)) default: - _, err := validators.ValidateModel(userCred, VpcManager, &query.VpcId) + _, err := validators.ValidateModel(userCred, VpcManager, &vpcId) if err != nil { return nil, err } - q = q.Equals("vpc_id", query.VpcId) + conditions = append(conditions, sqlchemy.Equals(q.Field("vpc_id"), vpcId)) } } + if len(conditions) > 0 { + q = q.Filter(sqlchemy.OR(conditions...)) + } + subq := VpcManager.Query("id").Snapshot() subq, err = manager.SCloudregionResourceBaseManager.ListItemFilter(ctx, subq, userCred, query.RegionalFilterListInput) if err != nil { diff --git a/pkg/compute/models/zones.go b/pkg/compute/models/zones.go index 6f252e3eff..f13911c30d 100644 --- a/pkg/compute/models/zones.go +++ b/pkg/compute/models/zones.go @@ -764,7 +764,7 @@ func (manager *SZoneManager) ListItemFilter( managerStr := query.CloudproviderId if len(managerStr) > 0 { - subq := CloudproviderRegionManager.QueryRelatedRegionIds(nil, managerStr) + subq := CloudproviderRegionManager.QueryRelatedRegionIds(nil, managerStr...) q = q.In("cloudregion_id", subq) } accountArr := query.CloudaccountId diff --git a/pkg/mcclient/options/base.go b/pkg/mcclient/options/base.go index a390ed4bef..6d1ad5ca3a 100644 --- a/pkg/mcclient/options/base.go +++ b/pkg/mcclient/options/base.go @@ -243,7 +243,7 @@ type BaseListOptions struct { ProjectOrganizations []string `help:"filter by projects of specified organizations"` DomainOrganizations []string `help:"filter by domains of specified organizations"` - Manager string `help:"List objects belonging to the cloud provider" json:"manager,omitempty"` + Manager []string `help:"List objects belonging to the cloud provider" json:"manager,omitempty"` Account string `help:"List objects belonging to the cloud account" json:"account,omitempty"` Provider []string `help:"List objects from the provider" choices:"OneCloud|VMware|Aliyun|Apsara|Qcloud|Azure|Aws|Huawei|OpenStack|Ucloud|ZStack|Google|Ctyun|Cloudpods|Nutanix|BingoCloud|IncloudSphere|JDcloud|Proxmox|Ceph|Ecloud|HCSO|HCS|HCSOP|H3C|S3|RemoteFile" json:"provider,omitempty"` Brand []string `help:"List objects belonging to a special brand"` diff --git a/pkg/mcclient/options/compute/dbinstances.go b/pkg/mcclient/options/compute/dbinstances.go index 8d795492d9..ea04a2a93b 100644 --- a/pkg/mcclient/options/compute/dbinstances.go +++ b/pkg/mcclient/options/compute/dbinstances.go @@ -75,7 +75,7 @@ func (opts *DBInstanceCreateOptions) Params() (jsonutils.JSONObject, error) { type DBInstanceListOptions struct { options.BaseListOptions BillingType string `help:"billing type" choices:"postpaid|prepaid"` - IpAddr string + IpAddr []string } func (opts *DBInstanceListOptions) Params() (jsonutils.JSONObject, error) { diff --git a/pkg/mcclient/options/compute/eips.go b/pkg/mcclient/options/compute/eips.go index 62a55f934a..0a479817e9 100644 --- a/pkg/mcclient/options/compute/eips.go +++ b/pkg/mcclient/options/compute/eips.go @@ -28,6 +28,7 @@ type ElasticipListOptions struct { UsableEipForAssociateId string `help:"With associate type filter which eip can associate"` OrderByIp string + IpAddr []string options.BaseListOptions } diff --git a/pkg/mcclient/options/compute/network.go b/pkg/mcclient/options/compute/network.go index a09d3e9ee1..0a0f5888fa 100644 --- a/pkg/mcclient/options/compute/network.go +++ b/pkg/mcclient/options/compute/network.go @@ -46,6 +46,7 @@ type NetworkListOptions struct { GuestIpStart []string `help:"search by guest_ip_start"` GuestIpEnd []string `help:"search by guest_ip_end"` + IpMatch []string `help:"search by network ips"` BgpType []string `help:"filter by bgp_type"` HostType string `help:"filter by host_type"` diff --git a/pkg/mcclient/options/compute/servers.go b/pkg/mcclient/options/compute/servers.go index 116aec65c7..3aabfc8e63 100644 --- a/pkg/mcclient/options/compute/servers.go +++ b/pkg/mcclient/options/compute/servers.go @@ -49,7 +49,7 @@ type ServerListOptions struct { WithEip *bool `help:"Show Servers with EIP"` WithoutEip *bool `help:"Show Servers without EIP"` OsType string `help:"OS Type" choices:"linux|windows|vmware"` - Vpc string `help:"Vpc id or name"` + Vpc []string `help:"Vpc id or name"` UsableServerForEip string `help:"Eip id or name"` WithoutUserMeta *bool `help:"Show Servers without user metadata"` EipAssociable *bool `help:"Show Servers can associate with eip"`