From 8fc56dcd4f4558631993f001b85b33050fc0ecd9 Mon Sep 17 00:00:00 2001 From: Jian Qiu Date: Sat, 25 Jan 2025 15:40:01 +0800 Subject: [PATCH] fix: support server change ipv6 address (#22016) Co-authored-by: Qiu Jian --- go.mod | 4 +- go.sum | 8 +-- pkg/cloudcommon/cmdline/parser.go | 38 +++++++---- pkg/cloudcommon/cmdline/parser_test.go | 65 +++++++++++++++++++ pkg/compute/models/guest_actions.go | 6 +- vendor/modules.txt | 4 +- .../pkg/multicloud/ksyun/instances.go | 30 +++++---- .../x/cloudmux/pkg/multicloud/ksyun/region.go | 22 +++++++ .../pkg/multicloud/volcengine/region.go | 8 +-- vendor/yunion.io/x/pkg/utils/tags.go | 46 ++++++++----- 10 files changed, 179 insertions(+), 52 deletions(-) diff --git a/go.mod b/go.mod index 9d9313a3c4..020688e0e6 100644 --- a/go.mod +++ b/go.mod @@ -93,12 +93,12 @@ 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.20250108102611-1b422fb27e8b + yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250113015514-eb7eb3112a75 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 yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900 - yunion.io/x/pkg v1.10.3 + yunion.io/x/pkg v1.10.4-0.20250123070256-9247ce856f07 yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1 yunion.io/x/sqlchemy v1.1.3-0.20240926163039-d41512b264e1 yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c diff --git a/go.sum b/go.sum index 5329cf8f97..d8b976eb1d 100644 --- a/go.sum +++ b/go.sum @@ -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.20250108102611-1b422fb27e8b h1:CnmPWb1fnMwF1ZlUxSCCIjiwdlfLd6/vFlScvHPIMjQ= -yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250108102611-1b422fb27e8b/go.mod h1:KQ/jWx7bZlmjCE711KEWuvHW/dzpdr/UTlBjjutkj0Y= +yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250113015514-eb7eb3112a75 h1:3GfPFiOXGcNlbMZbLg2TTov7VdRx2FS+FzrHQsmj64o= +yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250113015514-eb7eb3112a75/go.mod h1:KQ/jWx7bZlmjCE711KEWuvHW/dzpdr/UTlBjjutkj0Y= 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= @@ -1391,8 +1391,8 @@ 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-20190620104149-945c25821dbf/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E= yunion.io/x/pkg v0.0.0-20190628082551-f4033ba2ea30/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E= -yunion.io/x/pkg v1.10.3 h1:oaJAtMSIwASgF6jB/0W37iOQBLh6ICswfPL3ISnRZC4= -yunion.io/x/pkg v1.10.3/go.mod h1:0Bwxqd9MA3ACi119/l02FprY/o9gHahmYC2bsSbnVpM= +yunion.io/x/pkg v1.10.4-0.20250123070256-9247ce856f07 h1:XZsL8+YpgVBHMcRwdpZ4cOfSZCc+KsgUCTdV3KeK8FI= +yunion.io/x/pkg v1.10.4-0.20250123070256-9247ce856f07/go.mod h1:0Bwxqd9MA3ACi119/l02FprY/o9gHahmYC2bsSbnVpM= 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.20240926163039-d41512b264e1 h1:HWPqY1I5JSmM6Sks6FyK9hnq/MjL7FDghM6M8DXHob0= diff --git a/pkg/cloudcommon/cmdline/parser.go b/pkg/cloudcommon/cmdline/parser.go index 594ca6b9ee..b4763acd30 100644 --- a/pkg/cloudcommon/cmdline/parser.go +++ b/pkg/cloudcommon/cmdline/parser.go @@ -253,11 +253,27 @@ func ParseNetworkConfigByJSON(desc jsonutils.JSONObject, idx int) (*compute.Netw return conf, err } +func isQuoteChar(ch byte) (bool, string) { + switch ch { + case '[': + return true, "]" + default: + return false, "" + } +} + +func splitConfig(confStr string) ([]string, error) { + return utils.FindWords2([]byte(confStr), 0, ":", isQuoteChar) +} + func ParseNetworkConfig(desc string, idx int) (*compute.NetworkConfig, error) { if len(desc) == 0 { return nil, ErrorEmptyDesc } - parts := strings.Split(desc, ":") + parts, err := splitConfig(desc) + if err != nil { + return nil, errors.Wrap(err, "splitConfig") + } netConfig := new(compute.NetworkConfig) netConfig.Index = idx for _, p := range parts { @@ -300,23 +316,23 @@ func ParseNetworkConfig(desc string, idx int) (*compute.NetworkConfig, error) { } netConfig.Addresses6[i] = addr6.String() } - } else if p == "[require_designated_ip]" { + } else if p == "require_designated_ip" { netConfig.RequireDesignatedIP = true - } else if p == "[random_exit]" { + } else if p == "random_exit" { netConfig.Exit = true - } else if p == "[random]" { + } else if p == "random" { netConfig.Exit = false - } else if p == "[private]" { + } else if p == "private" { netConfig.Private = true - } else if p == "[reserved]" { + } else if p == "reserved" { netConfig.Reserved = true - } else if p == "[teaming]" { + } else if p == "teaming" { netConfig.RequireTeaming = true - } else if p == "[try-teaming]" { + } else if p == "try-teaming" { netConfig.TryTeaming = true - } else if p == "[defaultgw]" { + } else if p == "defaultgw" { netConfig.IsDefault = true - } else if p == "[ipv6]" { + } else if p == "ipv6" { netConfig.RequireIPv6 = true } else if strings.HasPrefix(p, "standby-port=") { netConfig.StandbyPortCount, _ = strconv.Atoi(p[len("standby-port="):]) @@ -332,7 +348,7 @@ func ParseNetworkConfig(desc string, idx int) (*compute.NetworkConfig, error) { return nil, err } netConfig.BwLimit = bw - } else if p == "[vip]" { + } else if p == "vip" { netConfig.Vip = true } else if strings.HasPrefix(p, "sriov-nic-id=") { netConfig.SriovDevice = &compute.IsolatedDeviceConfig{ diff --git a/pkg/cloudcommon/cmdline/parser_test.go b/pkg/cloudcommon/cmdline/parser_test.go index f394b6b9a4..b35c3d0aac 100644 --- a/pkg/cloudcommon/cmdline/parser_test.go +++ b/pkg/cloudcommon/cmdline/parser_test.go @@ -282,3 +282,68 @@ func TestParseBaremetalRootDiskMatcher(t *testing.T) { }) } } + +func TestParseNetworkConfig(t *testing.T) { + tests := []struct { + args string + want *compute.NetworkConfig + }{ + { + args: "77a7d3a7-022d-4b48-8bb6-e37ea3a20c94", + want: &compute.NetworkConfig{Network: "77a7d3a7-022d-4b48-8bb6-e37ea3a20c94"}, + }, + { + args: "77a7d3a7-022d-4b48-8bb6-e37ea3a20c94:172.22.121.12", + want: &compute.NetworkConfig{ + Network: "77a7d3a7-022d-4b48-8bb6-e37ea3a20c94", + Address: "172.22.121.12", + }, + }, + { + args: "77a7d3a7-022d-4b48-8bb6-e37ea3a20c94:172.22.121.12:[fd:3ffe:3200:90::2]", + want: &compute.NetworkConfig{ + Network: "77a7d3a7-022d-4b48-8bb6-e37ea3a20c94", + Address: "172.22.121.12", + Address6: "fd:3ffe:3200:90::2", + }, + }, + { + args: "77a7d3a7-022d-4b48-8bb6-e37ea3a20c94:172.22.121.12:[fd:3ffe:3200:90::2]:[teaming]", + want: &compute.NetworkConfig{ + Network: "77a7d3a7-022d-4b48-8bb6-e37ea3a20c94", + Address: "172.22.121.12", + Address6: "fd:3ffe:3200:90::2", + RequireTeaming: true, + }, + }, + { + args: "77a7d3a7-022d-4b48-8bb6-e37ea3a20c94:172.22.121.12:[fd:3ffe:3200:90::2]:wire=77a7d3a7-022d-4b48-8bb6-e37ea3a20c94", + want: &compute.NetworkConfig{ + Network: "77a7d3a7-022d-4b48-8bb6-e37ea3a20c94", + Address: "172.22.121.12", + Address6: "fd:3ffe:3200:90::2", + Wire: "77a7d3a7-022d-4b48-8bb6-e37ea3a20c94", + }, + }, + { + args: "77a7d3a7-022d-4b48-8bb6-e37ea3a20c94:172.22.121.12:[fd:3ffe:3200:90::2]:wire=77a7d3a7-022d-4b48-8bb6-e37ea3a20c94:[try-teaming]", + want: &compute.NetworkConfig{ + Network: "77a7d3a7-022d-4b48-8bb6-e37ea3a20c94", + Address: "172.22.121.12", + Address6: "fd:3ffe:3200:90::2", + Wire: "77a7d3a7-022d-4b48-8bb6-e37ea3a20c94", + TryTeaming: true, + }, + }, + } + for _, tt := range tests { + t.Run(tt.args, func(t *testing.T) { + got, err := ParseNetworkConfig(tt.args, 0) + if err != nil { + t.Errorf("ParseNetworkConfig %s fail %s", tt.args, err) + } else if !reflect.DeepEqual(got, tt.want) { + t.Errorf("ParseNetworkConfig() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/compute/models/guest_actions.go b/pkg/compute/models/guest_actions.go index 485e5b911f..11960a7b15 100644 --- a/pkg/compute/models/guest_actions.go +++ b/pkg/compute/models/guest_actions.go @@ -2602,7 +2602,11 @@ func (self *SGuest) PerformChangeIpaddr( if input.NetConf != nil { conf = input.NetConf } else if len(input.NetDesc) > 0 { - netConf, err := cmdline.ParseNetworkConfigByJSON(jsonutils.NewString(input.NetDesc), -1) + netDescJson, err := jsonutils.ParseString(input.NetDesc) + if err != nil { + netDescJson = jsonutils.NewString(input.NetDesc) + } + netConf, err := cmdline.ParseNetworkConfigByJSON(netDescJson, -1) if err != nil { return nil, httperrors.NewInputParameterError("fail to parse net_desc %s: %s", input.NetDesc, err) } diff --git a/vendor/modules.txt b/vendor/modules.txt index 04216e485e..de3f04815e 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -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.20250108102611-1b422fb27e8b +# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250113015514-eb7eb3112a75 ## explicit; go 1.21 yunion.io/x/cloudmux/pkg/apis yunion.io/x/cloudmux/pkg/apis/billing @@ -1882,7 +1882,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.3 +# yunion.io/x/pkg v1.10.4-0.20250123070256-9247ce856f07 ## explicit; go 1.18 yunion.io/x/pkg/appctx yunion.io/x/pkg/errors diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/ksyun/instances.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/ksyun/instances.go index 0d564d4471..a1f5291c3e 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/ksyun/instances.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/ksyun/instances.go @@ -94,7 +94,8 @@ type DataDisks struct { type SInstance struct { multicloud.SInstanceBase SKsTag - host *SHost + host *SHost + region *SRegion InstanceID string `json:"InstanceId"` ProjectID string `json:"ProjectId"` @@ -186,16 +187,16 @@ func (region *SRegion) GetInstance(instanceId string) (*SInstance, error) { if err != nil { return nil, errors.Wrap(err, "GetInstances") } - for _, instance := range instances { - if instance.GetGlobalId() == instanceId { - return &instance, nil + for i := range instances { + if instances[i].GetGlobalId() == instanceId { + return &instances[i], nil } } - return nil, errors.Wrapf(err, "instance id:%s", instanceId) + return nil, errors.Wrapf(cloudprovider.ErrNotFound, instanceId) } func (ins *SInstance) Refresh() error { - extIns, err := ins.host.zone.region.GetInstance(ins.GetGlobalId()) + extIns, err := ins.getRegion().GetInstance(ins.GetGlobalId()) if err != nil { return errors.Wrap(err, "GetInstance") } @@ -203,13 +204,20 @@ func (ins *SInstance) Refresh() error { } func (ins *SInstance) GetTags() (map[string]string, error) { - tags, err := ins.host.zone.region.ListTags("kec-instance", ins.InstanceID) + tags, err := ins.getRegion().ListTags("kec-instance", ins.InstanceID) if err != nil { return nil, err } return tags.GetTags(), nil } +func (ins *SInstance) getRegion() *SRegion { + if ins.region != nil { + return ins.region + } + return ins.host.zone.region +} + func (ins *SInstance) AssignSecurityGroup(secgroupId string) error { return cloudprovider.ErrNotImplemented } @@ -320,7 +328,7 @@ func (ins *SInstance) GetHypervisor() string { } func (ins *SInstance) GetIDisks() ([]cloudprovider.ICloudDisk, error) { - disks, err := ins.host.zone.region.GetDiskByInstanceId(ins.GetId()) + disks, err := ins.getRegion().GetDiskByInstanceId(ins.GetId()) if err != nil { return nil, errors.Wrap(err, "getDisks") } @@ -339,7 +347,7 @@ func (ins *SInstance) GetIEIP() (cloudprovider.ICloudEIP, error) { if len(eipIds) == 0 { return nil, cloudprovider.ErrNotFound } - eips, err := ins.host.zone.region.GetEips(eipIds) + eips, err := ins.getRegion().GetEips(eipIds) if err != nil { return nil, errors.Wrap(err, "get eips") } @@ -348,7 +356,7 @@ func (ins *SInstance) GetIEIP() (cloudprovider.ICloudEIP, error) { } for _, eip := range eips { if utils.IsInStringArray(eip.GetId(), eipIds) { - eip.region = ins.host.zone.region + eip.region = ins.getRegion() return &eip, nil } } @@ -371,7 +379,7 @@ func (ins *SInstance) GetINics() ([]cloudprovider.ICloudNic, error) { func (ins *SInstance) GetVNCInfo(input *cloudprovider.ServerVncInput) (*cloudprovider.ServerVncOutput, error) { // TODO - resp, err := ins.host.zone.region.ecsRequest("GetVNCAddress", map[string]string{"InstanceId": ins.InstanceID}) + resp, err := ins.getRegion().ecsRequest("GetVNCAddress", map[string]string{"InstanceId": ins.InstanceID}) if err != nil { return nil, errors.Wrap(err, "GetVNCAddress") } diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/ksyun/region.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/ksyun/region.go index b36a7b9499..e9dcdd337e 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/ksyun/region.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/ksyun/region.go @@ -238,6 +238,28 @@ func (region *SRegion) GetIStorages() ([]cloudprovider.ICloudStorage, error) { return iStores, nil } +func (r *SRegion) GetIVMs() ([]cloudprovider.ICloudVM, error) { + vms, err := r.GetInstances("", nil) + if err != nil { + return nil, err + } + ret := []cloudprovider.ICloudVM{} + for i := range vms { + vms[i].region = r + ret = append(ret, &vms[i]) + } + return ret, nil +} + +func (r *SRegion) GetIVMById(id string) (cloudprovider.ICloudVM, error) { + vm, err := r.GetInstance(id) + if err != nil { + return nil, err + } + vm.region = r + return vm, nil +} + func (region *SRegion) ecsRequest(action string, params map[string]string) (jsonutils.JSONObject, error) { return region.client.ec2Request(region.Region, action, params) } diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/volcengine/region.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/volcengine/region.go index 3d0639721a..28a39c801d 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/volcengine/region.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/volcengine/region.go @@ -32,9 +32,9 @@ import ( ) var RegionLocations = map[string]string{ - "cn-beijing": "华东2(北京)", + "cn-beijing": "华北2(北京)", "cn-shanghai": "华东2(上海)", - "cn-guangzhou": "华东2(广州)", + "cn-guangzhou": "华南1(广州)", "ap-southeast-1": "亚太东南(柔佛)", "cn-hongkong": "中国香港", } @@ -88,9 +88,9 @@ func (region *SRegion) GetId() string { func (region *SRegion) GetName() string { if localName, ok := RegionLocations[region.RegionId]; ok { - return fmt.Sprintf("%s %s", CLOUD_PROVIDER_VOLCENGINE_CN, localName) + return localName } - return fmt.Sprintf("%s %s", CLOUD_PROVIDER_VOLCENGINE_CN, region.RegionId) + return region.RegionId } func (region *SRegion) GetGlobalId() string { diff --git a/vendor/yunion.io/x/pkg/utils/tags.go b/vendor/yunion.io/x/pkg/utils/tags.go index 9926630cc5..6bd4bef8a2 100644 --- a/vendor/yunion.io/x/pkg/utils/tags.go +++ b/vendor/yunion.io/x/pkg/utils/tags.go @@ -39,28 +39,32 @@ func Unquote(str string) string { } func findString(str []byte, offset int) (string, int) { - return _findWord(str, offset, "\n\r") + return _findWord(str, offset, "\n\r", isQuoteCharInternal) } func findWord(str []byte, offset int) (string, int) { - return _findWord(str, offset, " :,\t\n}]") + return _findWord(str, offset, " :,\t\n}]", isQuoteCharInternal) } -func _findWord(str []byte, offset int, sepChars string) (string, int) { +func isQuoteCharInternal(ch byte) (bool, string) { + switch ch { + case '"': + return true, "\"" + case '\'': + return true, "'" + default: + return false, "" + } +} + +func _findWord(str []byte, offset int, sepChars string, isQuoteChar func(ch byte) (bool, string)) (string, int) { var buffer bytes.Buffer i := skipEmpty(str, offset) if i >= len(str) { return "", i } - var endstr string - quote := false - if str[i] == '"' { - quote = true - endstr = "\"" - i++ - } else if str[i] == '\'' { - quote = true - endstr = "'" + quote, endstr := isQuoteChar(str[i]) + if quote { i++ } else { // endstr = " :,\t\n\r}]" @@ -98,22 +102,30 @@ func _findWord(str []byte, offset int, sepChars string) (string, int) { } func FindWords(str []byte, offset int) []string { + words, err := FindWords2(str, offset, " :,\t\n}]", isQuoteCharInternal) + if err != nil { + panic(err.Error()) + } + return words +} + +func FindWords2(str []byte, offset int, sepChars string, isQuoteChar func(ch byte) (bool, string)) ([]string, error) { words := make([]string, 0) for offset < len(str) { - word, i := findWord(str, offset) + word, i := _findWord(str, offset, sepChars, isQuoteChar) words = append(words, word) i = skipEmpty(str, i) if i < len(str) { - if str[i] == ',' { + if strings.IndexByte(sepChars, str[i]) >= 0 { offset = i + 1 } else { - panic(fmt.Sprintf("Malformed multi value string: %s", string(str[offset:]))) + return nil, fmt.Errorf("Malformed multi value string: %s", string(str[offset:])) } } else { offset = i } } - return words + return words, nil } func TagMap(tag reflect.StructTag) map[string]string { @@ -155,7 +167,7 @@ func SplitCSV(csv string) []string { str := []byte(csv) for offset < len(str) { var word string - word, offset = _findWord(str, offset, ",\r\n") + word, offset = _findWord(str, offset, ",\r\n", isQuoteCharInternal) words = append(words, word) if offset < len(str) { offset++