yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/ecloud/monitor.go (about) 1 // Copyright 2019 Yunion 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package ecloud 16 17 import ( 18 "context" 19 "strconv" 20 "time" 21 22 "yunion.io/x/jsonutils" 23 "yunion.io/x/pkg/errors" 24 "yunion.io/x/pkg/util/timeutils" 25 "yunion.io/x/pkg/utils" 26 27 "yunion.io/x/cloudmux/pkg/cloudprovider" 28 "yunion.io/x/onecloud/pkg/httperrors" 29 ) 30 31 const ( 32 MONITOR_FETCH_REQUEST_ACTION = "v1.dawn.monitor.fetch" 33 MONITOR_PRODUCT_REQUEST_ACTION = "v1.dawn.monitor.products" 34 35 MONITOR_FETCH_SERVER_PATH = "/api/edw/edw/api" 36 37 REQUEST_SUCCESS_CODE = "000000" 38 ) 39 40 var ( 41 noMetricRegion = []string{"guangzhou-2", "beijing-1", "hunan-1"} 42 43 portRegionMap = map[string][]string{ 44 "8443": {"wuxi-1", "dongguan-1", "yaan-1", "zhengzhou-1", "beijing-2", "zhuzhou-1", "jinan-1", 45 "xian-1", "shanghai-1", "chongqing-1", "ningbo-1"}, 46 "18080": {"tianjin-1", "jilin-1", "hubei-1", "jiangxi-1", "gansu-1", "shanxi-1", "liaoning-1", 47 "yunnan-2", "hebei-1", "fujian-1", "guangxi-1", "anhui-1", "huhehaote-1", "guiyang-1"}, 48 } 49 ) 50 51 type Metric struct { 52 Name string `json:"MetricName"` 53 } 54 55 type MetricData struct { 56 Entitys []Entity `json:"entity"` 57 } 58 59 type Entity struct { 60 ResourceID string `json:"resourceId"` 61 MetricName string `json:"metricName"` 62 MetricNameCN string `json:"metricNameCn"` 63 Unit string `json:"unit"` 64 MaxValue int64 `json:"maxValue"` 65 AvgValue int64 `json:"avgValue"` 66 MinValue int64 `json:"minValue"` 67 Granularity string `json:"granularity"` 68 PolymerizeType string `json:"polymerizeType"` 69 SelectedMetricItem interface{} `json:"selectedMetricItem"` 70 MetricItems interface{} `json:"metricItems"` 71 IsChildnode bool `json:"isChildnode"` 72 Datapoints []Datapoint `json:"datapoints"` 73 } 74 75 type Datapoint []string 76 77 type SMonitorRequest struct { 78 SApiRequest 79 } 80 81 func NewMonitorRequest(regionId string, serverPath string, query map[string]string, data jsonutils.JSONObject) *SMonitorRequest { 82 apiRequest := NewApiRequest(regionId, serverPath, query, data) 83 return &SMonitorRequest{*apiRequest} 84 } 85 86 func (rr *SMonitorRequest) GetPort() string { 87 for port, regions := range portRegionMap { 88 if utils.IsInStringArray(rr.GetRegionId(), regions) { 89 return port 90 } 91 } 92 return "8443" 93 } 94 95 func (br *SMonitorRequest) ForMateResponseBody(jrbody jsonutils.JSONObject) (jsonutils.JSONObject, error) { 96 code, _ := jrbody.GetString("code") 97 if code != REQUEST_SUCCESS_CODE { 98 message, _ := jrbody.(*jsonutils.JSONDict).GetString("message") 99 return nil, httperrors.NewBadRequestError("rep body code is :%s, message:%s,body:%v", code, message, jrbody) 100 } 101 if jrbody == nil || !jrbody.Contains("entity") { 102 return nil, ErrMissKey{ 103 Key: "entity", 104 Jo: jrbody, 105 } 106 } 107 return jrbody, nil 108 } 109 110 func (self *SEcloudClient) DescribeMetricList(regionId, productType string, metrics []Metric, resourceId string, 111 since time.Time, until time.Time) (MetricData, error) { 112 metricData := MetricData{ 113 Entitys: make([]Entity, 0), 114 } 115 params := map[string]string{ 116 "eAction": MONITOR_FETCH_REQUEST_ACTION, 117 } 118 getBody := jsonutils.NewDict() 119 getBody.Set("startTime", jsonutils.NewString(since.Format(timeutils.MysqlTimeFormat))) 120 getBody.Set("endTime", jsonutils.NewString(until.Format(timeutils.MysqlTimeFormat))) 121 getBody.Set("productType", jsonutils.NewString(productType)) 122 getBody.Set("resourceId", jsonutils.NewString(resourceId)) 123 getBody.Set("metrics", jsonutils.Marshal(&metrics)) 124 request := NewMonitorRequest(regionId, MONITOR_FETCH_SERVER_PATH, params, getBody) 125 err := self.doGet(context.Background(), request, &metricData) 126 if err != nil { 127 return metricData, errors.Wrap(err, "client doGet error") 128 } 129 return metricData, nil 130 } 131 132 func (r *SRegion) GetProductTypes() (jsonutils.JSONObject, error) { 133 params := map[string]string{ 134 "eAction": MONITOR_PRODUCT_REQUEST_ACTION, 135 } 136 request := NewMonitorRequest(r.ID, MONITOR_FETCH_SERVER_PATH, params, nil) 137 rtn := jsonutils.NewDict() 138 err := r.client.doGet(context.Background(), request, rtn) 139 if err != nil { 140 return nil, errors.Wrap(err, "client doGet error") 141 } 142 return rtn, nil 143 } 144 145 func (self *SEcloudClient) GetMetrics(opts *cloudprovider.MetricListOptions) ([]cloudprovider.MetricValues, error) { 146 switch opts.ResourceType { 147 case cloudprovider.METRIC_RESOURCE_TYPE_SERVER: 148 return self.GetEcsMetrics(opts) 149 default: 150 return nil, errors.Wrapf(cloudprovider.ErrNotImplemented, "%s", opts.ResourceType) 151 } 152 } 153 154 func (self *SEcloudClient) GetEcsMetrics(opts *cloudprovider.MetricListOptions) ([]cloudprovider.MetricValues, error) { 155 metrics := map[string]cloudprovider.TMetricType{ 156 "cpu_util": cloudprovider.VM_METRIC_TYPE_CPU_USAGE, 157 "memory.util": cloudprovider.VM_METRIC_TYPE_MEM_USAGE, 158 "disk.device.read.requests.rate": cloudprovider.VM_METRIC_TYPE_DISK_IO_READ_IOPS, 159 "disk.device.write.requests.rate": cloudprovider.VM_METRIC_TYPE_DISK_IO_WRITE_IOPS, 160 "disk.device.read.bytes.rate": cloudprovider.VM_METRIC_TYPE_DISK_IO_READ_BPS, 161 "disk.device.write.bytes.rate": cloudprovider.VM_METRIC_TYPE_DISK_IO_WRITE_BPS, 162 "network.incoming.bytes": cloudprovider.VM_METRIC_TYPE_NET_BPS_RX, 163 "network.outgoing.bytes": cloudprovider.VM_METRIC_TYPE_NET_BPS_TX, 164 } 165 metricNames := []Metric{} 166 for metric := range metrics { 167 metricNames = append(metricNames, Metric{ 168 Name: metric, 169 }) 170 } 171 if utils.IsInStringArray(opts.RegionExtId, noMetricRegion) { 172 return []cloudprovider.MetricValues{}, nil 173 } 174 data, err := self.DescribeMetricList(opts.RegionExtId, "vm", metricNames, opts.ResourceId, opts.StartTime, opts.EndTime) 175 if err != nil { 176 return nil, errors.Wrapf(err, "DescribeMetricList") 177 } 178 ret := []cloudprovider.MetricValues{} 179 for _, value := range data.Entitys { 180 metric := cloudprovider.MetricValues{} 181 metric.Id = opts.ResourceId 182 metricType, ok := metrics[value.MetricName] 183 if !ok { 184 continue 185 } 186 metric.MetricType = metricType 187 for _, points := range value.Datapoints { 188 if len(points) != 2 { 189 continue 190 } 191 metricValue := cloudprovider.MetricValue{} 192 pointTime, err := strconv.ParseInt(points[1], 10, 64) 193 if err != nil { 194 continue 195 } 196 metricValue.Timestamp = time.Unix(pointTime, 0) 197 metricValue.Value, err = strconv.ParseFloat(points[0], 64) 198 if err != nil { 199 continue 200 } 201 metric.Values = append(metric.Values, metricValue) 202 } 203 ret = append(ret, metric) 204 } 205 return ret, nil 206 }