mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
fix(cloudmon): azure windows disk usage
This commit is contained in:
@@ -221,6 +221,7 @@ func (self *SCollectByResourceIdDriver) CollectServerMetrics(ctx context.Context
|
||||
RegionExtId: vm.RegionExtId,
|
||||
StartTime: start,
|
||||
EndTime: end,
|
||||
OsType: vm.OsType,
|
||||
}
|
||||
opts.ResourceId = vm.ExternalId
|
||||
|
||||
|
||||
@@ -358,6 +358,7 @@ type MetricListOptions struct {
|
||||
StartTime time.Time
|
||||
EndTime time.Time
|
||||
|
||||
OsType string
|
||||
Interval int
|
||||
// rds
|
||||
Engine string
|
||||
|
||||
@@ -64,8 +64,9 @@ const (
|
||||
type TAzureResource string
|
||||
|
||||
var (
|
||||
GraphResource = TAzureResource("graph")
|
||||
DefaultResource = TAzureResource("default")
|
||||
GraphResource = TAzureResource("graph")
|
||||
DefaultResource = TAzureResource("default")
|
||||
LoganalyticsResource = TAzureResource("loganalytics")
|
||||
)
|
||||
|
||||
type azureAuthClient struct {
|
||||
@@ -87,6 +88,8 @@ type SAzureClient struct {
|
||||
subscriptions []SSubscription
|
||||
|
||||
debug bool
|
||||
|
||||
workspaces []SLoganalyticsWorkspace
|
||||
}
|
||||
|
||||
type AzureClientConfig struct {
|
||||
@@ -182,6 +185,13 @@ func (self *SAzureClient) getClient(resource TAzureResource) (*azureAuthClient,
|
||||
case GraphResource:
|
||||
ret.domain = env.GraphEndpoint
|
||||
conf.Resource = env.GraphEndpoint
|
||||
case LoganalyticsResource:
|
||||
ret.domain = env.ResourceIdentifiers.OperationalInsights
|
||||
conf.Resource = env.ResourceIdentifiers.OperationalInsights
|
||||
if conf.Resource == "N/A" && self.envName == "AzureChinaCloud" {
|
||||
ret.domain = "https://api.loganalytics.azure.cn"
|
||||
conf.Resource = ret.domain
|
||||
}
|
||||
default:
|
||||
ret.domain = env.ResourceManagerEndpoint
|
||||
conf.Resource = env.ResourceManagerEndpoint
|
||||
@@ -213,6 +223,10 @@ func (self *SAzureClient) getGraphClient() (*azureAuthClient, error) {
|
||||
return self.getClient(GraphResource)
|
||||
}
|
||||
|
||||
func (self *SAzureClient) getLoganalyticsClient() (*azureAuthClient, error) {
|
||||
return self.getClient(LoganalyticsResource)
|
||||
}
|
||||
|
||||
func (self *SAzureClient) jsonRequest(method, path string, body jsonutils.JSONObject, params url.Values, showErrorMsg bool) (jsonutils.JSONObject, error) {
|
||||
cli, err := self.getDefaultClient()
|
||||
if err != nil {
|
||||
@@ -260,6 +274,18 @@ func (self *SAzureClient) jsonRequest(method, path string, body jsonutils.JSONOb
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func (self *SAzureClient) ljsonRequest(method, path string, body jsonutils.JSONObject, params url.Values) (jsonutils.JSONObject, error) {
|
||||
cli, err := self.getLoganalyticsClient()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "getLoganalyticsClient")
|
||||
}
|
||||
if params == nil {
|
||||
params = url.Values{}
|
||||
}
|
||||
params.Set("api-version", "2021-12-01-preview")
|
||||
return jsonRequest(cli.client, method, cli.domain, path, body, params, self.debug)
|
||||
}
|
||||
|
||||
func (self *SAzureClient) gjsonRequest(method, path string, body jsonutils.JSONObject, params url.Values) (jsonutils.JSONObject, error) {
|
||||
cli, err := self.getGraphClient()
|
||||
if err != nil {
|
||||
@@ -512,6 +538,8 @@ func (self *SAzureClient) _apiVersion(resource string, params url.Values) string
|
||||
return "2020-06-01"
|
||||
} else if utils.IsInStringArray("microsoft.containerservice", info) {
|
||||
return "2021-05-01"
|
||||
} else if utils.IsInStringArray("microsoft.operationalinsights", info) {
|
||||
return "2021-12-01-preview"
|
||||
}
|
||||
return AZURE_API_VERSION
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
// 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 azure
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/util/httputils"
|
||||
)
|
||||
|
||||
type SLoganalyticsWorkspace struct {
|
||||
Id string `json:"id"`
|
||||
Location string `json:"location"`
|
||||
Name string `json:"name"`
|
||||
SLoganalyticsWorkspaceProperties SLoganalyticsWorkspaceProperties `json:"properties"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
type SLoganalyticsWorkspaceProperties struct {
|
||||
CreatedDate string `json:"createdDate"`
|
||||
CustomerId string `json:"customerId"`
|
||||
SLoganalyticsWorkspacePropertiesFeatures SLoganalyticsWorkspacePropertiesFeatures `json:"features"`
|
||||
ModifiedDate string `json:"modifiedDate"`
|
||||
ProvisioningState string `json:"provisioningState"`
|
||||
PublicNetworkAccessForIngestion string `json:"publicNetworkAccessForIngestion"`
|
||||
PublicNetworkAccessForQuery string `json:"publicNetworkAccessForQuery"`
|
||||
RetentionInDays int `json:"retentionInDays"`
|
||||
SLoganalyticsWorkspacePropertiesSku SLoganalyticsWorkspacePropertiesSku `json:"sku"`
|
||||
Source string `json:"source"`
|
||||
SLoganalyticsWorkspacePropertiesWorkspaceCapping SLoganalyticsWorkspacePropertiesWorkspaceCapping `json:"workspaceCapping"`
|
||||
}
|
||||
|
||||
type SLoganalyticsWorkspacePropertiesWorkspaceCapping struct {
|
||||
DailyQuotaGb int `json:"dailyQuotaGb"`
|
||||
DataIngestionStatus string `json:"dataIngestionStatus"`
|
||||
QuotaNextResetTime string `json:"quotaNextResetTime"`
|
||||
}
|
||||
|
||||
type SLoganalyticsWorkspacePropertiesSku struct {
|
||||
LastSkuUpdate string `json:"lastSkuUpdate"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type SLoganalyticsWorkspacePropertiesFeatures struct {
|
||||
EnableLogAccessUsingOnlyResourcePermissions bool `json:"enableLogAccessUsingOnlyResourcePermissions"`
|
||||
Legacy int `json:"legacy"`
|
||||
SearchVersion int `json:"searchVersion"`
|
||||
}
|
||||
|
||||
func (self *SAzureClient) GetLoganalyticsWorkspaces() ([]SLoganalyticsWorkspace, error) {
|
||||
if len(self.workspaces) > 0 {
|
||||
return self.workspaces, nil
|
||||
}
|
||||
self.workspaces = []SLoganalyticsWorkspace{}
|
||||
return self.workspaces, self.list("Microsoft.OperationalInsights/workspaces", url.Values{}, &self.workspaces)
|
||||
}
|
||||
|
||||
type WorkspaceData struct {
|
||||
Name string
|
||||
Columns []struct {
|
||||
Name string
|
||||
Type string
|
||||
}
|
||||
Rows [][]string
|
||||
}
|
||||
|
||||
func (self *SAzureClient) GetInstanceDiskUsage(workspace string, instanceId string, start, end time.Time) ([]WorkspaceData, error) {
|
||||
params := url.Values{}
|
||||
params.Set("timespan", "P1D")
|
||||
query := fmt.Sprintf(`Perf | where ObjectName == "LogicalDisk" or ObjectName == "Logical Disk" | where _ResourceId == "%s" | where InstanceName != "_Total" | where CounterName == "%% Free Space" | where TimeGenerated between(datetime("%s") .. datetime("%s")) | project TimeGenerated, InstanceName, CounterValue, Computer, _ResourceId`, instanceId, start.Format(time.RFC3339), end.Format(time.RFC3339))
|
||||
params.Set("query", query)
|
||||
resp, err := self.ljsonRequest(string(httputils.GET), fmt.Sprintf("v1/workspaces/%s/query", workspace), nil, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := []WorkspaceData{}
|
||||
return ret, resp.Unmarshal(&ret, "tables")
|
||||
}
|
||||
@@ -19,11 +19,13 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/timeutils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
@@ -234,6 +236,48 @@ func (self *SAzureClient) GetEcsMetrics(opts *cloudprovider.MetricListOptions) (
|
||||
}
|
||||
}
|
||||
|
||||
if len(opts.OsType) == 0 || strings.Contains(strings.ToLower(opts.OsType), "win") {
|
||||
workspaces, err := self.GetLoganalyticsWorkspaces()
|
||||
if err != nil {
|
||||
return ret, nil
|
||||
}
|
||||
winmetric := cloudprovider.MetricValues{}
|
||||
winmetric.MetricType = cloudprovider.VM_METRIC_TYPE_DISK_USAGE
|
||||
winmetric.Values = []cloudprovider.MetricValue{}
|
||||
for i := range workspaces {
|
||||
data, err := self.GetInstanceDiskUsage(workspaces[i].SLoganalyticsWorkspaceProperties.CustomerId, opts.ResourceId, opts.StartTime, opts.EndTime)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for i := range data {
|
||||
for j := range data[i].Rows {
|
||||
if len(data[i].Rows[j]) == 5 {
|
||||
date, device, free := data[i].Rows[j][0], data[i].Rows[j][1], data[i].Rows[j][2]
|
||||
dataTime, err := timeutils.ParseTimeStr(date)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if dataTime.Second() > 15 {
|
||||
continue
|
||||
}
|
||||
freeSize, err := strconv.ParseFloat(free, 64)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
winmetric.Values = append(winmetric.Values, cloudprovider.MetricValue{
|
||||
Timestamp: dataTime,
|
||||
Value: 100 - freeSize,
|
||||
Tags: map[string]string{cloudprovider.METRIC_TAG_DEVICE: device},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(winmetric.Values) > 0 {
|
||||
ret = append(ret, winmetric)
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
// 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 shell
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/multicloud/azure"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type LoganalyticsWorkspaceListOptions struct {
|
||||
}
|
||||
shellutils.R(&LoganalyticsWorkspaceListOptions{}, "loganalytics-workspace-list", "List loganalytics workspaces", func(cli *azure.SRegion, args *LoganalyticsWorkspaceListOptions) error {
|
||||
workspaces, err := cli.GetClient().GetLoganalyticsWorkspaces()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(workspaces, len(workspaces), 0, 0, []string{})
|
||||
return nil
|
||||
})
|
||||
|
||||
type DiskUsageListOptions struct {
|
||||
WORKSPACE_ID string
|
||||
NAME string
|
||||
START time.Time
|
||||
END time.Time
|
||||
}
|
||||
|
||||
shellutils.R(&DiskUsageListOptions{}, "disk-usage-list", "List disk usage", func(cli *azure.SRegion, args *DiskUsageListOptions) error {
|
||||
usage, err := cli.GetClient().GetInstanceDiskUsage(args.WORKSPACE_ID, args.NAME, args.START, args.END)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(usage, len(usage), 0, 0, []string{})
|
||||
return nil
|
||||
})
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user