diff --git a/info/v1/machine.go b/info/v1/machine.go index ddc7452b..ba26d256 100644 --- a/info/v1/machine.go +++ b/info/v1/machine.go @@ -112,6 +112,22 @@ type NetInfo struct { Mtu int64 `json:"mtu"` } +type CloudProvider string + +const ( + GCE CloudProvider = "GCE" + AWS = "AWS" + BAREMETAL = "BAREMETAL" + UNKNOWN_PROVIDER = "UNKNOWN" +) + +type InstanceType string + +const ( + NO_INSTANCE InstanceType = "NONE" + UNKNOWN_INSTANCE = "UNKNOWN" +) + type MachineInfo struct { // The number of cores in this machine. NumCores int `json:"num_cores"` @@ -143,6 +159,12 @@ type MachineInfo struct { // Machine Topology // Describes cpu/memory layout and hierarchy. Topology []Node `json:"topology"` + + // Cloud provider the machine belongs to. + CloudProvider CloudProvider `json:"cloud_provider"` + + // Type of cloud instance (e.g. GCE standard) the machine is. + InstanceType InstanceType `json:"instance_type"` } type VersionInfo struct { diff --git a/info/v2/machine.go b/info/v2/machine.go index 21929793..4aef3d83 100644 --- a/info/v2/machine.go +++ b/info/v2/machine.go @@ -59,6 +59,12 @@ type Attributes struct { // Machine Topology // Describes cpu/memory layout and hierarchy. Topology []v1.Node `json:"topology"` + + // Cloud provider the machine belongs to + CloudProvider v1.CloudProvider `json:"cloud_provider"` + + // Type of cloud instance (e.g. GCE standard) the machine is. + InstanceType v1.InstanceType `json:"instance_type"` } func GetAttributes(mi *v1.MachineInfo, vi *v1.VersionInfo) Attributes { @@ -76,5 +82,7 @@ func GetAttributes(mi *v1.MachineInfo, vi *v1.VersionInfo) Attributes { DiskMap: mi.DiskMap, NetworkDevices: mi.NetworkDevices, Topology: mi.Topology, + CloudProvider: mi.CloudProvider, + InstanceType: mi.InstanceType, } } diff --git a/manager/machine.go b/manager/machine.go index cbc2f186..7a25341f 100644 --- a/manager/machine.go +++ b/manager/machine.go @@ -30,6 +30,7 @@ import ( "github.com/google/cadvisor/fs" info "github.com/google/cadvisor/info/v1" "github.com/google/cadvisor/utils" + "github.com/google/cadvisor/utils/cloudinfo" "github.com/google/cadvisor/utils/sysfs" "github.com/google/cadvisor/utils/sysinfo" version "github.com/google/cadvisor/version" @@ -273,6 +274,10 @@ func getMachineInfo(sysFs sysfs.SysFs, fsInfo fs.FsInfo) (*info.MachineInfo, err glog.Errorf("Failed to get system UUID: %v", err) } + realCloudInfo := cloudinfo.NewRealCloudInfo() + cloudProvider := realCloudInfo.GetCloudProvider() + instanceType := realCloudInfo.GetInstanceType() + machineInfo := &info.MachineInfo{ NumCores: numCores, CpuFrequency: clockSpeed, @@ -283,6 +288,8 @@ func getMachineInfo(sysFs sysfs.SysFs, fsInfo fs.FsInfo) (*info.MachineInfo, err MachineID: getInfoFromFiles(*machineIdFilePath), SystemUUID: systemUUID, BootID: getInfoFromFiles(*bootIdFilePath), + CloudProvider: cloudProvider, + InstanceType: instanceType, } for _, fs := range filesystems { diff --git a/utils/cloudinfo/cloudinfo.go b/utils/cloudinfo/cloudinfo.go new file mode 100644 index 00000000..4ca12f82 --- /dev/null +++ b/utils/cloudinfo/cloudinfo.go @@ -0,0 +1,87 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// 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. + +// Get information about the cloud provider (if any) cAdvisor is running on. + +package cloudinfo + +import ( + info "github.com/google/cadvisor/info/v1" +) + +type CloudInfo interface { + GetCloudProvider() info.CloudProvider + GetInstanceType() info.InstanceType +} + +type realCloudInfo struct { + cloudProvider info.CloudProvider + instanceType info.InstanceType +} + +func NewRealCloudInfo() CloudInfo { + cloudProvider := detectCloudProvider() + instanceType := detectInstanceType(cloudProvider) + return &realCloudInfo{ + cloudProvider: cloudProvider, + instanceType: instanceType, + } +} + +func (self *realCloudInfo) GetCloudProvider() info.CloudProvider { + return self.cloudProvider +} + +func (self *realCloudInfo) GetInstanceType() info.InstanceType { + return self.instanceType +} + +func detectCloudProvider() info.CloudProvider { + switch { + case inGCE(): + return info.GCE + case inAWS(): + return info.AWS + case inBareMetal(): + return info.BAREMETAL + } + return info.UNKNOWN_PROVIDER +} + +func detectInstanceType(cloudProvider info.CloudProvider) info.InstanceType { + switch cloudProvider { + case info.GCE: + return getGceInstanceType() + case info.AWS: + return getAwsInstanceType() + case info.BAREMETAL: + return info.NO_INSTANCE + } + return info.UNKNOWN_INSTANCE +} + +//TODO: Implement method. +func inAWS() bool { + return false +} + +//TODO: Implement method. +func getAwsInstanceType() info.InstanceType { + return info.UNKNOWN_INSTANCE +} + +//TODO: Implement method. +func inBareMetal() bool { + return false +} diff --git a/utils/cloudinfo/gce.go b/utils/cloudinfo/gce.go new file mode 100644 index 00000000..9f95fd08 --- /dev/null +++ b/utils/cloudinfo/gce.go @@ -0,0 +1,52 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// 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 cloudinfo + +import ( + "io" + "net/http" + "strings" + + info "github.com/google/cadvisor/info/v1" +) + +func inGCE() bool { + _, err := http.Get("http://metadata.google.internal/computeMetadata/v1/instance/machine-type") + return err == nil +} + +func getGceInstanceType() info.InstanceType { + // Query the metadata server. + req, err := http.NewRequest("GET", "http://metadata.google.internal/computeMetadata/v1/instance/machine-type", nil) + if err != nil { + return info.UNKNOWN_INSTANCE + } + req.Header.Set("Metadata-Flavor", "Google") + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + return info.UNKNOWN_INSTANCE + } + body := make([]byte, 1000) + numRead, err := resp.Body.Read(body) + if err != io.EOF { + return info.UNKNOWN_INSTANCE + } + + // Extract the instance name from the response. + responseString := string(body[:numRead]) + responseParts := strings.Split(responseString, "/") + return info.InstanceType(responseParts[len(responseParts)-1]) +}