Skip to content

Commit

Permalink
Merge pull request #20015 from wanyaoqi/automated-cherry-pick-of-#200…
Browse files Browse the repository at this point in the history
…13-upstream-master

Automated cherry pick of #20013: fix(region,host): custom device model add auto detect option
  • Loading branch information
zexi authored Apr 17, 2024
2 parents 9f00d7b + 1eb253e commit b610fd1
Show file tree
Hide file tree
Showing 10 changed files with 284 additions and 14 deletions.
70 changes: 70 additions & 0 deletions cmd/climc/shell/compute/isolated_device_models.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,13 @@
package compute

import (
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/util/printutils"

"yunion.io/x/onecloud/cmd/climc/shell"
"yunion.io/x/onecloud/pkg/mcclient"
modules "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
baseoptions "yunion.io/x/onecloud/pkg/mcclient/options"
options "yunion.io/x/onecloud/pkg/mcclient/options/compute"
)

Expand All @@ -28,4 +33,69 @@ func init() {
cmd.Delete(new(options.IsolatedDeviceIdsOptions))
cmd.Perform("set-hardware-info", new(options.IsolatedDeviceModelSetHardwareInfoOptions))
cmd.Get("hardware-info", new(options.IsolatedDeviceIdsOptions))

type HostIsolatedDeviceModelListOptions struct {
baseoptions.BaseListOptions
Host string `help:"ID or Name of Host"`
IsolatedDeviceModel string `help:"ID or Name of Isolated device model"`
}
R(&HostIsolatedDeviceModelListOptions{}, "host-isolated-device-model-list",
"List host Isolated device model pairs", func(s *mcclient.ClientSession, args *HostIsolatedDeviceModelListOptions) error {
var params *jsonutils.JSONDict
{
var err error
params, err = args.BaseListOptions.Params()
if err != nil {
return err

}
}
var result *printutils.ListResult
var err error
if len(args.Host) > 0 {
result, err = modules.HostIsolatedDeviceModels.ListDescendent(s, args.Host, params)
} else if len(args.IsolatedDeviceModel) > 0 {
result, err = modules.HostIsolatedDeviceModels.ListDescendent2(s, args.IsolatedDeviceModel, params)
} else {
result, err = modules.HostIsolatedDeviceModels.List(s, params)
}
if err != nil {
return err
}
printList(result, modules.HostIsolatedDeviceModels.GetColumns(s))
return nil
})

type HostIsolatedDeviceModelDetailOptions struct {
HOST string `help:"ID or Name of Host"`
IsolatedDeviceModel string `help:"ID or Name of Isolated device model"`
}
R(&HostIsolatedDeviceModelDetailOptions{}, "host-isolated-device-model-show", "Show host isolated-device-model details", func(s *mcclient.ClientSession, args *HostIsolatedDeviceModelDetailOptions) error {
result, err := modules.HostIsolatedDeviceModels.Get(s, args.HOST, args.IsolatedDeviceModel, nil)
if err != nil {
return err
}
printObject(result)
return nil
})

R(&HostIsolatedDeviceModelDetailOptions{}, "host-isolated-device-model-detach", "Detach a isolated-device-model from a host", func(s *mcclient.ClientSession, args *HostIsolatedDeviceModelDetailOptions) error {
result, err := modules.HostIsolatedDeviceModels.Detach(s, args.HOST, args.IsolatedDeviceModel, nil)
if err != nil {
return err
}
printObject(result)
return nil
})

R(&HostIsolatedDeviceModelDetailOptions{}, "host-isolated-device-model-attach", "Attach a isolated-device-model to a host", func(s *mcclient.ClientSession, args *HostIsolatedDeviceModelDetailOptions) error {
params := jsonutils.NewDict()
result, err := modules.HostIsolatedDeviceModels.Attach(s, args.HOST, args.IsolatedDeviceModel, params)
if err != nil {
return err
}
printObject(result)
return nil
})

}
19 changes: 19 additions & 0 deletions pkg/apis/compute/isolated_device.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,9 @@ type IsolatedDeviceModelListInput struct {

// 支持热插拔 HotPluggable
HotPluggable bool `json:"hot_pluggable"`

// 宿主机 Id
HostId string `json:"host_id"`
}

type IsolatedDeviceModelHardwareInfo struct {
Expand Down Expand Up @@ -329,3 +332,19 @@ func (info IsolatedDevicePCIEInfo) GetThroughputPerLane() PCIEVersionThroughput
}
return NewPCIEVersionThroughput(PCIEVersionUnknown)
}

type HostIsolatedDeviceModelDetails struct {
SHostJointsBase
HostJointResourceDetails
// 宿主机Id
HostId string `json:"host_id"`
// 存储Id
IsolatedDeviceModelId string `json:"isolated_device_model_id"`

Model string
VendorId string
DeviceId string
DevType string
HotPluggable bool
DisableAutoDetect bool
}
2 changes: 0 additions & 2 deletions pkg/apis/compute/isolated_device_const.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ const (
AMD_VENDOR_ID = "1002"
)

const MEAT_PROBED_HOST_COUNT = "probed_host_count"

var VALID_GPU_TYPES = []string{GPU_HPC_TYPE, GPU_VGA_TYPE}
var VALID_ATTACH_TYPES = []string{GPU_HPC_TYPE, GPU_VGA_TYPE, USB_TYPE, SRIOV_VGPU_TYPE, LEGACY_VGPU_TYPE}

Expand Down
121 changes: 121 additions & 0 deletions pkg/compute/models/host_isolated_device_models.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package models

import (
"context"

"yunion.io/x/jsonutils"
"yunion.io/x/log"

api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/stringutils2"
)

type SHostIsolatedDeviceModelManager struct {
SHostJointsManager
}

var HostIsolatedDeviceModelManager *SHostIsolatedDeviceModelManager

func init() {
db.InitManager(func() {
HostIsolatedDeviceModelManager = &SHostIsolatedDeviceModelManager{
SHostJointsManager: NewHostJointsManager(
"host_id",
SHostIsolatedDeviceModel{},
"host_isolated_device_models_tbl",
"host_isolated_device_model",
"host_isolated_device_models",
IsolatedDeviceModelManager,
),
}
HostIsolatedDeviceModelManager.SetVirtualObject(HostIsolatedDeviceModelManager)
HostIsolatedDeviceModelManager.TableSpec().AddIndex(false, "host_id", "isolated_device_model_id")
})
}

type SHostIsolatedDeviceModel struct {
SHostJointsBase

// 宿主机Id
HostId string `width:"36" charset:"ascii" nullable:"false" list:"domain" create:"required" json:"host_id"`
// 设备类型Id
IsolatedDeviceModelId string `width:"36" charset:"ascii" nullable:"false" list:"domain" create:"required" json:"isolated_device_model_id" index:"true"`
}

func (manager *SHostIsolatedDeviceModelManager) GetMasterFieldName() string {
return "host_id"
}

func (manager *SHostIsolatedDeviceModelManager) GetSlaveFieldName() string {
return "isolated_device_model_id"
}

func (self *SHostIsolatedDeviceModel) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
return db.DeleteModel(ctx, userCred, self)
}

func (self *SHostIsolatedDeviceModel) Detach(ctx context.Context, userCred mcclient.TokenCredential) error {
return db.DetachJoint(ctx, userCred, self)
}

func (manager *SHostIsolatedDeviceModelManager) FetchCustomizeColumns(
ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
objs []interface{},
fields stringutils2.SSortedStrings,
isList bool,
) []api.HostIsolatedDeviceModelDetails {
rows := make([]api.HostIsolatedDeviceModelDetails, len(objs))
hostRows := manager.SHostJointsManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)

devModelIds := make([]string, len(rows))
for i := range rows {
rows[i] = api.HostIsolatedDeviceModelDetails{
HostJointResourceDetails: hostRows[i],
}
devModelIds[i] = objs[i].(*SHostIsolatedDeviceModel).IsolatedDeviceModelId
}

devModels := make(map[string]SIsolatedDeviceModel)
err := db.FetchStandaloneObjectsByIds(IsolatedDeviceModelManager, devModelIds, &devModels)
if err != nil {
log.Errorf("db.FetchStandaloneObjectsByIds fail %s", err)
return rows
}

for i := range rows {
if devModel, ok := devModels[devModelIds[i]]; ok {
rows[i] = objs[i].(*SHostIsolatedDeviceModel).getExtraDetails(devModel, rows[i])
}
}

return rows
}

func (self *SHostIsolatedDeviceModel) getExtraDetails(devModel SIsolatedDeviceModel, out api.HostIsolatedDeviceModelDetails) api.HostIsolatedDeviceModelDetails {
out.Model = devModel.Model
out.VendorId = devModel.VendorId
out.DeviceId = devModel.DeviceId
out.DevType = devModel.DevType
out.HotPluggable = devModel.HotPluggable.Bool()
out.DisableAutoDetect = devModel.DisableAutoDetect.Bool()
return out
}

func (self *SHostIsolatedDeviceModel) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
self.SHostJointsBase.PostCreate(ctx, userCred, ownerId, query, data)

iHost, err := HostManager.FetchByIdOrName(ctx, userCred, self.HostId)
if err != nil {
log.Errorf("failed fetch host %s: %s", self.HostId, err)
return
}
host := iHost.(*SHost)
log.Infof("start request host %s scan isolated devices", host.GetName())
if err := host.RequestScanIsolatedDevices(ctx, userCred); err != nil {
log.Errorf("failed scan isolated device %s", err)
}
}
43 changes: 40 additions & 3 deletions pkg/compute/models/isolated_device_models.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,15 @@ type SIsolatedDeviceModel struct {
DevType string `width:"16" charset:"ascii" nullable:"false" list:"domain" create:"domain_required"`

HotPluggable tristate.TriState `default:"false" list:"domain" create:"domain_optional" update:"domain"`

// Disable auto detect isolated devices on host
DisableAutoDetect tristate.TriState `default:"false" list:"domain" create:"domain_optional" update:"domain"`
}

var _ db.IStandaloneModel = new(SIsolatedDeviceModel)

func (self *SIsolatedDeviceModel) SetName(name string) {}

func (manager *SIsolatedDeviceModelManager) ValidateCreateData(ctx context.Context,
userCred mcclient.TokenCredential,
ownerId mcclient.IIdentityProvider,
Expand Down Expand Up @@ -102,25 +109,46 @@ func (self *SIsolatedDeviceModel) PostCreate(ctx context.Context, userCred mccli
if err != nil {
log.Errorf("!!!data.Unmarshal api.IsolatedDeviceModelCreateInput fail %s", err)
}
go func() {
defer self.RemoveMetadata(ctx, api.MEAT_PROBED_HOST_COUNT, userCred)

go func() {
for i := range input.Hosts {
iHost, err := HostManager.FetchByIdOrName(ctx, userCred, input.Hosts[i])
if err != nil {
log.Errorf("failed fetch host %s: %s", input.Hosts[i], err)
continue
}
host := iHost.(*SHost)

if self.DisableAutoDetect.Bool() {
err = self.Attach2Host(ctx, userCred, host)
if err != nil {
log.Errorf("failed attach to host %s: %s", input.Hosts[i], err)
continue
}
}

log.Infof("start request host %s scan isolated devices", host.GetName())
if err := host.RequestScanIsolatedDevices(ctx, userCred); err != nil {
log.Errorf("failed scan isolated device %s", err)
}
self.SetMetadata(ctx, api.MEAT_PROBED_HOST_COUNT, strconv.Itoa(i+1), userCred)
}
}()
}

func (self *SIsolatedDeviceModel) Attach2Host(ctx context.Context, userCred mcclient.TokenCredential, host *SHost) error {
hs := SHostIsolatedDeviceModel{}
hs.SetModelManager(HostIsolatedDeviceModelManager, &hs)

hs.IsolatedDeviceModelId = self.Id
hs.HostId = host.Id
err := HostIsolatedDeviceModelManager.TableSpec().Insert(ctx, &hs)
if err != nil {
return err
}
db.OpsLog.LogAttachEvent(ctx, host, self, userCred, nil)
return nil
}

func (self *SIsolatedDeviceModel) ValidateDeleteCondition(ctx context.Context, info jsonutils.JSONObject) error {
modelIsEmpty, err := IsolatedDeviceManager.CheckModelIsEmpty(self.Model, self.VendorId, self.DeviceId, self.DevType)
if err != nil {
Expand Down Expand Up @@ -217,6 +245,15 @@ func (manager *SIsolatedDeviceModelManager) ListItemFilter(
if len(query.DeviceId) > 0 {
q = q.Equals("device_id", query.DeviceId)
}
if len(query.HostId) > 0 {
hidmq := HostIsolatedDeviceModelManager.Query("isolated_device_model_id").Equals("host_id", query.HostId).SubQuery()
q = q.Filter(sqlchemy.OR(
sqlchemy.IsFalse(q.Field("disable_auto_detect")),
sqlchemy.IsNull(q.Field("disable_auto_detect")),
sqlchemy.In(q.Field("id"), hidmq)),
)
}

return q, nil
}

Expand Down
1 change: 1 addition & 0 deletions pkg/compute/service/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ func InitHandlers(app *appsrv.Application) {
models.HostnetworkManager,
models.HoststorageManager,
models.HostschedtagManager,
models.HostIsolatedDeviceModelManager,
models.StorageschedtagManager,
models.NetworkschedtagManager,
models.CloudproviderschedtagManager,
Expand Down
1 change: 1 addition & 0 deletions pkg/hostman/isolated_device/isolated_device.go
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@ func (man *isolatedDeviceManager) getCustomIsolatedDeviceModels() ([]IsolatedDev
params := jsonutils.NewDict()
params.Set("limit", jsonutils.NewInt(0))
params.Set("scope", jsonutils.NewString("system"))
params.Set("host_id", jsonutils.NewString(man.host.GetHostId()))
res, err := modules.IsolatedDeviceModels.List(man.getSession(), jsonutils.NewDict())
if err != nil {
return nil, errors.Wrap(err, "list isolated_device_models from compute service")
Expand Down
20 changes: 20 additions & 0 deletions pkg/mcclient/modules/compute/mod_host_isolated_device_models.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package compute

import (
"yunion.io/x/onecloud/pkg/mcclient/modulebase"
"yunion.io/x/onecloud/pkg/mcclient/modules"
)

var (
HostIsolatedDeviceModels modulebase.JointResourceManager
)

func init() {
HostIsolatedDeviceModels = modules.NewJointComputeManager("host_isolated_device_model", "host_isolated_device_models",
[]string{"Host_ID", "Host", "Isolated_device_model_id", "Isolated_device_model", "Model", "Dev_type", "Device_id", "Vendor_id",
"Hot_pluggable", "Disable_auto_detect"},
[]string{},
&Hosts,
&IsolatedDeviceModels)
modules.RegisterCompute(&HostIsolatedDeviceModels)
}
2 changes: 1 addition & 1 deletion pkg/mcclient/modules/compute/mod_isolated_device_models.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ var (
func init() {
IsolatedDeviceModels = modules.NewComputeManager("isolated_device_model", "isolated_device_models",
[]string{"ID", "Dev_type",
"Model", "Vendor_id", "Device_id"},
"Model", "Vendor_id", "Device_id", "Hot_pluggable", "Disable_auto_detect"},
[]string{})
modules.RegisterCompute(&IsolatedDeviceModels)
}
Loading

0 comments on commit b610fd1

Please sign in to comment.