mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-01 04:27:15 +08:00
fix(region): isolated device share (#22351)
This commit is contained in:
@@ -17,6 +17,7 @@ package compute
|
||||
import (
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
modules "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options/compute"
|
||||
)
|
||||
|
||||
@@ -27,4 +28,6 @@ func init() {
|
||||
cmd.Show(&compute.DeviceShowOptions{})
|
||||
cmd.BatchDelete(&compute.DeviceDeleteOptions{})
|
||||
cmd.BatchPerform("purge", &compute.DevicePurgeOptions{})
|
||||
cmd.Perform("public", &options.SharableResourcePublicOptions{})
|
||||
cmd.Perform("private", &options.BaseIdOptions{})
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ func init() {
|
||||
cmd.Delete(&compute_options.NetworkIdOptions{})
|
||||
cmd.GetMetadata(&compute_options.NetworkIdOptions{})
|
||||
cmd.Perform("private", &compute_options.NetworkIdOptions{})
|
||||
cmd.Perform("public", &options.SharableResourcePublicOptions{})
|
||||
cmd.Perform("syncstatus", &compute_options.NetworkIdOptions{})
|
||||
cmd.Perform("sync", &compute_options.NetworkIdOptions{})
|
||||
cmd.Perform("purge", &compute_options.NetworkIdOptions{})
|
||||
@@ -48,22 +49,6 @@ func init() {
|
||||
cmd.Perform("sync-additional-wires", &compute_options.NetworkSyncAdditionalWiresOptions{})
|
||||
cmd.Get("available-addresses", &compute_options.NetworkIdOptions{})
|
||||
|
||||
type NetworkShareOptions struct {
|
||||
ID string `help:"ID or Name of the zone to show"`
|
||||
Scope string `help:"sharing scope" choices:"system|domain|project"`
|
||||
SharedProjects []string `help:"Share to prjects"`
|
||||
SharedDomains []string `help:"share to domains"`
|
||||
}
|
||||
R(&NetworkShareOptions{}, "network-public", "Make a network public", func(s *mcclient.ClientSession, args *NetworkShareOptions) error {
|
||||
params := jsonutils.Marshal(args)
|
||||
result, err := modules.Networks.PerformAction(s, args.ID, "public", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
type NetworkCreateOptions2 struct {
|
||||
Wire string `help:"ID or Name of wire in which the network is created"`
|
||||
Vpc string `help:"ID or Name of vpc in which the network is created"`
|
||||
|
||||
@@ -93,7 +93,7 @@ require (
|
||||
k8s.io/cri-api v0.22.17
|
||||
k8s.io/klog/v2 v2.20.0
|
||||
moul.io/http2curl/v2 v2.3.0
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250325152522-0d7006412421
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250331090349-7d6931240a65
|
||||
yunion.io/x/executor v0.0.0-20241205080005-48f5b1212256
|
||||
yunion.io/x/jsonutils v1.0.1-0.20240930100528-1671a2d0d22f
|
||||
yunion.io/x/log v1.0.1-0.20240305175729-7cf2d6cd5a91
|
||||
|
||||
@@ -1376,8 +1376,8 @@ sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250325152522-0d7006412421 h1:9q9pb2Yqv6sKN+dFL96gZmkydoWKALcU0ezQBKHKucI=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250325152522-0d7006412421/go.mod h1:FXxAEbdNfWXX9gjME3K2nJhkydHY5EKEUZb+RLEzVwQ=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250331090349-7d6931240a65 h1:q7lnCLb6PVLPhOuZWhb9pGtduL1mbksw4G47XFOiGLU=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250331090349-7d6931240a65/go.mod h1:FXxAEbdNfWXX9gjME3K2nJhkydHY5EKEUZb+RLEzVwQ=
|
||||
yunion.io/x/executor v0.0.0-20241205080005-48f5b1212256 h1:kLKQ6zbgPDQflRwoHFAjxNChcbhXIFgsUVLkJwiXu/8=
|
||||
yunion.io/x/executor v0.0.0-20241205080005-48f5b1212256/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws=
|
||||
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=
|
||||
|
||||
@@ -29,6 +29,7 @@ const (
|
||||
|
||||
type IsolateDeviceDetails struct {
|
||||
apis.StandaloneResourceDetails
|
||||
apis.SharableResourceBaseInfo
|
||||
HostResourceInfo
|
||||
|
||||
SIsolatedDevice
|
||||
|
||||
@@ -181,8 +181,9 @@ func GetCapabilities(ctx context.Context, userCred mcclient.TokenCredential, que
|
||||
var ownerId mcclient.IIdentityProvider
|
||||
scopeStr := jsonutils.GetAnyString(query, []string{"scope"})
|
||||
scope := rbacscope.String2Scope(scopeStr)
|
||||
var domainId string
|
||||
var domainId, tenantId string
|
||||
domainStr := jsonutils.GetAnyString(query, []string{"domain", "domain_id", "project_domain", "project_domain_id"})
|
||||
tenantStr := jsonutils.GetAnyString(query, []string{"tenant", "tenant_id", "project", "project_id"})
|
||||
if len(domainStr) > 0 {
|
||||
domain, err := db.TenantCacheManager.FetchDomainByIdOrName(ctx, domainStr)
|
||||
if err != nil {
|
||||
@@ -198,6 +199,16 @@ func GetCapabilities(ctx context.Context, userCred mcclient.TokenCredential, que
|
||||
domainId = userCred.GetProjectDomainId()
|
||||
ownerId = userCred
|
||||
}
|
||||
if len(tenantStr) > 0 {
|
||||
project, err := db.TenantCacheManager.FetchTenantById(ctx, tenantStr)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return capa, httperrors.NewResourceNotFoundError2("projects", tenantStr)
|
||||
}
|
||||
return capa, httperrors.NewGeneralError(err)
|
||||
}
|
||||
tenantId = project.GetId()
|
||||
}
|
||||
if scope == rbacscope.ScopeSystem {
|
||||
result := policy.PolicyManager.Allow(scope, userCred, consts.GetServiceType(), "capabilities", policy.PolicyActionList)
|
||||
if result.Result.IsDeny() {
|
||||
@@ -239,7 +250,7 @@ func GetCapabilities(ctx context.Context, userCred mcclient.TokenCredential, que
|
||||
if err != nil {
|
||||
return capa, errors.Wrapf(err, "getStorageTypes")
|
||||
}
|
||||
capa.GPUModels, capa.PCIModelTypes = getIsolatedDeviceInfo(ctx, userCred, region, zone, domainId)
|
||||
capa.GPUModels, capa.PCIModelTypes = getIsolatedDeviceInfo(ctx, userCred, region, zone, domainId, tenantId)
|
||||
capa.SchedPolicySupport = isSchedPolicySupported(region, zone)
|
||||
capa.MinNicCount = getMinNicCount(region, zone)
|
||||
capa.MaxNicCount = getMaxNicCount(region, zone)
|
||||
@@ -845,13 +856,42 @@ type PCIDevModelTypes struct {
|
||||
Hypervisor string
|
||||
}
|
||||
|
||||
func getIsolatedDeviceInfo(ctx context.Context, userCred mcclient.TokenCredential, region *SCloudregion, zone *SZone, domainId string) ([]string, []PCIDevModelTypes) {
|
||||
devices := IsolatedDeviceManager.Query().SubQuery()
|
||||
func getIsolatedDeviceInfo(ctx context.Context, userCred mcclient.TokenCredential, region *SCloudregion, zone *SZone, domainId, tenantId string) ([]string, []PCIDevModelTypes) {
|
||||
devicesQ := IsolatedDeviceManager.Query()
|
||||
hostQuery := HostManager.Query()
|
||||
if len(domainId) > 0 {
|
||||
ownerId := &db.SOwnerId{DomainId: domainId}
|
||||
hostQuery = StorageManager.FilterByOwner(ctx, hostQuery, StorageManager, userCred, ownerId, rbacscope.ScopeDomain)
|
||||
}
|
||||
if len(tenantId) > 0 {
|
||||
subq := db.SharedResourceManager.Query("resource_id")
|
||||
subq = subq.Equals("resource_type", IsolatedDeviceManager.Keyword())
|
||||
subq = subq.Equals("target_project_id", tenantId)
|
||||
subq = subq.Equals("target_type", db.SharedTargetProject)
|
||||
conds := []sqlchemy.ICondition{
|
||||
sqlchemy.AND(
|
||||
sqlchemy.IsTrue(devicesQ.Field("is_public")),
|
||||
sqlchemy.Equals(devicesQ.Field("public_scope"), rbacscope.ScopeSystem),
|
||||
),
|
||||
sqlchemy.In(devicesQ.Field("id"), subq.SubQuery()),
|
||||
}
|
||||
if len(domainId) > 0 {
|
||||
subq2 := db.SharedResourceManager.Query("resource_id")
|
||||
subq2 = subq2.Equals("resource_type", IsolatedDeviceManager.Keyword())
|
||||
subq2 = subq2.Equals("target_project_id", domainId)
|
||||
subq2 = subq2.Equals("target_type", db.SharedTargetDomain)
|
||||
conds = append(conds, sqlchemy.AND(
|
||||
sqlchemy.IsTrue(devicesQ.Field("is_public")),
|
||||
sqlchemy.Equals(devicesQ.Field("public_scope"), rbacscope.ScopeDomain),
|
||||
sqlchemy.OR(
|
||||
sqlchemy.In(devicesQ.Field("id"), subq2.SubQuery()),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
devicesQ = devicesQ.Filter(sqlchemy.OR(conds...))
|
||||
}
|
||||
devices := devicesQ.SubQuery()
|
||||
hosts := hostQuery.SubQuery()
|
||||
|
||||
q := devices.Query(hosts.Field("host_type"), devices.Field("model"), devices.Field("dev_type"), devices.Field("nvme_size_mb"))
|
||||
|
||||
@@ -2806,7 +2806,32 @@ func (hh *SHost) newIsolateDevice(ctx context.Context, userCred mcclient.TokenCr
|
||||
ret.DevType = dev.GetDevType()
|
||||
ret.NumaNode = dev.GetNumaNode()
|
||||
ret.VendorDeviceId = dev.GetVendorDeviceId()
|
||||
return IsolatedDeviceManager.TableSpec().Insert(ctx, ret)
|
||||
err := IsolatedDeviceManager.TableSpec().Insert(ctx, ret)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sharedProjectIds, err := dev.GetSharedProjectIds()
|
||||
if err != nil {
|
||||
if errors.Cause(err) == cloudprovider.ErrNotImplemented {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
if len(sharedProjectIds) == 0 {
|
||||
return nil
|
||||
}
|
||||
if len(sharedProjectIds) > 0 {
|
||||
projectIds, err := db.FetchField(ExternalProjectManager, "tenant_id", func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
|
||||
return q.Equals("manager_id", hh.ManagerId).In("external_id", sharedProjectIds)
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
input := apis.PerformPublicProjectInput{SharedProjectIds: projectIds}
|
||||
input.Scope = "project"
|
||||
db.SharablePerformPublic(ret, ctx, userCred, input)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (hh *SHost) SyncHostVMs(ctx context.Context, userCred mcclient.TokenCredential, iprovider cloudprovider.ICloudProvider, vms []cloudprovider.ICloudVM, syncOwnerId mcclient.IIdentityProvider, xor bool) ([]SGuestSyncResult, compare.SyncResult) {
|
||||
|
||||
@@ -35,6 +35,7 @@ import (
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
hostapi "yunion.io/x/onecloud/pkg/apis/host"
|
||||
"yunion.io/x/onecloud/pkg/apis/notify"
|
||||
@@ -69,6 +70,7 @@ var VENDOR_ID_MAP = api.VENDOR_ID_MAP
|
||||
type SIsolatedDeviceManager struct {
|
||||
db.SStandaloneResourceBaseManager
|
||||
db.SExternalizedResourceBaseManager
|
||||
db.SSharableBaseResourceManager
|
||||
SHostResourceBaseManager
|
||||
}
|
||||
|
||||
@@ -93,7 +95,8 @@ func init() {
|
||||
type SIsolatedDevice struct {
|
||||
db.SStandaloneResourceBase
|
||||
db.SExternalizedResourceBase
|
||||
SHostResourceBase `width:"36" charset:"ascii" nullable:"false" default:"" index:"true" list:"domain" create:"domain_required"`
|
||||
db.SSharableBaseResource `"is_public->create":"domain_optional" "public_scope->create":"domain_optional"`
|
||||
SHostResourceBase `width:"36" charset:"ascii" nullable:"false" default:"" index:"true" list:"domain" create:"domain_required"`
|
||||
|
||||
// # PCI / GPU-HPC / GPU-VGA / USB / NIC
|
||||
// 设备类型
|
||||
@@ -1398,11 +1401,13 @@ func (manager *SIsolatedDeviceManager) FetchCustomizeColumns(
|
||||
|
||||
stdRows := manager.SStandaloneResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
hostRows := manager.SHostResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
shareRows := manager.SSharableBaseResourceManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
guestIds := make([]string, len(rows))
|
||||
for i := range rows {
|
||||
rows[i] = api.IsolateDeviceDetails{
|
||||
StandaloneResourceDetails: stdRows[i],
|
||||
HostResourceInfo: hostRows[i],
|
||||
SharableResourceBaseInfo: shareRows[i],
|
||||
}
|
||||
guestIds[i] = objs[i].(*SIsolatedDevice).GuestId
|
||||
}
|
||||
@@ -1587,7 +1592,7 @@ func (manager *SIsolatedDeviceManager) NamespaceScope() rbacscope.TRbacScope {
|
||||
}
|
||||
|
||||
func (manager *SIsolatedDeviceManager) ResourceScope() rbacscope.TRbacScope {
|
||||
return rbacscope.ScopeDomain
|
||||
return rbacscope.ScopeProject
|
||||
}
|
||||
|
||||
func (manager *SIsolatedDeviceManager) FilterByOwner(ctx context.Context, q *sqlchemy.SQuery, man db.FilterByOwnerProvider, userCred mcclient.TokenCredential, owner mcclient.IIdentityProvider, scope rbacscope.TRbacScope) *sqlchemy.SQuery {
|
||||
@@ -1625,7 +1630,39 @@ func (model *SIsolatedDevice) syncWithCloudIsolateDevice(ctx context.Context, us
|
||||
model.VendorDeviceId = dev.GetVendorDeviceId()
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sharedProjectIds, err := dev.GetSharedProjectIds()
|
||||
if err != nil {
|
||||
if errors.Cause(err) == cloudprovider.ErrNotImplemented {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
log.Infof("share projectIds: %s", sharedProjectIds)
|
||||
if len(sharedProjectIds) == 0 {
|
||||
return nil
|
||||
}
|
||||
host := model.getHost()
|
||||
if host == nil {
|
||||
return nil
|
||||
}
|
||||
if len(sharedProjectIds) > 0 {
|
||||
projectIds, err := db.FetchField(ExternalProjectManager, "tenant_id", func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
|
||||
return q.Equals("manager_id", host.ManagerId).In("external_id", sharedProjectIds)
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
input := apis.PerformPublicProjectInput{SharedProjectIds: projectIds}
|
||||
input.Scope = "project"
|
||||
err = db.SharablePerformPublic(model, ctx, userCred, input)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "SharablePerformPublic")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (model *SIsolatedDevice) SetNetworkIndex(idx int) error {
|
||||
@@ -1635,3 +1672,35 @@ func (model *SIsolatedDevice) SetNetworkIndex(idx int) error {
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (model *SIsolatedDevice) GetRequiredSharedDomainIds() []string {
|
||||
host := model.getHost()
|
||||
if host != nil {
|
||||
return []string{host.DomainId}
|
||||
}
|
||||
return []string{}
|
||||
}
|
||||
|
||||
func (model *SIsolatedDevice) GetSharableTargetDomainIds() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (model *SIsolatedDevice) GetSharedDomains() []string {
|
||||
return db.SharableGetSharedProjects(model, db.SharedTargetDomain)
|
||||
}
|
||||
|
||||
func (model *SIsolatedDevice) PerformPublic(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformPublicProjectInput) (jsonutils.JSONObject, error) {
|
||||
err := db.SharablePerformPublic(model, ctx, userCred, input)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SharablePerformPublic")
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (model *SIsolatedDevice) PerformPrivate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformPrivateInput) (jsonutils.JSONObject, error) {
|
||||
err := db.SharablePerformPrivate(model, ctx, userCred)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SharablePerformPrivate")
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -51,6 +51,14 @@ func (d *SIsolatedDevice) GetVendorDeviceId() string {
|
||||
return d.VendorDeviceId
|
||||
}
|
||||
|
||||
func (d *SIsolatedDevice) GetSharedProjectIds() ([]string, error) {
|
||||
ret := []string{}
|
||||
for _, p := range d.SharedProjects {
|
||||
ret = append(ret, p.Id)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) GetIsolatedDevices(hostId string, serverId string) ([]SIsolatedDevice, error) {
|
||||
params := map[string]interface{}{}
|
||||
if len(hostId) > 0 {
|
||||
|
||||
@@ -51,3 +51,16 @@ type SharableResourcePublicBaseOptions struct {
|
||||
SharedProjects []string `help:"Share to projects"`
|
||||
SharedDomains []string `help:"Share to domains"`
|
||||
}
|
||||
|
||||
type SharableResourcePublicOptions struct {
|
||||
ID string
|
||||
SharableResourcePublicBaseOptions
|
||||
}
|
||||
|
||||
func (opts *SharableResourcePublicOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(opts.SharableResourcePublicBaseOptions), nil
|
||||
}
|
||||
|
||||
func (opts *SharableResourcePublicOptions) GetId() string {
|
||||
return opts.ID
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -1785,7 +1785,7 @@ sigs.k8s.io/structured-merge-diff/v4/value
|
||||
# sigs.k8s.io/yaml v1.2.0
|
||||
## explicit; go 1.12
|
||||
sigs.k8s.io/yaml
|
||||
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250325152522-0d7006412421
|
||||
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250331090349-7d6931240a65
|
||||
## explicit; go 1.21
|
||||
yunion.io/x/cloudmux/pkg/apis
|
||||
yunion.io/x/cloudmux/pkg/apis/billing
|
||||
|
||||
+1
@@ -331,6 +331,7 @@ type IsolateDevice interface {
|
||||
GetDevType() string
|
||||
GetNumaNode() int8
|
||||
GetVendorDeviceId() string
|
||||
GetSharedProjectIds() ([]string, error)
|
||||
}
|
||||
|
||||
type ICloudVM interface {
|
||||
|
||||
Reference in New Issue
Block a user