1
0
mirror of https://github.com/Oxalide/vsphere-influxdb-go.git synced 2023-10-10 11:36:51 +00:00

Compare commits

..

No commits in common. "master" and "v0.8.1" have entirely different histories.

8 changed files with 205 additions and 377 deletions

3
.gitignore vendored
View File

@ -11,6 +11,3 @@ vsphere-influxdb
# Configuration file
vsphere-influxdb.json
# Vim swap files
*.swp

View File

@ -17,6 +17,6 @@ before_script:
script:
- git status
after_success:
# - gem install --no-ri --no-rdoc fpm
- gem install --no-ri --no-rdoc fpm
- test -n "$TRAVIS_TAG" && curl -sL https://git.io/goreleaser | bash

View File

@ -1,18 +0,0 @@
FROM golang:1.12-alpine3.10 as builder
WORKDIR /go/src/vsphere-influxdb-go
COPY . .
RUN apk --update add --virtual build-deps git
RUN go get -d -v ./...
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo
FROM alpine:3.10
RUN apk update \
&& apk upgrade \
&& apk add ca-certificates \
&& addgroup -S spock && adduser -S spock -G spock
COPY --from=0 /go/src/vsphere-influxdb-go/vsphere-influxdb-go /vsphere-influxdb-go
USER spock
CMD ["/vsphere-influxdb-go"]

39
Gopkg.lock generated
View File

@ -2,65 +2,32 @@
[[projects]]
digest = "1:56c130d885a4aacae1dd9c7b71cfe39912c7ebc1ff7d2b46083c8812996dc43b"
name = "github.com/davecgh/go-spew"
packages = ["spew"]
pruneopts = ""
revision = "346938d642f2ec3594ed81d874461961cd0faa76"
version = "v1.1.0"
[[projects]]
digest = "1:ec837623c12abf4f44837163ad32274dd0c9dfa29f0d65068c60897bce34bb75"
name = "github.com/influxdata/influxdb"
packages = [
"client/v2",
"models",
"pkg/escape",
]
pruneopts = ""
packages = ["client/v2","models","pkg/escape"]
revision = "a7c3d3c0f7b74f71919047adbc4933460967a576"
version = "v1.3.6"
[[projects]]
digest = "1:c5342f3ddefc1644d1a3ed028e739bfabe5b457978084b9a28d42ed235c8bb4d"
name = "github.com/vmware/govmomi"
packages = [
".",
"property",
"session",
"vim25",
"vim25/debug",
"vim25/methods",
"vim25/mo",
"vim25/progress",
"vim25/soap",
"vim25/types",
"vim25/xml",
]
pruneopts = ""
packages = [".","property","session","vim25","vim25/debug","vim25/methods","vim25/mo","vim25/progress","vim25/soap","vim25/types","vim25/xml"]
revision = "b63044e5f833781eb7b305bc035392480ee06a82"
version = "v0.15.0"
[[projects]]
branch = "master"
digest = "1:70ca15641aa31be55859a7f75ddef3ae384ae18068deab8274668a1a77d1e84a"
name = "golang.org/x/net"
packages = ["context"]
pruneopts = ""
revision = "4b14673ba32bee7f5ac0f990a48f033919fd418b"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
input-imports = [
"github.com/davecgh/go-spew/spew",
"github.com/influxdata/influxdb/client/v2",
"github.com/vmware/govmomi",
"github.com/vmware/govmomi/property",
"github.com/vmware/govmomi/vim25/methods",
"github.com/vmware/govmomi/vim25/mo",
"github.com/vmware/govmomi/vim25/types",
"golang.org/x/net/context",
]
inputs-digest = "0b7718e6a338978c4ea1efca3255565c667967ddd6ff68999a1d1cea5112209e"
solver-name = "gps-cdcl"
solver-version = 1

View File

@ -49,7 +49,7 @@ For InfluxDB:
For vSphere:
* VSPHERE\_HOSTNAME
* VSPHERE\_USERNAME
* VSPHERE\_PASSWORD
* SPHERE\_PASSWORD
Keep in mind, that currently only one vCenter/ESXi can be added via environment variable.
@ -57,7 +57,6 @@ If you set a domain, it will be automaticaly removed from the names of the found
Metrics collected are defined by associating ObjectType groups with Metric groups.
There have been reports of the script not working correctly when the time is incorrect on the vsphere or vcenter. Make sure that the time is valid or activate the NTP service on the machine.
# Run as a service

View File

@ -19,7 +19,7 @@ archive:
files:
- LICENSE.txt
- README.md
nfpm:
fpm:
# Your app's vendor.
# Default is empty.
vendor: Oxalide

View File

@ -1,17 +1,17 @@
/* Copyright 2016-2018 Adrian Todorov, Oxalide ato@oxalide.com
Original project author: https://github.com/cblomart
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
/* Copyright 2016 Adrian Todorov, Oxalide ato@oxalide.com
Original project author: https://github.com/cblomart
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package main
@ -47,12 +47,11 @@ const (
// Configuration is used to store config data
type Configuration struct {
VCenters []*VCenter
Metrics []Metric
Interval int
Domain string
RemoveHostDomainName bool
InfluxDB InfluxDB
VCenters []*VCenter
Metrics []Metric
Interval int
Domain string
InfluxDB InfluxDB
}
// InfluxDB is used for InfluxDB connections
@ -61,7 +60,6 @@ type InfluxDB struct {
Username string
Password string
Database string
Prefix string
}
// VCenter for VMware vCenter connections
@ -70,7 +68,6 @@ type VCenter struct {
Username string
Password string
MetricGroups []*MetricGroup
client *govmomi.Client
}
// MetricDef metric definition
@ -100,76 +97,52 @@ type EntityQuery struct {
Metrics []int32
}
var getversion, debug, test bool
var debug bool
var stdlog, errlog *log.Logger
var version = "master"
// Connect to the actual vCenter connection used to query data
func (vcenter *VCenter) Connect() error {
func (vcenter *VCenter) Connect() (*govmomi.Client, error) {
// Prepare vCenter Connections
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
stdlog.Println("Connecting to vcenter:", vcenter.Hostname)
u, err := url.Parse("https://" + vcenter.Hostname + "/sdk")
u.User = url.UserPassword(vcenter.Username, vcenter.Password)
stdlog.Println("connecting to vcenter: " + vcenter.Hostname)
u, err := url.Parse("https://" + vcenter.Username + ":" + vcenter.Password + "@" + vcenter.Hostname + "/sdk")
if err != nil {
errlog.Println("Could not parse vcenter url:", vcenter.Hostname)
errlog.Println("Error:", err)
return err
errlog.Println("Could not parse vcenter url: ", vcenter.Hostname)
errlog.Println("Error: ", err)
return nil, err
}
client, err := govmomi.NewClient(ctx, u, true)
if err != nil {
errlog.Println("Could not connect to vcenter:", vcenter.Hostname)
errlog.Println("Error:", err)
return err
errlog.Println("Could not connect to vcenter: ", vcenter.Hostname)
errlog.Println("Error: ", err)
return nil, err
}
vcenter.client = client
return nil
}
// Disconnect from the vCenter
func (vcenter *VCenter) Disconnect() error {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
if vcenter.client != nil {
if err := vcenter.client.Logout(ctx); err != nil {
errlog.Println("Could not disconnect properly from vcenter:", vcenter.Hostname, err)
return err
}
}
return nil
return client, nil
}
// Init the VCenter connection
func (vcenter *VCenter) Init(config Configuration) error {
func (vcenter *VCenter) Init(config Configuration) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client := vcenter.client
// Print version
if debug {
aboutInfo := client.Client.ServiceContent.About
stdlog.Println("Version:", aboutInfo.FullName)
client, err := vcenter.Connect()
if err != nil {
errlog.Println("Could not connect to vcenter: ", vcenter.Hostname)
errlog.Println("Error: ", err)
return
}
defer client.Logout(ctx)
var perfmanager mo.PerformanceManager
err := client.RetrieveOne(ctx, *client.ServiceContent.PerfManager, nil, &perfmanager)
err = client.RetrieveOne(ctx, *client.ServiceContent.PerfManager, nil, &perfmanager)
if err != nil {
errlog.Println("Could not get performance manager")
errlog.Println("Error:", err)
return err
}
// Print PerformanceManager interval collection level
if debug {
stdlog.Println("PerformanceManager interval collection level")
spew.Dump(perfmanager.HistoricalInterval)
errlog.Println("Error: ", err)
return
}
for _, perf := range perfmanager.PerfCounter {
@ -198,25 +171,30 @@ func (vcenter *VCenter) Init(config Configuration) error {
}
}
}
return nil
}
// Query a vcenter
func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.Client, nowTime time.Time) {
stdlog.Println("Setting up query inventory of vcenter:", vcenter.Hostname)
func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.Client) {
stdlog.Println("Setting up query inventory of vcenter: ", vcenter.Hostname)
// Create the contect
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// Get the client
client := vcenter.client
client, err := vcenter.Connect()
if err != nil {
errlog.Println("Could not connect to vcenter: ", vcenter.Hostname)
errlog.Println("Error: ", err)
return
}
defer client.Logout(ctx)
// Create the view manager
var viewManager mo.ViewManager
err := client.RetrieveOne(ctx, *client.ServiceContent.ViewManager, nil, &viewManager)
err = client.RetrieveOne(ctx, *client.ServiceContent.ViewManager, nil, &viewManager)
if err != nil {
errlog.Println("Could not get view manager from vcenter:", vcenter.Hostname)
errlog.Println("Could not get view manager from vcenter: " + vcenter.Hostname)
errlog.Println("Error: ", err)
return
}
@ -225,16 +203,16 @@ func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.
var rootFolder mo.Folder
err = client.RetrieveOne(ctx, client.ServiceContent.RootFolder, nil, &rootFolder)
if err != nil {
errlog.Println("Could not get root folder from vcenter:", vcenter.Hostname)
errlog.Println("Error:", err)
errlog.Println("Could not get root folder from vcenter: " + vcenter.Hostname)
errlog.Println("Error: ", err)
return
}
datacenters := []types.ManagedObjectReference{}
for _, child := range rootFolder.ChildEntity {
//if child.Type == "Datacenter" {
datacenters = append(datacenters, child)
//}
if child.Type == "Datacenter" {
datacenters = append(datacenters, child)
}
}
// Get intresting object types from specified queries
objectTypes := []string{}
@ -252,16 +230,16 @@ func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.
req := types.CreateContainerView{This: viewManager.Reference(), Container: datacenter, Type: objectTypes, Recursive: true}
res, err := methods.CreateContainerView(ctx, client.RoundTripper, &req)
if err != nil {
errlog.Println("Could not create container view from vcenter:", vcenter.Hostname)
errlog.Println("Error:", err)
errlog.Println("Could not create container view from vcenter: " + vcenter.Hostname)
errlog.Println("Error: ", err)
continue
}
// Retrieve the created ContentView
var containerView mo.ContainerView
err = client.RetrieveOne(ctx, res.Returnval, nil, &containerView)
if err != nil {
errlog.Println("Could not get container view from vcenter:", vcenter.Hostname)
errlog.Println("Error:", err)
errlog.Println("Could not get container view from vcenter: " + vcenter.Hostname)
errlog.Println("Error: ", err)
continue
}
// Add found object to object list
@ -277,7 +255,7 @@ func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.
newMors := []types.ManagedObjectReference{}
if debug {
if debug == true {
spew.Dump(mors)
}
// Assign each MORS type to a specific array
@ -301,26 +279,20 @@ func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.
mors = newMors
pc := property.DefaultCollector(client.Client)
// govmomi segfaults when the list objects to retrieve is empty, so check everything
// Retrieve properties for all vms
var vmmo []mo.VirtualMachine
if len(vmRefs) > 0 {
err = pc.Retrieve(ctx, vmRefs, []string{"summary"}, &vmmo)
if err != nil {
fmt.Println(err)
return
}
err = pc.Retrieve(ctx, vmRefs, []string{"summary"}, &vmmo)
if err != nil {
fmt.Println(err)
return
}
// Retrieve properties for hosts
var hsmo []mo.HostSystem
if len(hostRefs) > 0 {
err = pc.Retrieve(ctx, hostRefs, []string{"parent", "summary"}, &hsmo)
if err != nil {
fmt.Println(err)
return
}
err = pc.Retrieve(ctx, hostRefs, []string{"parent", "summary"}, &hsmo)
if err != nil {
fmt.Println(err)
return
}
//Retrieve properties for Cluster(s)
@ -345,12 +317,10 @@ func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.
// Retrieve summary property for all datastores
var dss []mo.Datastore
if len(datastoreRefs) > 0 {
err = pc.Retrieve(ctx, datastoreRefs, []string{"summary"}, &dss)
if err != nil {
log.Fatal(err)
return
}
err = pc.Retrieve(ctx, datastoreRefs, []string{"summary"}, &dss)
if err != nil {
log.Fatal(err)
return
}
// Initialize the map that will hold the VM MOR to ResourcePool reference
@ -359,8 +329,8 @@ func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.
var respool []mo.ResourcePool
// Retrieve properties for ResourcePools
if len(respoolRefs) > 0 {
if debug {
stdlog.Println("Going inside ResourcePools")
if debug == true {
stdlog.Println("going inside ResourcePools")
}
err = pc.Retrieve(ctx, respoolRefs, []string{"name", "config", "vm"}, &respool)
if err != nil {
@ -368,14 +338,14 @@ func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.
return
}
for _, pool := range respool {
if debug {
stdlog.Println(pool.Config.MemoryAllocation.GetResourceAllocationInfo().Limit)
stdlog.Println(pool.Config.CpuAllocation.GetResourceAllocationInfo().Limit)
if debug == true {
stdlog.Println("---resourcepool name - you should see every resourcepool here (+VMs inside)----")
stdlog.Println(pool.Name)
stdlog.Println(pool.Config.MemoryAllocation.GetResourceAllocationInfo().Limit)
stdlog.Println(pool.Config.CpuAllocation.GetResourceAllocationInfo().Limit)
}
for _, vm := range pool.Vm {
if debug {
if debug == true {
stdlog.Println("--VM ID - you should see every VM ID here--")
stdlog.Println(vm)
}
@ -387,16 +357,13 @@ func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.
// Initialize the map that will hold the VM MOR to cluster reference
vmToCluster := make(map[types.ManagedObjectReference]string)
// Initialize the map that will hold the host MOR to cluster reference
// Initialize the map that will hold the VM MOR to cluster reference
hostToCluster := make(map[types.ManagedObjectReference]string)
// Initialize the map that will hold the vDisk UUID per VM MOR to datastore reference
// vDiskToDatastore := make(map[types.ManagedObjectReference]map[string]string)
// Retrieve properties for clusters, if any
if len(clusterRefs) > 0 {
if debug {
stdlog.Println("Going inside clusters")
if debug == true {
stdlog.Println("going inside clusters")
}
// Step 1 : Get ObjectContents and Host info for VM
@ -411,10 +378,6 @@ func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.
// If we find it, return it, otherwise we return null.
for _, vm := range vmmo {
// check if VM is a clone in progress and skip it
if vm.Summary.Runtime.Host == nil {
continue
}
vmhost := vm.Summary.Runtime.Host
for _, cl := range clmo {
@ -437,34 +400,24 @@ func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.
respoolSummary[pools.Self]["name"] = pools.Summary.GetResourcePoolSummary().Name
}
// Initialize the maps that will hold the extra tags and metrics for VMs
// Retrieve properties for the hosts
hostSummary := make(map[types.ManagedObjectReference]map[string]string)
hostExtraMetrics := make(map[types.ManagedObjectReference]map[string]int64)
for _, host := range hsmo {
// Extra tags per host
hostSummary[host.Self] = make(map[string]string)
hostSummary[host.Self]["name"] = host.Summary.Config.Name
// Remove Domain Name from Host
if config.RemoveHostDomainName {
hostSummary[host.Self]["name"] = strings.Replace(host.Summary.Config.Name, config.Domain, "", -1)
}
hostSummary[host.Self]["cluster"] = hostToCluster[host.Self]
// Extra metrics per host
hostExtraMetrics[host.Self] = make(map[string]int64)
hostExtraMetrics[host.Self]["uptime"] = int64(host.Summary.QuickStats.Uptime)
hostExtraMetrics[host.Self]["cpu_corecount_total"] = int64(host.Summary.Hardware.NumCpuThreads)
}
// Initialize the maps that will hold the extra tags and metrics for VMs
// Initialize the map that will hold all extra tags
vmSummary := make(map[types.ManagedObjectReference]map[string]string)
vmExtraMetrics := make(map[types.ManagedObjectReference]map[string]int64)
// Assign extra details per VM in vmSummary
for _, vm := range vmmo {
// extra tags per VM
vmSummary[vm.Self] = make(map[string]string)
// Ugly way to extract datastore value
re, err := regexp.Compile(`\[(.*?)\]`)
@ -472,34 +425,15 @@ func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.
fmt.Println(err)
}
vmSummary[vm.Self]["datastore"] = strings.Replace(strings.Replace(re.FindString(fmt.Sprintln(vm.Summary.Config)), "[", "", -1), "]", "", -1)
// List all devices to get vDisks
// for _, device := range vm.Config.Hardware.Device {
// // Hacky way to check if it's a vDisk and if it's datastore is different than the main one for VM
// if device.Backing.FileName != nil && device.Backing.Datastore.Name != vmSummary[vm.Self]["datastore"] {
// if vDiskToDatastore[vm.Self] == nil {
// vDiskToDatastore[vm.Self] = make(map[string]string)
// }
// vDiskToDatastore[vm.Self][device.diskObjectId] = device.Backing.Datastore.Name
// }
// }
if vmToCluster[vm.Self] != "" {
vmSummary[vm.Self]["cluster"] = vmToCluster[vm.Self]
}
if vmToPool[vm.Self] != "" {
vmSummary[vm.Self]["respool"] = vmToPool[vm.Self]
}
if vm.Summary.Runtime.Host != nil {
vmSummary[vm.Self]["esx"] = hostSummary[*vm.Summary.Runtime.Host]["name"]
}
// Extra metrics per VM
vmExtraMetrics[vm.Self] = make(map[string]int64)
vmExtraMetrics[vm.Self]["uptime"] = int64(vm.Summary.QuickStats.UptimeSeconds)
vmSummary[vm.Self]["esx"] = hostSummary[*vm.Summary.Runtime.Host]["name"]
}
// fmt.Println("vDiskDatastore:")
// spew.Dump(vDiskToDatastore)
// get object names
objects := []mo.ManagedEntity{}
@ -514,16 +448,16 @@ func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.
propreq := types.RetrieveProperties{SpecSet: []types.PropertyFilterSpec{{ObjectSet: objectSet, PropSet: []types.PropertySpec{*propSpec}}}}
propres, err := client.PropertyCollector().RetrieveProperties(ctx, propreq)
if err != nil {
errlog.Println("Could not retrieve object names from vcenter:", vcenter.Hostname)
errlog.Println("Error:", err)
errlog.Println("Could not retrieve object names from vcenter: " + vcenter.Hostname)
errlog.Println("Error: ", err)
return
}
//load retrieved properties
err = mo.LoadRetrievePropertiesResponse(propres, &objects)
if err != nil {
errlog.Println("Could not retrieve object names from vcenter:", vcenter.Hostname)
errlog.Println("Error:", err)
errlog.Println("Could not retrieve object names from vcenter: " + vcenter.Hostname)
errlog.Println("Error: ", err)
return
}
@ -570,8 +504,8 @@ func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.
perfreq := types.QueryPerf{This: *client.ServiceContent.PerfManager, QuerySpec: queries}
perfres, err := methods.QueryPerf(ctx, client.RoundTripper, &perfreq)
if err != nil {
errlog.Println("Could not request perfs from vcenter:", vcenter.Hostname)
errlog.Println("Error:", err)
errlog.Println("Could not request perfs from vcenter: " + vcenter.Hostname)
errlog.Println("Error: ", err)
return
}
@ -673,21 +607,15 @@ func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.
specialTags[measurementName][tags["name"]][instanceName]["instance"] = instanceName
}
}
// Create the fields for the hostExtraMetrics
if metrics, ok := hostExtraMetrics[pem.Entity]; ok {
for key, value := range metrics {
fields[key] = value
}
}
// Create the fields for the vmExtraMetrics
if metrics, ok := vmExtraMetrics[pem.Entity]; ok {
for key, value := range metrics {
fields[key] = value
}
}
//create InfluxDB points
pt, err := influxclient.NewPoint(config.InfluxDB.Prefix+entityName, tags, fields, nowTime)
pt, err := influxclient.NewPoint(entityName, tags, fields, nowTime)
if err != nil {
errlog.Println(err)
continue
@ -697,7 +625,7 @@ func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.
for measurement, v := range specialFields {
for name, metric := range v {
for instance, value := range metric {
pt2, err := influxclient.NewPoint(config.InfluxDB.Prefix+measurement, specialTags[measurement][name][instance], value, time.Now())
pt2, err := influxclient.NewPoint(measurement, specialTags[measurement][name][instance], value, time.Now())
if err != nil {
errlog.Println(err)
continue
@ -707,13 +635,20 @@ func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.
}
}
// var respool []mo.ResourcePool
// err = pc.Retrieve(ctx, respoolRefs, []string{"name", "config", "vm"}, &respool)
// if err != nil {
// errlog.Println(err)
// continue
// }
for _, pool := range respool {
respoolFields := map[string]interface{}{
"cpu_limit": pool.Config.CpuAllocation.GetResourceAllocationInfo().Limit,
"memory_limit": pool.Config.MemoryAllocation.GetResourceAllocationInfo().Limit,
}
respoolTags := map[string]string{"pool_name": pool.Name}
pt3, err := influxclient.NewPoint(config.InfluxDB.Prefix+"resourcepool", respoolTags, respoolFields, time.Now())
pt3, err := influxclient.NewPoint("resourcepool", respoolTags, respoolFields, time.Now())
if err != nil {
errlog.Println(err)
continue
@ -725,10 +660,9 @@ func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.
datastoreFields := map[string]interface{}{
"capacity": datastore.Summary.Capacity,
"free_space": datastore.Summary.FreeSpace,
"usage": 1.0 - (float64(datastore.Summary.FreeSpace) / float64(datastore.Summary.Capacity)),
}
datastoreTags := map[string]string{"ds_name": datastore.Summary.Name, "host": vcName}
pt4, err := influxclient.NewPoint(config.InfluxDB.Prefix+"datastore", datastoreTags, datastoreFields, time.Now())
pt4, err := influxclient.NewPoint("datastore", datastoreTags, datastoreFields, time.Now())
if err != nil {
errlog.Println(err)
continue
@ -738,17 +672,14 @@ func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.
}
//InfluxDB send if not in test mode
if test != true {
err = InfluxDBClient.Write(bp)
if err != nil {
errlog.Println(err)
return
}
stdlog.Println("Sent data to Influxdb from:", vcenter.Hostname)
} else {
spew.Dump(bp)
//InfluxDB send
err = InfluxDBClient.Write(bp)
if err != nil {
errlog.Println(err)
return
}
stdlog.Println("sent data to Influxdb")
}
func min(n ...int64) int64 {
@ -766,6 +697,7 @@ func min(n ...int64) int64 {
}
return min
}
func max(n ...int64) int64 {
var max int64 = -1
for _, i := range n {
@ -805,44 +737,20 @@ func average(n ...int64) int64 {
return int64(math.Floor(favg + .5))
}
func worker(id int, config Configuration, influxDBClient influxclient.Client, nowTime time.Time, vcenters <-chan *VCenter, results chan<- bool) {
for vcenter := range vcenters {
if debug {
stdlog.Println("Worker", id, "received vcenter", vcenter.Hostname)
}
if err := vcenter.Connect(); err != nil {
errlog.Println("Could not initialize connection to vcenter", vcenter.Hostname, err)
results <- true
continue
}
if err := vcenter.Init(config); err == nil {
vcenter.Query(config, influxDBClient, nowTime)
}
vcenter.Disconnect()
results <- true
}
func queryVCenter(vcenter VCenter, config Configuration, InfluxDBClient influxclient.Client) {
stdlog.Println("Querying vcenter")
vcenter.Query(config, InfluxDBClient)
}
func main() {
baseName := path.Base(os.Args[0])
flag.BoolVar(&debug, "debug", false, "Debug mode")
var cfgFile = flag.String("config", "/etc/"+path.Base(os.Args[0])+".json", "Config file to use. Default is /etc/"+path.Base(os.Args[0])+".json")
flag.Parse()
stdlog = log.New(os.Stdout, "", log.Ldate|log.Ltime)
errlog = log.New(os.Stderr, "", log.Ldate|log.Ltime)
flag.BoolVar(&debug, "debug", false, "Debug mode")
flag.BoolVar(&test, "test", false, "Test mode, data will be collected from vCenters, but nothing will be written to InfluxDB, only printed to stdout")
flag.BoolVar(&getversion, "version", false, "Get version and exit")
workerCount := flag.Int("workers", 4, "Number of concurrent workers to query vcenters")
cfgFile := flag.String("config", "/etc/"+baseName+".json", "Config file to use")
flag.Parse()
if getversion {
fmt.Println("Version:", version)
os.Exit(0)
}
stdlog.Println("Starting", baseName, "with config file", *cfgFile)
stdlog.Println("Starting :", path.Base(os.Args[0]))
// read the configuration
file, err := os.Open(*cfgFile)
@ -866,6 +774,7 @@ func main() {
config.InfluxDB.Password = os.Getenv("INFLUX_PASSWORD")
config.InfluxDB.Database = os.Getenv("INFLUX_DATABASE")
}
// Support environment variables for VSphere
// Currently ony one server is supported and added to the list of vSphere servers
if vhostname := os.Getenv("VSPHERE_HOSTNAME"); vhostname != "" {
@ -878,48 +787,28 @@ func main() {
}
// Print configuration in debug mode
if debug {
if debug == true {
stdlog.Println("---Configuration - you should see the config here---")
spew.Dump(config)
}
// Initialize InfluxDB and connect to database
for _, vcenter := range config.VCenters {
vcenter.Init(config)
}
InfluxDBClient, err := influxclient.NewHTTPClient(influxclient.HTTPConfig{
Addr: config.InfluxDB.Hostname,
Username: config.InfluxDB.Username,
Password: config.InfluxDB.Password,
})
if err != nil {
errlog.Println("Could not initialize InfluxDB client")
errlog.Fatalln(err)
}
if _, _, err := InfluxDBClient.Ping(0); err != nil {
errlog.Println("Could not connect to InfluxDB")
errlog.Fatalln(err)
}
defer InfluxDBClient.Close()
stdlog.Println("Successfully connected to Influx")
// make the channels, get the time, launch the goroutines
vcenterCount := len(config.VCenters)
vcenters := make(chan *VCenter, vcenterCount)
results := make(chan bool, vcenterCount)
nowTime := time.Now()
for i := 0; i < *workerCount; i++ {
go worker(i, config, InfluxDBClient, nowTime, vcenters, results)
}
for _, vcenter := range config.VCenters {
vcenters <- vcenter
queryVCenter(*vcenter, config, InfluxDBClient)
}
close(vcenters)
for i := 0; i < vcenterCount; i++ {
<-results
}
}

View File

@ -1,82 +1,76 @@
{
"Domain": ".lab",
"RemoveHostDomainName": false,
"Interval": 60,
"VCenters": [
{ "Username": "monitoring", "Password": "monixx", "Hostname": "vcenter-01.dc-01.lab" },
{ "Username": "monitoring", "Password": "monixx", "Hostname": "vcenter-01.dc-02.lab" },
{ "Username": "monitoring", "Password": "monixx", "Hostname": "vcenter-02.dc-02.lab" },
{ "Username": "monitoring", "Password": "monixx", "Hostname": "vcenter-01.home.lab" }
],
"Domain": ".lab",
"Interval": 60,
"VCenters": [
{ "Username": "monitoring", "Password": "monixx", "Hostname": "vcenter-01.dc-01.lab" },
{ "Username": "monitoring", "Password": "monixx", "Hostname": "vcenter-01.dc-02.lab" },
{ "Username": "monitoring", "Password": "monixx", "Hostname": "vcenter-02.dc-02.lab" },
{ "Username": "monitoring", "Password": "monixx", "Hostname": "vcenter-01.home.lab" }
"InfluxDB": {
"Prefix": "vsphere_",
"Hostname": "http://influxdb-01.dc-01.lab:8086",
"Username": "vm",
"Password": "vmware334",
"Database": "vmware_performance"
},
"Metrics": [
{
"ObjectType": [ "VirtualMachine", "HostSystem" ],
"Definition": [
{ "Metric": "cpu.usage.average", "Instances": "*" },
{ "Metric": "cpu.usage.maximum", "Instances": "*" },
{ "Metric": "cpu.usagemhz.average", "Instances": "*" },
{ "Metric": "cpu.usagemhz.maximum", "Instances": "*" },
{ "Metric": "cpu.wait.summation", "Instances": "*" },
{ "Metric": "cpu.system.summation", "Instances": "*" },
{ "Metric": "cpu.ready.summation", "Instances": "*" },
{ "Metric": "mem.usage.average", "Instances": "*" },
{ "Metric": "mem.usage.maximum", "Instances": "*" },
{ "Metric": "mem.consumed.average", "Instances": "*" },
{ "Metric": "mem.consumed.maximum", "Instances": "*" },
{ "Metric": "mem.active.average", "Instances": "*" },
{ "Metric": "mem.active.maximum", "Instances": "*" },
{ "Metric": "mem.vmmemctl.average", "Instances": "*" },
{ "Metric": "mem.vmmemctl.maximum", "Instances": "*" },
{ "Metric": "mem.totalCapacity.average", "Instances": "*" },
{ "Metric": "net.packetsRx.summation", "Instances": "*" },
{ "Metric": "net.packetsTx.summation", "Instances": "*" },
{ "Metric": "net.throughput.usage.average", "Instances": "*" },
{ "Metric": "net.received.average", "Instances": "*" },
{ "Metric": "net.transmitted.average", "Instances": "*" },
{ "Metric": "net.throughput.usage.nfs.average", "Instances": "*" },
{ "Metric": "datastore.numberReadAveraged.average", "Instances": "*" },
{ "Metric": "datastore.numberWriteAveraged.average", "Instances": "*" },
{ "Metric": "datastore.read.average", "Instances": "*" },
{ "Metric": "datastore.write.average", "Instances": "*" },
{ "Metric": "datastore.totalReadLatency.average", "Instances": "*" },
{ "Metric": "datastore.totalWriteLatency.average", "Instances": "*" },
{ "Metric": "mem.capacity.provisioned.average", "Instances": "*"},
{ "Metric": "cpu.corecount.provisioned.average", "Instances": "*" }
]
},
{
"ObjectType": [ "VirtualMachine" ],
"Definition": [
{ "Metric": "datastore.datastoreVMObservedLatency.latest", "Instances": "*" }
]
},
{
"ObjectType": [ "HostSystem" ],
"Definition": [
{ "Metric": "disk.maxTotalLatency.latest", "Instances": "" },
{ "Metric": "disk.numberReadAveraged.average", "Instances": "*" },
{ "Metric": "disk.numberWriteAveraged.average", "Instances": "*" },
{ "Metric": "net.throughput.contention.summation", "Instances": "*" }
]
},
{
"ObjectType": [ "Datastore" ],
"Definition": [
{ "Metric": "disk.capacity.latest", "Instances": "*" },
{ "Metric": "disk.used.latest", "Instances": "*" }
]
}
]
],
"InfluxDB": {
"Hostname": "http://influxdb-01.dc-01.lab:8086",
"Username": "vm",
"Password": "vmware334",
"Database": "vmware_performance"
},
"Metrics": [
{
"ObjectType": [ "VirtualMachine", "HostSystem" ],
"Definition": [
{ "Metric": "cpu.usage.average", "Instances": "*" },
{ "Metric": "cpu.usage.maximum", "Instances": "*" },
{ "Metric": "cpu.usagemhz.average", "Instances": "*" },
{ "Metric": "cpu.usagemhz.maximum", "Instances": "*" },
{ "Metric": "cpu.wait.summation", "Instances": "*" },
{ "Metric": "cpu.system.summation", "Instances": "*" },
{ "Metric": "cpu.ready.summation", "Instances": "*" },
{ "Metric": "mem.usage.average", "Instances": "*" },
{ "Metric": "mem.usage.maximum", "Instances": "*" },
{ "Metric": "mem.consumed.average", "Instances": "*" },
{ "Metric": "mem.consumed.maximum", "Instances": "*" },
{ "Metric": "mem.active.average", "Instances": "*" },
{ "Metric": "mem.active.maximum", "Instances": "*" },
{ "Metric": "mem.vmmemctl.average", "Instances": "*" },
{ "Metric": "mem.vmmemctl.maximum", "Instances": "*" },
{ "Metric": "mem.totalCapacity.average", "Instances": "*" },
{ "Metric": "net.packetsRx.summation", "Instances": "*" },
{ "Metric": "net.packetsTx.summation", "Instances": "*" },
{ "Metric": "net.throughput.usage.average", "Instances": "*" },
{ "Metric": "net.received.average", "Instances": "*" },
{ "Metric": "net.transmitted.average", "Instances": "*" },
{ "Metric": "net.throughput.usage.nfs.average", "Instances": "*" },
{ "Metric": "datastore.numberReadAveraged.average", "Instances": "*" },
{ "Metric": "datastore.numberWriteAveraged.average", "Instances": "*" },
{ "Metric": "datastore.read.average", "Instances": "*" },
{ "Metric": "datastore.write.average", "Instances": "*" },
{ "Metric": "datastore.totalReadLatency.average", "Instances": "*" },
{ "Metric": "datastore.totalWriteLatency.average", "Instances": "*" },
{ "Metric": "mem.capacity.provisioned.average", "Instances": "*"},
{ "Metric": "cpu.corecount.provisioned.average", "Instances": "*" }
]
},
{
"ObjectType": [ "VirtualMachine" ],
"Definition": [
{ "Metric": "datastore.datastoreVMObservedLatency.latest", "Instances": "*" }
]
},
{
"ObjectType": [ "HostSystem" ],
"Definition": [
{ "Metric": "disk.maxTotalLatency.latest", "Instances": "" },
{ "Metric": "disk.numberReadAveraged.average", "Instances": "*" },
{ "Metric": "disk.numberWriteAveraged.average", "Instances": "*" },
{ "Metric": "net.throughput.contention.summation", "Instances": "*" }
]
},
{
"ObjectType": [ "Datastore" ],
"Definition": [
{ "Metric": "disk.capacity.latest", "Instances": "*" },
{ "Metric": "disk.used.latest", "Instances": "*" }
]
}
]
}