mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/yunionio/cloudpods.git
synced 2026-09-20 08:03:53 +08:00
Compare commits
3 Commits
4abe94ca0b
...
472b0ae4af
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
472b0ae4af | ||
|
|
d108efd764 | ||
|
|
1d1aea797c |
2
go.mod
2
go.mod
@@ -122,7 +122,7 @@ require (
|
||||
yunion.io/x/jsonutils v1.0.1-0.20260917025845-3108cd9a32ea
|
||||
yunion.io/x/log v1.0.1-0.20240305175729-7cf2d6cd5a91
|
||||
yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900
|
||||
yunion.io/x/pkg v1.10.4-0.20260916163305-b7743fa5e758
|
||||
yunion.io/x/pkg v1.10.4-0.20260918012554-27cd9d2e093b
|
||||
yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1
|
||||
yunion.io/x/sqlchemy v1.1.3-0.20260917035232-d682485b3a12
|
||||
yunion.io/x/structarg v0.0.0-20260917033311-96c7653334ac
|
||||
|
||||
3
go.sum
3
go.sum
@@ -1989,8 +1989,9 @@ yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900 h1:Hu/4ERvoWaN6aiFs4h4/yvVB
|
||||
yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900/go.mod h1:0vLkNEhlmA64HViPBAnSTUMrx5QP1CLsxXmxDKQ80tc=
|
||||
yunion.io/x/pkg v0.0.0-20190628082551-f4033ba2ea30/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
|
||||
yunion.io/x/pkg v0.0.0-20200814072949-4f1b541857d6/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
|
||||
yunion.io/x/pkg v1.10.4-0.20260916163305-b7743fa5e758 h1:3p/GCOPvDfvlSfovOh9GKxsSa7PPqp//DUjGRX8Wyus=
|
||||
yunion.io/x/pkg v1.10.4-0.20260916163305-b7743fa5e758/go.mod h1:Crp6aUYB+Yq16DFjZPHhHq7ha5HL2DfyPvzCo2LJ+LU=
|
||||
yunion.io/x/pkg v1.10.4-0.20260918012554-27cd9d2e093b h1:XUJLpD48685DE8hwxEC+ms1F4T6/g2KKAfGuVn8rZeo=
|
||||
yunion.io/x/pkg v1.10.4-0.20260918012554-27cd9d2e093b/go.mod h1:S8ITTpENaL3qSXi8Y4L6wVbVlP8XZ5BvABO10DFqF7M=
|
||||
yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1 h1:1KJ3YYinydPHpDEQRXdr/T8SYcKZ5Er+m489H+PnaQ4=
|
||||
yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1/go.mod h1:0iFKpOs1y4lbCxeOmq3Xx/0AcQoewVPwj62eRluioEo=
|
||||
yunion.io/x/sqlchemy v1.1.3-0.20260917035232-d682485b3a12 h1:xU8Z/Zg+zc199Y58eB3fA8mvOHsA28UCDfd7OuK3QKA=
|
||||
|
||||
@@ -123,10 +123,12 @@ func buildRaid(driver raid.IRaidDriver, adapter raid.IRaidAdapter, confs []*api.
|
||||
|
||||
for _, conf := range confs {
|
||||
selected, left, err = baremetal.RetrieveStorages(conf, left)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "baremetal.RetrieveStorages")
|
||||
}
|
||||
// RetrieveStorages also returns match diagnostics for leftover disks in rest;
|
||||
// only treat it as failure when no disk was selected (same as CalculateLayout).
|
||||
if len(selected) == 0 {
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "no enough disks for config %#v", conf)
|
||||
}
|
||||
return errors.Wrapf(httperrors.ErrInputParameter, "no enough disks for config %#v", conf)
|
||||
}
|
||||
var err error
|
||||
|
||||
@@ -951,7 +951,22 @@ func (task *STask) ClearPendingUsage(index int) error {
|
||||
}
|
||||
|
||||
func (task *STask) GetParams() *jsonutils.JSONDict {
|
||||
return task.Params
|
||||
result := jsonutils.NewDict()
|
||||
if task.Params == nil {
|
||||
return result
|
||||
}
|
||||
copied := task.Params.DeepCopy()
|
||||
copyParams, ok := copied.(*jsonutils.JSONDict)
|
||||
if !ok || copyParams == nil {
|
||||
return result
|
||||
}
|
||||
paramsJsonMap, _ := copyParams.GetMap()
|
||||
for k, v := range paramsJsonMap {
|
||||
if !strings.HasPrefix(k, "__") {
|
||||
result.Set(k, v)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (task *STask) GetUserCred() mcclient.TokenCredential {
|
||||
|
||||
144
pkg/cloudcommon/db/taskman/tasks_test.go
Normal file
144
pkg/cloudcommon/db/taskman/tasks_test.go
Normal file
@@ -0,0 +1,144 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package taskman
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
)
|
||||
|
||||
func TestSTaskGetParams(t *testing.T) {
|
||||
newParams := func(pairs map[string]jsonutils.JSONObject) *jsonutils.JSONDict {
|
||||
params := jsonutils.NewDict()
|
||||
for k, v := range pairs {
|
||||
params.Set(k, v)
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
||||
nested := jsonutils.NewDict()
|
||||
nested.Set("ip", jsonutils.NewString("10.0.0.1"))
|
||||
stages := jsonutils.NewArray(
|
||||
jsonutils.NewDict(),
|
||||
jsonutils.NewString("on_init"),
|
||||
)
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
params *jsonutils.JSONDict
|
||||
want *jsonutils.JSONDict
|
||||
}{
|
||||
{
|
||||
name: "nil_params",
|
||||
params: nil,
|
||||
want: jsonutils.NewDict(),
|
||||
},
|
||||
{
|
||||
name: "empty_params",
|
||||
params: jsonutils.NewDict(),
|
||||
want: jsonutils.NewDict(),
|
||||
},
|
||||
{
|
||||
name: "keep_public_keys",
|
||||
params: newParams(map[string]jsonutils.JSONObject{
|
||||
"parent_task_id": jsonutils.NewString("task-1"),
|
||||
"auto_start": jsonutils.JSONTrue,
|
||||
}),
|
||||
want: newParams(map[string]jsonutils.JSONObject{
|
||||
"parent_task_id": jsonutils.NewString("task-1"),
|
||||
"auto_start": jsonutils.JSONTrue,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "drop_internal_keys",
|
||||
params: newParams(map[string]jsonutils.JSONObject{
|
||||
"__stages": stages,
|
||||
"__pending_usage__": jsonutils.NewDict(),
|
||||
"__request_context": jsonutils.NewDict(),
|
||||
"__parent_task_notifyurl": jsonutils.NewString("http://notify"),
|
||||
}),
|
||||
want: jsonutils.NewDict(),
|
||||
},
|
||||
{
|
||||
name: "mixed_keys",
|
||||
params: newParams(map[string]jsonutils.JSONObject{
|
||||
"desc": nested,
|
||||
"__stages": stages,
|
||||
"_private": jsonutils.NewString("keep"),
|
||||
"__": jsonutils.NewString("drop"),
|
||||
"guest_id": jsonutils.NewString("g-1"),
|
||||
}),
|
||||
want: newParams(map[string]jsonutils.JSONObject{
|
||||
"desc": nested,
|
||||
"_private": jsonutils.NewString("keep"),
|
||||
"guest_id": jsonutils.NewString("g-1"),
|
||||
}),
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
c := c
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
task := &STask{}
|
||||
task.Params = c.params
|
||||
got := task.GetParams()
|
||||
if got == nil {
|
||||
t.Fatal("GetParams() returned nil, want empty dict")
|
||||
}
|
||||
if !got.Equals(c.want) {
|
||||
t.Fatalf("GetParams() = %s, want %s", got, c.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSTaskGetParamsDoesNotMutateOriginal(t *testing.T) {
|
||||
orig := jsonutils.NewDict()
|
||||
orig.Set("guest_id", jsonutils.NewString("g-1"))
|
||||
orig.Set("__stages", jsonutils.NewArray(jsonutils.NewString("on_init")))
|
||||
nested := jsonutils.NewDict()
|
||||
nested.Set("ip", jsonutils.NewString("10.0.0.1"))
|
||||
orig.Set("desc", nested)
|
||||
|
||||
task := &STask{STaskBase: STaskBase{Params: orig}}
|
||||
got := task.GetParams()
|
||||
got.Set("guest_id", jsonutils.NewString("g-2"))
|
||||
got.Set("extra", jsonutils.JSONTrue)
|
||||
desc, err := got.Get("desc")
|
||||
if err != nil {
|
||||
t.Fatalf("get desc: %v", err)
|
||||
}
|
||||
descDict, ok := desc.(*jsonutils.JSONDict)
|
||||
if !ok {
|
||||
t.Fatalf("desc type %T, want *jsonutils.JSONDict", desc)
|
||||
}
|
||||
descDict.Set("ip", jsonutils.NewString("10.0.0.2"))
|
||||
|
||||
if got.Contains("__stages") {
|
||||
t.Fatal("GetParams() leaked internal key __stages")
|
||||
}
|
||||
guestId, _ := orig.GetString("guest_id")
|
||||
if guestId != "g-1" {
|
||||
t.Fatalf("original guest_id = %s, want g-1", guestId)
|
||||
}
|
||||
if !orig.Contains("__stages") {
|
||||
t.Fatal("original __stages was removed")
|
||||
}
|
||||
origIp, _ := orig.GetString("desc", "ip")
|
||||
if origIp != "10.0.0.1" {
|
||||
t.Fatalf("original nested ip = %s, want 10.0.0.1", origIp)
|
||||
}
|
||||
}
|
||||
@@ -356,6 +356,7 @@ func (self *SBaremetalGuestDriver) RequestStartOnHost(ctx context.Context, guest
|
||||
if params.Length() > 0 {
|
||||
config.Add(params, "params")
|
||||
}
|
||||
log.Debugf("RequestStartOnHost config: %s", config.String())
|
||||
headers := task.GetTaskRequestHeader()
|
||||
url := fmt.Sprintf("/baremetals/%s/servers/%s/start", host.Id, guest.Id)
|
||||
_, err := host.BaremetalSyncRequest(ctx, "POST", url, headers, config)
|
||||
|
||||
@@ -78,7 +78,13 @@ func (m *kunlunxinXPUManager) NewContainerDevices(input *hostapi.ContainerCreate
|
||||
|
||||
func (m *kunlunxinXPUManager) GetContainerExtraConfigures(devs []*hostapi.ContainerDevice) ([]*runtimeapi.KeyValue, []*runtimeapi.Mount) {
|
||||
indices := collectKunlunxinXpuVisibleIndices(devs)
|
||||
return buildKunlunxinXpuExtraConfigures(indices, kunlunxinXreHome(), hygonPathExists)
|
||||
return buildKunlunxinXpuExtraConfigures(
|
||||
indices,
|
||||
kunlunxinXreHome(),
|
||||
kunlunxinXpuSmiPath(),
|
||||
hygonPathExists,
|
||||
procutils.RemoteReadlink,
|
||||
)
|
||||
}
|
||||
|
||||
type kunlunxinXPU struct {
|
||||
|
||||
@@ -22,12 +22,15 @@ import (
|
||||
"strings"
|
||||
|
||||
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
|
||||
|
||||
"yunion.io/x/log"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultKunlunxinXreHome = "/usr/local/xpu"
|
||||
defaultKunlunxinXpuSmiPath = "/usr/local/bin/xpu-smi"
|
||||
kunlunxinXpuDevicePrefix = "/dev/xpu"
|
||||
kunlunxinXpuMlLibName = "libxpunvidia-ml.so.1"
|
||||
)
|
||||
|
||||
var kunlunxinXpuCommonDevicePaths = []string{
|
||||
@@ -186,23 +189,99 @@ func buildKunlunxinXpuRuntimeEnvs(indices []string, xreHome string, pathExists f
|
||||
}
|
||||
}
|
||||
|
||||
func buildKunlunxinXpuRuntimeMounts(xreHome string, pathExists func(string) bool) []*runtimeapi.Mount {
|
||||
func kunlunxinXpuMlLibPathCandidates(xreHome string) []string {
|
||||
xreHome = normalizeKunlunxinXreHome(xreHome)
|
||||
return []string{
|
||||
path.Join("/lib/x86_64-linux-gnu", kunlunxinXpuMlLibName),
|
||||
path.Join("/usr/lib/x86_64-linux-gnu", kunlunxinXpuMlLibName),
|
||||
path.Join(xreHome, "so", kunlunxinXpuMlLibName),
|
||||
path.Join(xreHome, "lib64", kunlunxinXpuMlLibName),
|
||||
path.Join(xreHome, "lib", kunlunxinXpuMlLibName),
|
||||
}
|
||||
}
|
||||
|
||||
func resolveKunlunxinXpuMlLibPath(xreHome string, pathExists func(string) bool) string {
|
||||
if pathExists == nil {
|
||||
return ""
|
||||
}
|
||||
for _, p := range kunlunxinXpuMlLibPathCandidates(xreHome) {
|
||||
if pathExists(p) {
|
||||
return p
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// collectSymlinkMountPaths returns start plus the final path from readlink
|
||||
// (RemoteReadlink uses `readlink -f`, which resolves to the canonical target in one call).
|
||||
func collectSymlinkMountPaths(start string, readlink func(string) (string, error)) []string {
|
||||
if start == "" {
|
||||
return nil
|
||||
}
|
||||
start = path.Clean(start)
|
||||
out := []string{start}
|
||||
if readlink == nil {
|
||||
return out
|
||||
}
|
||||
final, err := readlink(start)
|
||||
if err != nil || final == "" {
|
||||
return out
|
||||
}
|
||||
final = path.Clean(final)
|
||||
if final == start {
|
||||
return out
|
||||
}
|
||||
return append(out, final)
|
||||
}
|
||||
|
||||
func appendReadonlyMountIfExists(mounts []*runtimeapi.Mount, hostPath string, pathExists func(string) bool, seen map[string]bool) []*runtimeapi.Mount {
|
||||
if hostPath == "" || pathExists == nil || !pathExists(hostPath) || seen[hostPath] {
|
||||
return mounts
|
||||
}
|
||||
seen[hostPath] = true
|
||||
return append(mounts, &runtimeapi.Mount{
|
||||
ContainerPath: hostPath,
|
||||
HostPath: hostPath,
|
||||
Readonly: true,
|
||||
})
|
||||
}
|
||||
|
||||
func buildKunlunxinXpuRuntimeMounts(
|
||||
xreHome, smiPath string,
|
||||
pathExists func(string) bool,
|
||||
readlink func(string) (string, error),
|
||||
) []*runtimeapi.Mount {
|
||||
xreHome = normalizeKunlunxinXreHome(xreHome)
|
||||
if pathExists == nil || !pathExists(xreHome) {
|
||||
return nil
|
||||
}
|
||||
return []*runtimeapi.Mount{
|
||||
{
|
||||
ContainerPath: xreHome,
|
||||
HostPath: xreHome,
|
||||
Readonly: true,
|
||||
},
|
||||
seen := map[string]bool{}
|
||||
mounts := appendReadonlyMountIfExists(nil, xreHome, pathExists, seen)
|
||||
mounts = appendReadonlyMountIfExists(mounts, smiPath, pathExists, seen)
|
||||
|
||||
mlPath := resolveKunlunxinXpuMlLibPath(xreHome, pathExists)
|
||||
if mlPath == "" {
|
||||
return mounts
|
||||
}
|
||||
for _, p := range collectSymlinkMountPaths(mlPath, readlink) {
|
||||
if pathExists(p) {
|
||||
mounts = appendReadonlyMountIfExists(mounts, p, pathExists, seen)
|
||||
continue
|
||||
}
|
||||
log.Warningf("kunlunxin xpu ml lib symlink target %s not found, skip mount", p)
|
||||
}
|
||||
return mounts
|
||||
}
|
||||
|
||||
func buildKunlunxinXpuExtraConfigures(indices []string, xreHome string, pathExists func(string) bool) ([]*runtimeapi.KeyValue, []*runtimeapi.Mount) {
|
||||
func buildKunlunxinXpuExtraConfigures(
|
||||
indices []string,
|
||||
xreHome, smiPath string,
|
||||
pathExists func(string) bool,
|
||||
readlink func(string) (string, error),
|
||||
) ([]*runtimeapi.KeyValue, []*runtimeapi.Mount) {
|
||||
if len(indices) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return buildKunlunxinXpuRuntimeEnvs(indices, xreHome, pathExists), buildKunlunxinXpuRuntimeMounts(xreHome, pathExists)
|
||||
return buildKunlunxinXpuRuntimeEnvs(indices, xreHome, pathExists),
|
||||
buildKunlunxinXpuRuntimeMounts(xreHome, smiPath, pathExists, readlink)
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package container_device
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -78,7 +79,7 @@ func TestBuildKunlunxinXpuExtraConfigures(t *testing.T) {
|
||||
exists := func(p string) bool {
|
||||
return p == "/usr/local/xpu" || p == "/usr/local/xpu/lib"
|
||||
}
|
||||
envs, mounts := buildKunlunxinXpuExtraConfigures([]string{"0", "3"}, "/usr/local/xpu", exists)
|
||||
envs, mounts := buildKunlunxinXpuExtraConfigures([]string{"0", "3"}, "/usr/local/xpu", "/usr/local/bin/xpu-smi", exists, nil)
|
||||
require.Len(t, envs, 2)
|
||||
assert.Equal(t, "XPU_VISIBLE_DEVICES", envs[0].Key)
|
||||
assert.Equal(t, "0,3", envs[0].Value)
|
||||
@@ -88,11 +89,76 @@ func TestBuildKunlunxinXpuExtraConfigures(t *testing.T) {
|
||||
assert.Equal(t, "/usr/local/xpu", mounts[0].HostPath)
|
||||
assert.True(t, mounts[0].Readonly)
|
||||
|
||||
envs, mounts = buildKunlunxinXpuExtraConfigures(nil, "/usr/local/xpu", exists)
|
||||
envs, mounts = buildKunlunxinXpuExtraConfigures(nil, "/usr/local/xpu", "/usr/local/bin/xpu-smi", exists, nil)
|
||||
assert.Nil(t, envs)
|
||||
assert.Nil(t, mounts)
|
||||
}
|
||||
|
||||
func TestBuildKunlunxinXpuRuntimeMountsWithSmiAndMlLib(t *testing.T) {
|
||||
smi := "/usr/local/bin/xpu-smi"
|
||||
ml := "/lib/x86_64-linux-gnu/libxpunvidia-ml.so.1"
|
||||
exists := func(p string) bool {
|
||||
switch p {
|
||||
case "/usr/local/xpu", "/usr/local/xpu/lib", smi, ml:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
mounts := buildKunlunxinXpuRuntimeMounts("/usr/local/xpu", smi, exists, nil)
|
||||
require.Len(t, mounts, 3)
|
||||
assert.Equal(t, "/usr/local/xpu", mounts[0].HostPath)
|
||||
assert.Equal(t, smi, mounts[1].HostPath)
|
||||
assert.Equal(t, ml, mounts[2].HostPath)
|
||||
for _, m := range mounts {
|
||||
assert.Equal(t, m.HostPath, m.ContainerPath)
|
||||
assert.True(t, m.Readonly)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCollectSymlinkMountPathsReadlinkF(t *testing.T) {
|
||||
link := "/lib/x86_64-linux-gnu/libxpunvidia-ml.so.1"
|
||||
final := "/lib/x86_64-linux-gnu/libxpunvidia-ml.so.1.0.0"
|
||||
readlink := func(p string) (string, error) {
|
||||
if p == link {
|
||||
return final, nil // RemoteReadlink: readlink -f
|
||||
}
|
||||
return "", os.ErrInvalid
|
||||
}
|
||||
paths := collectSymlinkMountPaths(link, readlink)
|
||||
assert.Equal(t, []string{link, final}, paths)
|
||||
|
||||
assert.Equal(t, []string{link}, collectSymlinkMountPaths(link, nil))
|
||||
same := func(p string) (string, error) { return p, nil }
|
||||
assert.Equal(t, []string{link}, collectSymlinkMountPaths(link, same))
|
||||
}
|
||||
|
||||
func TestBuildKunlunxinXpuRuntimeMountsFollowsSymlink(t *testing.T) {
|
||||
smi := "/usr/local/bin/xpu-smi"
|
||||
link := "/lib/x86_64-linux-gnu/libxpunvidia-ml.so.1"
|
||||
real := "/lib/x86_64-linux-gnu/libxpunvidia-ml.so.1.0.0"
|
||||
exists := func(p string) bool {
|
||||
switch p {
|
||||
case "/usr/local/xpu", smi, link, real:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
readlink := func(p string) (string, error) {
|
||||
if p == link {
|
||||
return real, nil
|
||||
}
|
||||
return "", os.ErrInvalid
|
||||
}
|
||||
mounts := buildKunlunxinXpuRuntimeMounts("/usr/local/xpu", smi, exists, readlink)
|
||||
require.Len(t, mounts, 4)
|
||||
assert.Equal(t, "/usr/local/xpu", mounts[0].HostPath)
|
||||
assert.Equal(t, smi, mounts[1].HostPath)
|
||||
assert.Equal(t, link, mounts[2].HostPath)
|
||||
assert.Equal(t, real, mounts[3].HostPath)
|
||||
}
|
||||
|
||||
func TestParseKunlunxinXpuNodeIndex(t *testing.T) {
|
||||
idx, ok := parseKunlunxinXpuNodeIndex("xpu3")
|
||||
assert.True(t, ok)
|
||||
|
||||
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@@ -2788,7 +2788,7 @@ yunion.io/x/log/hooks
|
||||
yunion.io/x/ovsdb/cli_util
|
||||
yunion.io/x/ovsdb/schema/ovn_nb
|
||||
yunion.io/x/ovsdb/types
|
||||
# yunion.io/x/pkg v1.10.4-0.20260916163305-b7743fa5e758
|
||||
# yunion.io/x/pkg v1.10.4-0.20260918012554-27cd9d2e093b
|
||||
## explicit; go 1.18
|
||||
yunion.io/x/pkg/appctx
|
||||
yunion.io/x/pkg/errors
|
||||
|
||||
26
vendor/yunion.io/x/pkg/util/reflectutils/ambiguous.go
generated
vendored
26
vendor/yunion.io/x/pkg/util/reflectutils/ambiguous.go
generated
vendored
@@ -57,7 +57,7 @@ func expandAmbiguousPrefix(fields SStructFieldValueSet) SStructFieldValueSet {
|
||||
if prefixed[idx] {
|
||||
continue
|
||||
}
|
||||
amPrefix, ok := fields[idx].Info.Tags[TAG_AMBIGUOUS_PREFIX]
|
||||
amPrefix, ok := fields[idx].Info.Tag(TAG_AMBIGUOUS_PREFIX)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
@@ -65,15 +65,25 @@ func expandAmbiguousPrefix(fields SStructFieldValueSet) SStructFieldValueSet {
|
||||
if takenByOther(fields, expanded, indexes) {
|
||||
continue
|
||||
}
|
||||
fields[idx].Info.Name = expanded
|
||||
if depBy, ok := fields[idx].Info.Tags[TAG_DEPRECATED_BY]; ok {
|
||||
fields[idx].Info.Tags[TAG_DEPRECATED_BY] = fmt.Sprintf("%s%s", amPrefix, depBy)
|
||||
info := fields[idx].Info
|
||||
info.Name = expanded
|
||||
_, newDepBy := info.tags[TAG_DEPRECATED_BY]
|
||||
_, oldDepBy := info.tags[TAG_OLD_DEPRECATED_BY]
|
||||
if newDepBy || oldDepBy {
|
||||
// the tags may still be shared with other callers
|
||||
info.copyTags()
|
||||
}
|
||||
if depBy, ok := fields[idx].Info.Tags[TAG_OLD_DEPRECATED_BY]; ok {
|
||||
fields[idx].Info.Tags[TAG_OLD_DEPRECATED_BY] = fmt.Sprintf("%s%s", amPrefix, depBy)
|
||||
if newDepBy {
|
||||
info.tags[TAG_DEPRECATED_BY] = fmt.Sprintf("%s%s", amPrefix, info.tags[TAG_DEPRECATED_BY])
|
||||
}
|
||||
for i := range fields[idx].Info.Aliases {
|
||||
fields[idx].Info.Aliases[i] = fmt.Sprintf("%s%s", amPrefix, fields[idx].Info.Aliases[i])
|
||||
if oldDepBy {
|
||||
info.tags[TAG_OLD_DEPRECATED_BY] = fmt.Sprintf("%s%s", amPrefix, info.tags[TAG_OLD_DEPRECATED_BY])
|
||||
}
|
||||
if len(info.aliases) > 0 {
|
||||
info.copyAliases()
|
||||
for i := range info.aliases {
|
||||
info.aliases[i] = fmt.Sprintf("%s%s", amPrefix, info.aliases[i])
|
||||
}
|
||||
}
|
||||
prefixed[idx] = true
|
||||
changed = true
|
||||
|
||||
89
vendor/yunion.io/x/pkg/util/reflectutils/jsonfield.go
generated
vendored
89
vendor/yunion.io/x/pkg/util/reflectutils/jsonfield.go
generated
vendored
@@ -30,9 +30,10 @@ import (
|
||||
// package. Do not construct a literal or modify the exported fields in an
|
||||
// unmanaged way
|
||||
//
|
||||
// The tags of a field are meant to be read through Tag and TagMap rather than
|
||||
// off the Tags map, which is not handed out to stay writable by whoever read
|
||||
// it; a caller may modify what TagMap returns.
|
||||
// The tags of a field are read through Tag and TagMap. The map behind them
|
||||
// is shared with the other callers of the fetch functions, which is what
|
||||
// makes reading a field several times cheap, so a caller may only modify what
|
||||
// TagMap hands out, which is a copy of its own.
|
||||
type SStructFieldInfo struct {
|
||||
// True if the field has json tag `json:"-"`
|
||||
Ignore bool
|
||||
@@ -72,40 +73,34 @@ type SStructFieldInfo struct {
|
||||
// value as a json string
|
||||
ForceString bool
|
||||
|
||||
// Tags holds the tags of the field keyed by tag name, a tag without a
|
||||
// value being mapped to the empty string. Read it through Tag or
|
||||
// TagMap rather than off here.
|
||||
Tags map[string]string
|
||||
// tags holds the tags of the field keyed by tag name, a tag without a
|
||||
// value being mapped to the empty string. The map is shared with the
|
||||
// other callers of the fetch functions, so it has to be copied with
|
||||
// copyTags before being written to; read it through Tag or TagMap.
|
||||
tags map[string]string
|
||||
|
||||
// Aliases are the other names the field is looked up by, taken from
|
||||
// the "alias" tag
|
||||
Aliases []string
|
||||
// aliases are the other names the field is looked up by, taken from
|
||||
// the "alias" tag. Like tags it is shared, and has to be copied with
|
||||
// copyAliases before being written to.
|
||||
aliases []string
|
||||
}
|
||||
|
||||
func (s *SStructFieldInfo) updateTags(k, v string) {
|
||||
s.Tags[k] = v
|
||||
}
|
||||
|
||||
func (s SStructFieldInfo) deepCopy() *SStructFieldInfo {
|
||||
scopy := SStructFieldInfo{
|
||||
Ignore: s.Ignore,
|
||||
OmitEmpty: s.OmitEmpty,
|
||||
OmitFalse: s.OmitFalse,
|
||||
OmitZero: s.OmitZero,
|
||||
Name: s.Name,
|
||||
FieldName: s.FieldName,
|
||||
ForceString: s.ForceString,
|
||||
kebabFieldName: s.kebabFieldName,
|
||||
}
|
||||
tags := make(map[string]string, len(s.Tags))
|
||||
for k, v := range s.Tags {
|
||||
// copyTags takes a private copy of the tags, so that they can be written to
|
||||
// without touching the ones this info was read out of.
|
||||
func (s *SStructFieldInfo) copyTags() {
|
||||
tags := make(map[string]string, len(s.tags)+1)
|
||||
for k, v := range s.tags {
|
||||
tags[k] = v
|
||||
}
|
||||
scopy.Tags = tags
|
||||
aliases := make([]string, len(s.Aliases))
|
||||
copy(aliases, s.Aliases)
|
||||
scopy.Aliases = aliases
|
||||
return &scopy
|
||||
s.tags = tags
|
||||
}
|
||||
|
||||
// copyAliases takes a private copy of the aliases, so that they can be
|
||||
// written to without touching the ones this info was read out of.
|
||||
func (s *SStructFieldInfo) copyAliases() {
|
||||
aliases := make([]string, len(s.aliases))
|
||||
copy(aliases, s.aliases)
|
||||
s.aliases = aliases
|
||||
}
|
||||
|
||||
func ParseStructFieldJsonInfo(sf reflect.StructField) SStructFieldInfo {
|
||||
@@ -120,8 +115,8 @@ func ParseFieldJsonInfo(name string, tag reflect.StructTag) SStructFieldInfo {
|
||||
info.OmitZero = false
|
||||
info.OmitFalse = false
|
||||
|
||||
info.Tags = utils.TagMap(tag)
|
||||
if val, ok := info.Tags["json"]; ok {
|
||||
info.tags = utils.TagMap(tag)
|
||||
if val, ok := info.tags["json"]; ok {
|
||||
keys := strings.Split(val, ",")
|
||||
if len(keys) > 0 {
|
||||
if keys[0] == "-" {
|
||||
@@ -155,14 +150,14 @@ func ParseFieldJsonInfo(name string, tag reflect.StructTag) SStructFieldInfo {
|
||||
}
|
||||
}
|
||||
}
|
||||
if val, ok := info.Tags["name"]; ok {
|
||||
if val, ok := info.tags["name"]; ok {
|
||||
info.Name = val
|
||||
}
|
||||
if !info.Ignore && len(info.Name) == 0 {
|
||||
info.Name = info.kebabFieldName
|
||||
}
|
||||
if val, ok := info.Tags["alias"]; !info.Ignore && ok {
|
||||
info.Aliases = strings.Split(val, ",")
|
||||
if val, ok := info.tags["alias"]; !info.Ignore && ok {
|
||||
info.aliases = strings.Split(val, ",")
|
||||
}
|
||||
return info
|
||||
}
|
||||
@@ -179,15 +174,15 @@ func (info *SStructFieldInfo) MarshalName() string {
|
||||
// Tag returns the value of the tag named name and whether the field has it.
|
||||
// A tag without a value is reported as present with an empty value.
|
||||
func (info *SStructFieldInfo) Tag(name string) (string, bool) {
|
||||
val, ok := info.Tags[name]
|
||||
val, ok := info.tags[name]
|
||||
return val, ok
|
||||
}
|
||||
|
||||
// TagMap returns a copy of the tags of the field, which the caller owns and
|
||||
// is free to modify.
|
||||
func (info *SStructFieldInfo) TagMap() map[string]string {
|
||||
tags := make(map[string]string, len(info.Tags))
|
||||
for k, v := range info.Tags {
|
||||
tags := make(map[string]string, len(info.tags))
|
||||
for k, v := range info.tags {
|
||||
tags[k] = v
|
||||
}
|
||||
return tags
|
||||
@@ -375,10 +370,10 @@ func fetchStructFieldValueSet3(dataValue reflect.Value, allocatePtr bool, tags m
|
||||
continue
|
||||
}
|
||||
}
|
||||
fieldInfo := fieldInfos[sf.Name].deepCopy()
|
||||
fieldInfo := fieldInfos[sf.Name]
|
||||
if !fieldInfo.Ignore || includeIgnore {
|
||||
structFieldVaule := SStructFieldValue{
|
||||
Info: fieldInfo,
|
||||
Info: &fieldInfo,
|
||||
Value: fv,
|
||||
}
|
||||
if parent != nil {
|
||||
@@ -390,6 +385,7 @@ func fetchStructFieldValueSet3(dataValue reflect.Value, allocatePtr bool, tags m
|
||||
if len(tags) > 0 {
|
||||
for i := range fields {
|
||||
fieldName := fields[i].Info.MarshalName()
|
||||
owned := false
|
||||
for k, v := range tags {
|
||||
target := ""
|
||||
pos := strings.Index(k, "->")
|
||||
@@ -400,7 +396,12 @@ func fetchStructFieldValueSet3(dataValue reflect.Value, allocatePtr bool, tags m
|
||||
if len(target) > 0 && target != fieldName {
|
||||
continue
|
||||
}
|
||||
fields[i].Info.updateTags(k, v)
|
||||
if !owned {
|
||||
// the tags may still be shared with other callers
|
||||
fields[i].Info.copyTags()
|
||||
owned = true
|
||||
}
|
||||
fields[i].Info.tags[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -445,7 +446,7 @@ func (fields SStructFieldValueSet) GetStructFieldIndexes2(name string, strictMod
|
||||
ret = append(ret, i)
|
||||
} else if info.FieldName == capName {
|
||||
ret = append(ret, i)
|
||||
} else if len(info.Aliases) > 0 && utils.IsInArray(name, info.Aliases) {
|
||||
} else if len(info.aliases) > 0 && utils.IsInArray(name, info.aliases) {
|
||||
ret = append(ret, i)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user