From 4c3186f4a1bcddb0dd31953401164ee8eab0f8df Mon Sep 17 00:00:00 2001 From: Jian Qiu Date: Tue, 23 Sep 2025 23:23:00 +0800 Subject: [PATCH] Automated cherry pick of #23363: fix: network filter by ip error for dameng (#23366) * fix: network filter by ip error for dameng * fix: update vendor 20250923 --------- Co-authored-by: Qiu Jian --- go.mod | 4 +- go.sum | 8 +- pkg/compute/models/networks.go | 8 + vendor/modules.txt | 4 +- .../pkg/multicloud/google/instance.go | 2 +- .../pkg/multicloud/qcloud/dbinstance.go | 7 + .../cloudmux/pkg/multicloud/qcloud/monitor.go | 94 +++- .../pkg/multicloud/qcloud/rds_sqlserver.go | 459 ++++++++++++++++++ .../pkg/multicloud/qcloud/tag_base.go | 2 +- .../x/sqlchemy/backends/dameng/sync.go | 10 + vendor/yunion.io/x/sqlchemy/reflect.go | 113 +++++ vendor/yunion.io/x/sqlchemy/update.go | 3 + 12 files changed, 699 insertions(+), 15 deletions(-) create mode 100644 vendor/yunion.io/x/cloudmux/pkg/multicloud/qcloud/rds_sqlserver.go diff --git a/go.mod b/go.mod index b9acef3c04..21b55eb741 100644 --- a/go.mod +++ b/go.mod @@ -87,14 +87,14 @@ require ( k8s.io/client-go v0.19.3 k8s.io/cluster-bootstrap v0.19.3 moul.io/http2curl/v2 v2.3.0 - yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250912144914-f4ac27216443 + yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250919074216-efb21a7a9220 yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0 yunion.io/x/jsonutils v1.0.1-0.20250507052344-1abcf4f443b1 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.20250820035218-6008459eb4f0 yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1 - yunion.io/x/sqlchemy v1.1.3-0.20250902120005-3b18bc6371c7 + yunion.io/x/sqlchemy v1.1.3-0.20250923143347-b98e89dbc372 yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c ) diff --git a/go.sum b/go.sum index 427e2c71f2..592506178f 100644 --- a/go.sum +++ b/go.sum @@ -1271,8 +1271,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.20250912144914-f4ac27216443 h1:Ps0lKqMmqOBrW1V1zRvXugCW2LL5T/A+K8AXAJPUssI= -yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250912144914-f4ac27216443/go.mod h1:FXxAEbdNfWXX9gjME3K2nJhkydHY5EKEUZb+RLEzVwQ= +yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250919074216-efb21a7a9220 h1:+1QsqGzuTlEykMrMg056xFvxsCpbqWMpRIiFWmpi75o= +yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250919074216-efb21a7a9220/go.mod h1:FXxAEbdNfWXX9gjME3K2nJhkydHY5EKEUZb+RLEzVwQ= yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0 h1:msG4SiDSVU7CrXH06WuHlNEZXIooTcmNbfrIGHuIHBU= yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws= yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634= @@ -1290,7 +1290,7 @@ yunion.io/x/pkg v1.10.4-0.20250820035218-6008459eb4f0 h1:/vHcYqzQInxqR1jjS+e7A0o yunion.io/x/pkg v1.10.4-0.20250820035218-6008459eb4f0/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.20250902120005-3b18bc6371c7 h1:0OccQYkey6OsNUZNxd6CpCB/espBPnwlLT/gjl9YbXM= -yunion.io/x/sqlchemy v1.1.3-0.20250902120005-3b18bc6371c7/go.mod h1:vCIZpqhZ5Jzaq3tFyrti/vv8BijQKtkzSgNT/uH4H5A= +yunion.io/x/sqlchemy v1.1.3-0.20250923143347-b98e89dbc372 h1:8lR9HzYTxSgxcVv6uC2Ogkk1Y3FEEanABfgeleCzhfA= +yunion.io/x/sqlchemy v1.1.3-0.20250923143347-b98e89dbc372/go.mod h1:vCIZpqhZ5Jzaq3tFyrti/vv8BijQKtkzSgNT/uH4H5A= yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c h1:QuLab2kSRECZRxo4Lo2KcYn6XjQFDGaZ1+x0pYDVVwQ= yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c/go.mod h1:EP6NSv2C0zzqBDTKumv8hPWLb3XvgMZDHQRfyuOrQng= diff --git a/pkg/compute/models/networks.go b/pkg/compute/models/networks.go index d808144648..d9bcbb030b 100644 --- a/pkg/compute/models/networks.go +++ b/pkg/compute/models/networks.go @@ -2667,6 +2667,10 @@ func (manager *SNetworkManager) ListItemFilter( ipConst := sqlchemy.INET_ATON(q.StringField(ip4Addr.String())) ipCondtion = sqlchemy.AND( + sqlchemy.IsNotNull(q.Field("guest_ip_start")), + sqlchemy.IsNotNull(q.Field("guest_ip_end")), + sqlchemy.IsNotEmpty(q.Field("guest_ip_start")), + sqlchemy.IsNotEmpty(q.Field("guest_ip_end")), sqlchemy.GE(ipEnd, ipConst), sqlchemy.LE(ipStart, ipConst), ) @@ -2685,6 +2689,10 @@ func (manager *SNetworkManager) ListItemFilter( ipConst := sqlchemy.INET6_ATON(q.StringField(ip6Addr.String())) ipCondtion = sqlchemy.AND( + sqlchemy.IsNotNull(q.Field("guest_ip6_start")), + sqlchemy.IsNotNull(q.Field("guest_ip6_end")), + sqlchemy.IsNotEmpty(q.Field("guest_ip6_start")), + sqlchemy.IsNotEmpty(q.Field("guest_ip6_end")), sqlchemy.GE(ipEnd, ipConst), sqlchemy.LE(ipStart, ipConst), ) diff --git a/vendor/modules.txt b/vendor/modules.txt index 73e2ef6b86..951a66314d 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1576,7 +1576,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.20250912144914-f4ac27216443 +# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250919074216-efb21a7a9220 ## explicit; go 1.21 yunion.io/x/cloudmux/pkg/apis yunion.io/x/cloudmux/pkg/apis/billing @@ -1725,7 +1725,7 @@ yunion.io/x/pkg/utils # yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1 ## explicit; go 1.12 yunion.io/x/s3cli -# yunion.io/x/sqlchemy v1.1.3-0.20250902120005-3b18bc6371c7 +# yunion.io/x/sqlchemy v1.1.3-0.20250923143347-b98e89dbc372 ## explicit; go 1.17 yunion.io/x/sqlchemy yunion.io/x/sqlchemy/backends diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/google/instance.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/google/instance.go index e37da455ff..96471daaed 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/google/instance.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/google/instance.go @@ -609,7 +609,7 @@ func (region *SRegion) _createVM(zone string, desc *cloudprovider.SManagedVMCrea if err != nil { return nil, errors.Wrap(err, "region.GetNetwork") } - networkInterface["network"] = vpc.SelfLink + networkInterface["subnetwork"] = getGlobalId(vpc.SelfLink) } if len(desc.IpAddr) > 0 { networkInterface["networkIp"] = desc.IpAddr diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/qcloud/dbinstance.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/qcloud/dbinstance.go index 77f013c483..076254b54a 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/qcloud/dbinstance.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/qcloud/dbinstance.go @@ -36,6 +36,11 @@ func (self *SRegion) GetIDBInstances() ([]cloudprovider.ICloudDBInstance, error) return nil, errors.Wrapf(err, "GetITDSQLs") } ret = append(ret, tdsqls...) + mssqls, err := self.GetISQLServers() + if err != nil { + return nil, errors.Wrapf(err, "GetISQLServers") + } + ret = append(ret, mssqls...) return ret, nil } @@ -44,6 +49,8 @@ func (self *SRegion) GetIDBInstanceById(id string) (cloudprovider.ICloudDBInstan return self.GetMySQLInstanceById(id) } else if strings.HasPrefix(id, "tdsqlshard") { return self.GetTDSQL(id) + } else if strings.HasPrefix(id, "mssql") { + return self.GetSQLServer(id) } return nil, cloudprovider.ErrNotFound } diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/qcloud/monitor.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/qcloud/monitor.go index ae5fdd20a8..0f6133c109 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/qcloud/monitor.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/qcloud/monitor.go @@ -16,6 +16,7 @@ package qcloud import ( "fmt" + "strconv" "strings" "time" @@ -84,11 +85,14 @@ func (self *SQcloudClient) metricsRequest(action string, params map[string]strin return monitorRequest(cli, action, params, self.cpcfg.UpdatePermission, self.debug) } -func (self *SQcloudClient) GetMonitorData(ns string, name string, since time.Time, until time.Time, regionId string, dimensionName string, resIds []string) ([]SDataPoint, error) { +func (self *SQcloudClient) GetMonitorData(ns string, name string, period int, since time.Time, until time.Time, regionId string, dimensionName string, resIds []string) ([]SDataPoint, error) { params := make(map[string]string) params["Region"] = regionId params["MetricName"] = name params["Namespace"] = ns + if period > 0 { + params["Period"] = strconv.Itoa(period) + } params["StartTime"] = since.Format(timeutils.IsoTimeFormat) params["EndTime"] = until.Format(timeutils.IsoTimeFormat) for idx, resId := range resIds { @@ -164,7 +168,7 @@ func (self *SQcloudClient) GetEcsMetrics(opts *cloudprovider.MetricListOptions) }, } { for metricName, tag := range metricNames { - metrics, err := self.GetMonitorData("QCE/CVM", metricName, opts.StartTime, opts.EndTime, opts.RegionExtId, "InstanceId", opts.ResourceIds) + metrics, err := self.GetMonitorData("QCE/CVM", metricName, 0, opts.StartTime, opts.EndTime, opts.RegionExtId, "InstanceId", opts.ResourceIds) if err != nil { log.Errorf("GetMonitorData error: %v", err) continue @@ -232,7 +236,7 @@ func (self *SQcloudClient) GetRedisMetrics(opts *cloudprovider.MetricListOptions }, } { for metricName, tag := range metricNames { - metrics, err := self.GetMonitorData("QCE/REDIS_MEM", metricName, opts.StartTime, opts.EndTime, opts.RegionExtId, "instanceid", opts.ResourceIds) + metrics, err := self.GetMonitorData("QCE/REDIS_MEM", metricName, 0, opts.StartTime, opts.EndTime, opts.RegionExtId, "instanceid", opts.ResourceIds) if err != nil { log.Errorf("GetMonitorData error: %v", err) continue @@ -265,7 +269,60 @@ func (self *SQcloudClient) GetRedisMetrics(opts *cloudprovider.MetricListOptions return ret, nil } -func (self *SQcloudClient) GetRdsMetrics(opts *cloudprovider.MetricListOptions) ([]cloudprovider.MetricValues, error) { +func (self *SQcloudClient) GetSQLServerMetrics(opts *cloudprovider.MetricListOptions, resourceIds []string) ([]cloudprovider.MetricValues, error) { + ret := []cloudprovider.MetricValues{} + for metricType, metricNames := range map[cloudprovider.TMetricType]map[string]string{ + cloudprovider.RDS_METRIC_TYPE_CPU_USAGE: { + "Cpu": "", + }, + cloudprovider.RDS_METRIC_TYPE_MEM_USAGE: { + "UsageMemory": "", + }, + cloudprovider.RDS_METRIC_TYPE_DISK_USAGE: { + "FreeStorage": "", + }, + cloudprovider.RDS_METRIC_TYPE_CONN_COUNT: { + "Connections": "", + }, + } { + for metricName, tag := range metricNames { + metrics, err := self.GetMonitorData("QCE/SQLSERVER", metricName, 60, opts.StartTime, opts.EndTime, opts.RegionExtId, "resourceId", resourceIds) + if err != nil { + log.Errorf("GetMonitorData error: %v", err) + continue + } + for i := range metrics { + metric := cloudprovider.MetricValues{} + if len(metrics[i].Dimensions) < 1 || metrics[i].Dimensions[0].Name != "resourceId" { + continue + } + metric.Id = metrics[i].Dimensions[0].Value + metric.MetricType = metricType + metricValue := cloudprovider.MetricValue{} + metricValue.Tags = map[string]string{} + idx := strings.Index(tag, ":") + if idx > 0 { + metricValue.Tags[tag[:idx]] = tag[idx+1:] + } + if len(metrics[i].Timestamps) == 0 { + continue + } + for j := range metrics[i].Timestamps { + metricValue.Value = metrics[i].Values[j] + if metricType == cloudprovider.RDS_METRIC_TYPE_DISK_USAGE { + metricValue.Value = 100 - metricValue.Value + } + metricValue.Timestamp = time.Unix(int64(metrics[i].Timestamps[j]), 0) + metric.Values = append(metric.Values, metricValue) + } + ret = append(ret, metric) + } + } + } + return ret, nil +} + +func (self *SQcloudClient) GetMySQLMetrics(opts *cloudprovider.MetricListOptions, resourceIds []string) ([]cloudprovider.MetricValues, error) { ret := []cloudprovider.MetricValues{} for metricType, metricNames := range map[cloudprovider.TMetricType]map[string]string{ cloudprovider.RDS_METRIC_TYPE_CPU_USAGE: { @@ -303,7 +360,7 @@ func (self *SQcloudClient) GetRdsMetrics(opts *cloudprovider.MetricListOptions) }, } { for metricName, tag := range metricNames { - metrics, err := self.GetMonitorData("QCE/CDB", metricName, opts.StartTime, opts.EndTime, opts.RegionExtId, "InstanceId", opts.ResourceIds) + metrics, err := self.GetMonitorData("QCE/CDB", metricName, 60, opts.StartTime, opts.EndTime, opts.RegionExtId, "InstanceId", resourceIds) if err != nil { log.Errorf("GetMonitorData error: %v", err) continue @@ -336,6 +393,33 @@ func (self *SQcloudClient) GetRdsMetrics(opts *cloudprovider.MetricListOptions) return ret, nil } +func (self *SQcloudClient) GetRdsMetrics(opts *cloudprovider.MetricListOptions) ([]cloudprovider.MetricValues, error) { + cdbs, mssqls := []string{}, []string{} + for _, resourceId := range opts.ResourceIds { + if strings.HasPrefix(resourceId, "cdb") { + cdbs = append(cdbs, resourceId) + } else if strings.HasPrefix(resourceId, "mssql") { + mssqls = append(mssqls, resourceId) + } + } + ret := []cloudprovider.MetricValues{} + if len(cdbs) > 0 { + part, err := self.GetMySQLMetrics(opts, cdbs) + if err != nil { + return nil, err + } + ret = append(ret, part...) + } + if len(mssqls) > 0 { + part, err := self.GetSQLServerMetrics(opts, mssqls) + if err != nil { + return nil, err + } + ret = append(ret, part...) + } + return ret, nil +} + func (self *SQcloudClient) GetK8sMetrics(opts *cloudprovider.MetricListOptions) ([]cloudprovider.MetricValues, error) { ret := []cloudprovider.MetricValues{} for metricType, metricName := range map[cloudprovider.TMetricType]string{ diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/qcloud/rds_sqlserver.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/qcloud/rds_sqlserver.go new file mode 100644 index 0000000000..d17338f814 --- /dev/null +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/qcloud/rds_sqlserver.go @@ -0,0 +1,459 @@ +// 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 qcloud + +import ( + "context" + "fmt" + "strings" + "time" + + billingapi "yunion.io/x/cloudmux/pkg/apis/billing" + api "yunion.io/x/cloudmux/pkg/apis/compute" + "yunion.io/x/cloudmux/pkg/cloudprovider" + "yunion.io/x/cloudmux/pkg/multicloud" + "yunion.io/x/jsonutils" + "yunion.io/x/pkg/errors" + "yunion.io/x/pkg/util/billing" +) + +/* + { + "Architecture": "SINGLE", + "BackupCycle": + [], + "BackupCycleType": "", + "BackupModel": "", + "BackupSaveDays": 7, + "BackupTime": "", + "Collation": "Chinese_PRC_CI_AS", + "Cpu": 2, + "CreateTime": "2025-09-16 20:27:09", + "CrossBackupEnabled": "disable", + "CrossBackupSaveDays": 0, + "CrossRegions": + [], + "DnsPodDomain": "", + "EndTime": "0000-00-00 00:00:00", + "HAFlag": "SINGLE", + "InstanceId": "mssql-ezqm0pk4", + "InstanceNote": "", + "InstanceType": "SI", + "IsDrZone": false, + "IsolateOperator": "", + "IsolateTime": "0000-00-00 00:00:00", + "Memory": 4, + "Model": 2, + "MultiSlaveZones": + [], + "Name": "11b58192-1ddd-4dc8-8ae9-454ac919927f", + "PayMode": 0, + "Pid": 1003456, + "ProjectId": 0, + "ROFlag": "", + "Region": "ap-beijing", + "RegionId": 8, + "RenewFlag": 0, + "SlaveZones": + { + "SlaveZone": "", + "SlaveZoneName": "" + }, + "StartTime": "2025-09-16 20:27:09", + "Status": 1, + "Storage": 20, + "Style": "EXCLUSIVE", + "SubFlag": "", + "SubnetId": 1344612, + "TgwWanVPort": 0, + "TimeZone": "China Standard Time", + "Type": "CLOUD_BSSD", + "Uid": "", + "UniqSubnetId": "subnet-ej5fo5gd", + "UniqVpcId": "vpc-dvnlj4aq", + "UpdateTime": "2025-09-16 20:27:09", + "UsedStorage": 0, + "Version": "2019", + "VersionName": "SQL Server 2019 Enterprise", + "Vip": "", + "VpcId": 3832347, + "Vport": 0, + "Zone": "ap-beijing-5", + "ZoneId": 800005 + } +*/ + +type SSQLServer struct { + multicloud.SDBInstanceBase + QcloudTags + + Architecture string + BackupCycle []string + BackupCycleType string + BackupModel string + BackupSaveDays int + BackupTime string + Collation string + Cpu int + CreateTime time.Time + CrossBackupEnabled string + CrossBackupSaveDays int + CrossRegions []string + DnsPodDomain string + EndTime time.Time + HAFlag string + InstanceId string + InstanceNote string + InstanceType string + IsDrZone bool + IsolateOperator string + IsolateTime string + Memory int + Model int + MultiSlaveZones []string + Name string + PayMode int + Pid int + ProjectId string + ROFlag string + Region string + RegionId int + RenewFlag int + SlaveZones struct { + SlaveZone string + SlaveZoneName string + } + StartTime string + Status int + Storage int + Style string + SubFlag string + SubnetId int + TgwWanVPort int + TimeZone string + Type string + Uid string + UniqSubnetId string + UniqVpcId string + UpdateTime string + UsedStorage int + Version string + VersionName string + Vip string + VpcId int + Vport int + Zone string + ZoneId int + + region *SRegion +} + +func (mssql *SSQLServer) GetId() string { + return mssql.InstanceId +} + +func (mssql *SSQLServer) GetGlobalId() string { + return mssql.InstanceId +} + +func (mssql *SSQLServer) GetName() string { + if len(mssql.Name) > 0 { + return mssql.Name + } + return mssql.InstanceId +} + +func (mssql *SSQLServer) GetDiskSizeGB() int { + return mssql.Storage +} + +func (mssql *SSQLServer) GetEngine() string { + return api.DBINSTANCE_TYPE_SQLSERVER +} + +func (mssql *SSQLServer) GetEngineVersion() string { + return mssql.Version +} + +func (mssql *SSQLServer) GetIVpcId() string { + return mssql.UniqVpcId +} + +func (mssql *SSQLServer) Refresh() error { + rds, err := mssql.region.GetSQLServer(mssql.InstanceId) + if err != nil { + return errors.Wrapf(err, "GetSQLServer(%s)", mssql.InstanceId) + } + return jsonutils.Update(mssql, rds) +} + +func (mssql *SSQLServer) GetInstanceType() string { + return fmt.Sprintf("%d核%dMB", mssql.Cpu, mssql.Memory) +} + +func (mssql *SSQLServer) GetMaintainTime() string { + return "" +} + +func (mssql *SSQLServer) GetDBNetworks() ([]cloudprovider.SDBInstanceNetwork, error) { + return []cloudprovider.SDBInstanceNetwork{ + {NetworkId: mssql.UniqSubnetId, IP: mssql.Vip}, + }, nil +} + +func (mssql *SSQLServer) GetConnectionStr() string { + return "" +} + +func (mssql *SSQLServer) GetInternalConnectionStr() string { + return fmt.Sprintf("%s:%d", mssql.Vip, mssql.Vport) +} + +func (mssql *SSQLServer) Reboot() error { + return cloudprovider.ErrNotImplemented +} + +func (mssql *SSQLServer) ChangeConfig(ctx context.Context, opts *cloudprovider.SManagedDBInstanceChangeConfig) error { + return cloudprovider.ErrNotImplemented +} + +func (mssql *SSQLServer) GetMasterInstanceId() string { + return "" +} + +func (mssql *SSQLServer) GetSecurityGroupIds() ([]string, error) { + return mssql.region.DescribeSQLServerDBSecurityGroups(mssql.InstanceId) +} + +func (region *SRegion) DescribeSQLServerDBSecurityGroups(id string) ([]string, error) { + params := map[string]string{ + "InstanceId": id, + } + resp, err := region.sqlserverRequest("DescribeDBSecurityGroups", params) + if err != nil { + return []string{}, errors.Wrapf(err, "DescribeDBSecurityGroups") + } + ret := struct { + SecurityGroupSet []struct { + SecurityGroupId string + } + }{} + err = resp.Unmarshal(&ret) + if err != nil { + return nil, errors.Wrapf(err, "Unmarshal") + } + groups := []string{} + for i := range ret.SecurityGroupSet { + groups = append(groups, ret.SecurityGroupSet[i].SecurityGroupId) + } + + return groups, nil +} + +func (mssql *SSQLServer) SetSecurityGroups(ids []string) error { + return mssql.region.ModifyDBInstanceSecurityGroups(mssql.InstanceId, ids) +} + +func (region *SRegion) ModifyDBInstanceSecurityGroups(rdsId string, secIds []string) error { + params := map[string]string{ + "InstanceId": rdsId, + } + for idx, id := range secIds { + params[fmt.Sprintf("SecurityGroupIdSet.%d", idx)] = id + } + _, err := region.sqlserverRequest("ModifyDBInstanceSecurityGroups", params) + return err +} + +func (mssql *SSQLServer) Renew(bc billing.SBillingCycle) error { + return cloudprovider.ErrNotImplemented +} + +func (mssql *SSQLServer) OpenPublicConnection() error { + return cloudprovider.ErrNotImplemented +} + +func (mssql *SSQLServer) ClosePublicConnection() error { + return cloudprovider.ErrNotImplemented +} + +func (mssql *SSQLServer) GetPort() int { + return mssql.Vport +} + +func (mssql *SSQLServer) GetStatus() string { + switch mssql.Status { + case 1: + return api.DBINSTANCE_DEPLOYING + case 2, 3: + return api.DBINSTANCE_RUNNING + case 5, 6, 8: + return api.DBINSTANCE_DELETING + case 7, 9, 13, 14, 15, 16, 17: + return api.DBINSTANCE_UPGRADING + case 4: + return api.DBINSTANCE_ISOLATE + case 12: + return api.DBINSTANCE_REBOOTING + case 10: + return api.DBINSTANCE_MIGRATING + default: + return api.DBINSTANCE_DEPLOYING + } +} + +func (mssql *SSQLServer) GetCategory() string { + return strings.ToLower(mssql.Architecture) +} + +func (mssql *SSQLServer) GetStorageType() string { + return api.QCLOUD_DBINSTANCE_STORAGE_TYPE_CLOUD_SSD +} + +func (mssql *SSQLServer) GetCreatedAt() time.Time { + // 2019-12-25 09:00:43 #非UTC时间 + return mssql.CreateTime.Add(time.Hour * -8) +} + +func (mssql *SSQLServer) GetBillingType() string { + if mssql.PayMode == 1 { + return billingapi.BILLING_TYPE_PREPAID + } + return billingapi.BILLING_TYPE_POSTPAID +} + +func (mssql *SSQLServer) SetAutoRenew(bc billing.SBillingCycle) error { + return cloudprovider.ErrNotImplemented +} + +func (mssql *SSQLServer) IsAutoRenew() bool { + return mssql.RenewFlag == 1 +} + +func (mssql *SSQLServer) GetExpiredAt() time.Time { + return mssql.EndTime +} + +func (mssql *SSQLServer) GetVcpuCount() int { + return mssql.Cpu +} + +func (mssql *SSQLServer) GetVmemSizeMB() int { + return mssql.Memory * 1024 +} + +func (mssql *SSQLServer) GetZone1Id() string { + return mssql.Zone +} + +func (mssql *SSQLServer) GetZone2Id() string { + return mssql.SlaveZones.SlaveZone +} + +func (mssql *SSQLServer) GetZone3Id() string { + return mssql.SlaveZones.SlaveZone +} + +func (mssql *SSQLServer) GetProjectId() string { + return mssql.ProjectId +} + +func (mssql *SSQLServer) Delete() error { + err := mssql.region.DeleteSQLServer(mssql.InstanceId) + if err != nil { + return errors.Wrapf(err, "DeleteSQLServer") + } + return mssql.region.DeleteSQLServerInRecycleBin(mssql.InstanceId) +} + +func (region *SRegion) GetSQLServers(id string) ([]SSQLServer, error) { + params := map[string]string{} + if len(id) > 0 { + params["InstanceIdSet.0"] = id + } + offset := 0 + ret := []SSQLServer{} + for { + resp, err := region.sqlserverRequest("DescribeDBInstances", params) + if err != nil { + return nil, errors.Wrapf(err, "DescribeDBInstances") + } + part := struct { + DBInstances []SSQLServer + TotalCount int + }{} + err = resp.Unmarshal(&part) + if err != nil { + return nil, errors.Wrapf(err, "resp.Unmarshal") + } + for i := range part.DBInstances { + if part.DBInstances[i].Status == 4 { // 过滤掉回收站 + continue + } + part.DBInstances[i].region = region + + ret = append(ret, part.DBInstances[i]) + } + if len(ret) >= part.TotalCount || len(part.DBInstances) == 0 { + break + } + offset++ + params["Offset"] = fmt.Sprintf("%d", offset) + } + return ret, nil +} + +func (region *SRegion) GetISQLServers() ([]cloudprovider.ICloudDBInstance, error) { + servers, err := region.GetSQLServers("") + if err != nil { + return nil, errors.Wrapf(err, "GetSQLServers") + } + ret := []cloudprovider.ICloudDBInstance{} + for i := range servers { + servers[i].region = region + ret = append(ret, &servers[i]) + } + return ret, nil +} + +func (region *SRegion) GetSQLServer(id string) (*SSQLServer, error) { + vms, err := region.GetSQLServers(id) + if err != nil { + return nil, errors.Wrapf(err, "GetSQLServers") + } + for i := range vms { + if vms[i].InstanceId == id { + vms[i].region = region + return &vms[i], nil + } + } + return nil, cloudprovider.ErrNotFound +} + +func (region *SRegion) DeleteSQLServer(id string) error { + params := map[string]string{ + "InstanceIdSet.0": id, + } + _, err := region.sqlserverRequest("TerminateDBInstance", params) + return err +} + +func (region *SRegion) DeleteSQLServerInRecycleBin(id string) error { + params := map[string]string{ + "InstanceId": id, + } + _, err := region.sqlserverRequest("DeleteDBInstance", params) + return err +} diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/qcloud/tag_base.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/qcloud/tag_base.go index 030fd26646..73e281cb5b 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/qcloud/tag_base.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/qcloud/tag_base.go @@ -34,7 +34,7 @@ type QcloudTags struct { Tags []multicloud.STag // Cdn Tag []multicloud.STag - // TDSQL + // TDSQL, SQLServer ResourceTags []multicloud.STag } diff --git a/vendor/yunion.io/x/sqlchemy/backends/dameng/sync.go b/vendor/yunion.io/x/sqlchemy/backends/dameng/sync.go index 08ef053288..a607448e22 100644 --- a/vendor/yunion.io/x/sqlchemy/backends/dameng/sync.go +++ b/vendor/yunion.io/x/sqlchemy/backends/dameng/sync.go @@ -145,6 +145,16 @@ func (mysql *SDamengBackend) CommitTableChangeSQL(ts sqlchemy.ITableSpec, change sql := fmt.Sprintf(`ALTER TABLE "%s" ALTER COLUMN "%s" DROP DEFAULT`, ts.Name(), cols.NewCol.Name()) alters = append(alters, sql) } + + if cols.NewCol.IsNullable() != cols.OldCol.IsNullable() { + if cols.NewCol.IsNullable() { + sql := fmt.Sprintf(`ALTER TABLE "%s" MODIFY "%s" NULL`, ts.Name(), cols.NewCol.Name()) + alters = append(alters, sql) + } else { + sql := fmt.Sprintf(`ALTER TABLE "%s" ALTER COLUMN "%s" SET NOT NULL`, ts.Name(), cols.NewCol.Name()) + alters = append(alters, sql) + } + } } } for _, col := range changes.AddColumns { diff --git a/vendor/yunion.io/x/sqlchemy/reflect.go b/vendor/yunion.io/x/sqlchemy/reflect.go index 27c84d4509..e7d3ae2044 100644 --- a/vendor/yunion.io/x/sqlchemy/reflect.go +++ b/vendor/yunion.io/x/sqlchemy/reflect.go @@ -758,3 +758,116 @@ func ConvertValueToString(val interface{}) string { } return jsonutils.Marshal(val).String() } + +func getFloatValue(val interface{}) (float64, error) { + switch v := val.(type) { + case float32: + return float64(v), nil + case float64: + return v, nil + case int: + return float64(v), nil + case int8: + return float64(v), nil + case int16: + return float64(v), nil + case int32: + return float64(v), nil + case int64: + return float64(v), nil + case uint: + return float64(v), nil + case uint8: + return float64(v), nil + case uint16: + return float64(v), nil + case uint32: + return float64(v), nil + case uint64: + return float64(v), nil + case *float32: + return float64(*v), nil + case *float64: + return *v, nil + case *int: + return float64(*v), nil + case *int8: + return float64(*v), nil + case *int16: + return float64(*v), nil + case *int32: + return float64(*v), nil + case *int64: + return float64(*v), nil + case *uint: + return float64(*v), nil + case *uint8: + return float64(*v), nil + case *uint16: + return float64(*v), nil + case *uint32: + return float64(*v), nil + case *uint64: + return float64(*v), nil + case string: + return strconv.ParseFloat(v, 64) + case *string: + return strconv.ParseFloat(*v, 64) + } + return 0, errors.ErrInvalidFormat +} + +func getTimeValue(val interface{}) (time.Time, error) { + switch v := val.(type) { + case time.Time: + return v, nil + case *time.Time: + return *v, nil + case string: + return timeutils.ParseTimeStr(v) + case *string: + return timeutils.ParseTimeStr(*v) + } + return time.Time{}, errors.ErrInvalidFormat +} + +const MIN_FLOAT_EQUAL_DIFF = float64(0.000001) + +func floatEqual(of, nf float64) bool { + if of > nf { + return of < MIN_FLOAT_EQUAL_DIFF+nf + } else if of < nf { + return of+MIN_FLOAT_EQUAL_DIFF > nf + } else { + return true + } +} + +const MIN_MICRO_SECOND_EQUAL_DIFF = 1000000 + +func timeEqual(of, nf time.Time) bool { + ofUnix := of.UnixMicro() + nfUnix := nf.UnixMicro() + if ofUnix == nfUnix { + return true + } + if ofUnix > nfUnix { + return ofUnix < MIN_MICRO_SECOND_EQUAL_DIFF+nfUnix + } else { + return ofUnix+MIN_MICRO_SECOND_EQUAL_DIFF > nfUnix + } +} + +func EqualsGrossValue(of, nf interface{}) bool { + ofFloat, ofErr := getFloatValue(of) + nfFloat, nfErr := getFloatValue(nf) + if ofErr == nil && nfErr == nil { + return floatEqual(ofFloat, nfFloat) + } + ofTime, ofErr := getTimeValue(of) + nfTime, nfErr := getTimeValue(nf) + if ofErr == nil && nfErr == nil { + return timeEqual(ofTime, nfTime) + } + return false +} diff --git a/vendor/yunion.io/x/sqlchemy/update.go b/vendor/yunion.io/x/sqlchemy/update.go index e14db490e3..727fd369f9 100644 --- a/vendor/yunion.io/x/sqlchemy/update.go +++ b/vendor/yunion.io/x/sqlchemy/update.go @@ -174,6 +174,9 @@ func (us *SUpdateSession) SaveUpdateSql(dt interface{}) (*SUpdateSQLResult, erro if ofJsonStr == nfJsonStr { continue } + if EqualsGrossValue(of, nf) { + continue + } } if c.IsZero(nf) && c.IsText() { nf = nil