diff --git a/info/v1/machine.go b/info/v1/machine.go index f26291c1..242d1b52 100644 --- a/info/v1/machine.go +++ b/info/v1/machine.go @@ -117,6 +117,7 @@ type CloudProvider string const ( GCE CloudProvider = "GCE" AWS = "AWS" + Azure = "Azure" Baremetal = "Baremetal" UnkownProvider = "Unknown" ) @@ -128,6 +129,12 @@ const ( UnknownInstance = "Unknown" ) +type InstanceID string + +const ( + UnNamedInstance InstanceID = "None" +) + type MachineInfo struct { // The number of cores in this machine. NumCores int `json:"num_cores"` @@ -165,6 +172,9 @@ type MachineInfo struct { // Type of cloud instance (e.g. GCE standard) the machine is. InstanceType InstanceType `json:"instance_type"` + + // ID of cloud instance (e.g. instance-1) given to it by the cloud provider. + InstanceID InstanceID `json:"instance_id"` } type VersionInfo struct { diff --git a/manager/machine.go b/manager/machine.go index 19b10b3a..e323fd24 100644 --- a/manager/machine.go +++ b/manager/machine.go @@ -96,6 +96,7 @@ func getMachineInfo(sysFs sysfs.SysFs, fsInfo fs.FsInfo, inHostNamespace bool) ( realCloudInfo := cloudinfo.NewRealCloudInfo() cloudProvider := realCloudInfo.GetCloudProvider() instanceType := realCloudInfo.GetInstanceType() + instanceID := realCloudInfo.GetInstanceID() machineInfo := &info.MachineInfo{ NumCores: numCores, @@ -109,6 +110,7 @@ func getMachineInfo(sysFs sysfs.SysFs, fsInfo fs.FsInfo, inHostNamespace bool) ( BootID: getInfoFromFiles(filepath.Join(rootFs, *bootIdFilePath)), CloudProvider: cloudProvider, InstanceType: instanceType, + InstanceID: instanceID, } for _, fs := range filesystems { diff --git a/utils/cloudinfo/aws.go b/utils/cloudinfo/aws.go new file mode 100644 index 00000000..c51e446c --- /dev/null +++ b/utils/cloudinfo/aws.go @@ -0,0 +1,45 @@ +// 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 ( + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/ec2metadata" + "github.com/aws/aws-sdk-go/aws/session" + + info "github.com/google/cadvisor/info/v1" +) + +func onAWS() bool { + client := ec2metadata.New(session.New(&aws.Config{})) + return client.Available() +} + +func getAwsMetadata(name string) string { + client := ec2metadata.New(session.New(&aws.Config{})) + data, err := client.GetMetadata(name) + if err != nil { + return info.UnknownInstance + } + return data +} + +func getAwsInstanceType() info.InstanceType { + return info.InstanceType(getAwsMetadata("instance-type")) +} + +func getAwsInstanceID() info.InstanceID { + return info.InstanceID(getAwsMetadata("instance-id")) +} diff --git a/utils/cloudinfo/azure.go b/utils/cloudinfo/azure.go new file mode 100644 index 00000000..7ac6d555 --- /dev/null +++ b/utils/cloudinfo/azure.go @@ -0,0 +1,48 @@ +// 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 ( + info "github.com/google/cadvisor/info/v1" + "io/ioutil" + "strings" +) + +const ( + SysVendorFileName = "/sys/class/dmi/id/sys_vendor" + BiosUUIDFileName = "/sys/class/dmi/id/product_uuid" + MicrosoftCorporation = "Microsoft Corporation" +) + +func onAzure() bool { + data, err := ioutil.ReadFile(SysVendorFileName) + if err != nil { + return false + } + return strings.Contains(string(data), MicrosoftCorporation) +} + +//TODO: Implement method. +func getAzureInstanceType() info.InstanceType { + return info.UnknownInstance +} + +func getAzureInstanceID() info.InstanceID { + data, err := ioutil.ReadFile(BiosUUIDFileName) + if err != nil { + return info.UnNamedInstance + } + return info.InstanceID(strings.TrimSuffix(string(data), "\n")) +} diff --git a/utils/cloudinfo/cloudinfo.go b/utils/cloudinfo/cloudinfo.go index e073fae6..78c5fc3e 100644 --- a/utils/cloudinfo/cloudinfo.go +++ b/utils/cloudinfo/cloudinfo.go @@ -23,19 +23,23 @@ import ( type CloudInfo interface { GetCloudProvider() info.CloudProvider GetInstanceType() info.InstanceType + GetInstanceID() info.InstanceID } type realCloudInfo struct { cloudProvider info.CloudProvider instanceType info.InstanceType + instanceID info.InstanceID } func NewRealCloudInfo() CloudInfo { cloudProvider := detectCloudProvider() instanceType := detectInstanceType(cloudProvider) + instanceID := detectInstanceID(cloudProvider) return &realCloudInfo{ cloudProvider: cloudProvider, instanceType: instanceType, + instanceID: instanceID, } } @@ -47,12 +51,18 @@ func (self *realCloudInfo) GetInstanceType() info.InstanceType { return self.instanceType } +func (self *realCloudInfo) GetInstanceID() info.InstanceID { + return self.instanceID +} + func detectCloudProvider() info.CloudProvider { switch { case onGCE(): return info.GCE case onAWS(): return info.AWS + case onAzure(): + return info.Azure case onBaremetal(): return info.Baremetal } @@ -65,20 +75,26 @@ func detectInstanceType(cloudProvider info.CloudProvider) info.InstanceType { return getGceInstanceType() case info.AWS: return getAwsInstanceType() + case info.Azure: + return getAzureInstanceType() case info.Baremetal: return info.NoInstance } return info.UnknownInstance } -//TODO: Implement method. -func onAWS() bool { - return false -} - -//TODO: Implement method. -func getAwsInstanceType() info.InstanceType { - return info.UnknownInstance +func detectInstanceID(cloudProvider info.CloudProvider) info.InstanceID { + switch cloudProvider { + case info.GCE: + return getGceInstanceID() + case info.AWS: + return getAwsInstanceID() + case info.Azure: + return getAzureInstanceID() + case info.Baremetal: + return info.UnNamedInstance + } + return info.UnNamedInstance } //TODO: Implement method. diff --git a/utils/cloudinfo/gce.go b/utils/cloudinfo/gce.go index a3b5907d..0d044d62 100644 --- a/utils/cloudinfo/gce.go +++ b/utils/cloudinfo/gce.go @@ -35,3 +35,11 @@ func getGceInstanceType() info.InstanceType { responseParts := strings.Split(machineType, "/") // Extract the instance name from the machine type. return info.InstanceType(responseParts[len(responseParts)-1]) } + +func getGceInstanceID() info.InstanceID { + instanceID, err := metadata.Get("instance/id") + if err != nil { + return info.UnknownInstance + } + return info.InstanceID(info.InstanceType(instanceID)) +}