mirror of
https://github.com/Oxalide/vsphere-influxdb-go.git
synced 2023-10-10 11:36:51 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72f628354b | ||
|
|
076f633377 | ||
|
|
59e2e1d2df | ||
|
|
a461957082 | ||
|
|
bf09836f04 | ||
|
|
c252b28988 | ||
|
|
d00ca9ee6d | ||
|
|
ba0b81c0ef | ||
|
|
8b519e50c8 | ||
|
|
942b49d61e | ||
|
|
3fe6b1fc22 | ||
|
|
01483a5b97 | ||
|
|
65b5bd801f |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -11,3 +11,6 @@ vsphere-influxdb
|
||||
|
||||
# Configuration file
|
||||
vsphere-influxdb.json
|
||||
|
||||
# Vim swap files
|
||||
*.swp
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/* 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.
|
||||
/* 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
|
||||
@@ -60,6 +60,7 @@ type InfluxDB struct {
|
||||
Username string
|
||||
Password string
|
||||
Database string
|
||||
Prefix string
|
||||
}
|
||||
|
||||
// VCenter for VMware vCenter connections
|
||||
@@ -68,6 +69,7 @@ type VCenter struct {
|
||||
Username string
|
||||
Password string
|
||||
MetricGroups []*MetricGroup
|
||||
client *govmomi.Client
|
||||
}
|
||||
|
||||
// MetricDef metric definition
|
||||
@@ -97,52 +99,64 @@ type EntityQuery struct {
|
||||
Metrics []int32
|
||||
}
|
||||
|
||||
var debug bool
|
||||
var getversion, debug, test bool
|
||||
var stdlog, errlog *log.Logger
|
||||
var version = "master"
|
||||
|
||||
|
||||
// Connect to the actual vCenter connection used to query data
|
||||
func (vcenter *VCenter) Connect() (*govmomi.Client, error) {
|
||||
// Prepare vCenter Connections
|
||||
func (vcenter *VCenter) Connect() error {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
stdlog.Println("connecting to vcenter: " + vcenter.Hostname)
|
||||
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 nil, err
|
||||
errlog.Println("Could not parse vcenter url:", vcenter.Hostname)
|
||||
errlog.Println("Error:", err)
|
||||
return 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 nil, err
|
||||
errlog.Println("Could not connect to vcenter:", vcenter.Hostname)
|
||||
errlog.Println("Error:", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return client, nil
|
||||
vcenter.client = client
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Init the VCenter connection
|
||||
func (vcenter *VCenter) Init(config Configuration) {
|
||||
// Disconnect from the vCenter
|
||||
func (vcenter *VCenter) Disconnect() error {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
client, err := vcenter.Connect()
|
||||
if err != nil {
|
||||
errlog.Println("Could not connect to vcenter: ", vcenter.Hostname)
|
||||
errlog.Println("Error: ", err)
|
||||
return
|
||||
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
|
||||
}
|
||||
}
|
||||
defer client.Logout(ctx)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Init the VCenter connection
|
||||
func (vcenter *VCenter) Init(config Configuration) error {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
client := vcenter.client
|
||||
|
||||
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
|
||||
errlog.Println("Error:", err)
|
||||
return err
|
||||
}
|
||||
|
||||
for _, perf := range perfmanager.PerfCounter {
|
||||
@@ -171,30 +185,25 @@ func (vcenter *VCenter) Init(config Configuration) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Query a vcenter
|
||||
func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.Client) {
|
||||
stdlog.Println("Setting up query inventory of vcenter: ", vcenter.Hostname)
|
||||
func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.Client, nowTime time.Time) {
|
||||
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, err := vcenter.Connect()
|
||||
if err != nil {
|
||||
errlog.Println("Could not connect to vcenter: ", vcenter.Hostname)
|
||||
errlog.Println("Error: ", err)
|
||||
return
|
||||
}
|
||||
defer client.Logout(ctx)
|
||||
client := vcenter.client
|
||||
|
||||
// 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
|
||||
}
|
||||
@@ -203,16 +212,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{}
|
||||
@@ -230,16 +239,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
|
||||
@@ -255,7 +264,7 @@ func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.
|
||||
|
||||
newMors := []types.ManagedObjectReference{}
|
||||
|
||||
if debug == true {
|
||||
if debug {
|
||||
spew.Dump(mors)
|
||||
}
|
||||
// Assign each MORS type to a specific array
|
||||
@@ -279,20 +288,26 @@ 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
|
||||
err = pc.Retrieve(ctx, vmRefs, []string{"summary"}, &vmmo)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
if len(vmRefs) > 0 {
|
||||
err = pc.Retrieve(ctx, vmRefs, []string{"summary"}, &vmmo)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve properties for hosts
|
||||
var hsmo []mo.HostSystem
|
||||
err = pc.Retrieve(ctx, hostRefs, []string{"parent", "summary"}, &hsmo)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
if len(hostRefs) > 0 {
|
||||
err = pc.Retrieve(ctx, hostRefs, []string{"parent", "summary"}, &hsmo)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
//Retrieve properties for Cluster(s)
|
||||
@@ -317,10 +332,12 @@ func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.
|
||||
|
||||
// Retrieve summary property for all datastores
|
||||
var dss []mo.Datastore
|
||||
err = pc.Retrieve(ctx, datastoreRefs, []string{"summary"}, &dss)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return
|
||||
if len(datastoreRefs) > 0 {
|
||||
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
|
||||
@@ -329,8 +346,8 @@ func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.
|
||||
var respool []mo.ResourcePool
|
||||
// Retrieve properties for ResourcePools
|
||||
if len(respoolRefs) > 0 {
|
||||
if debug == true {
|
||||
stdlog.Println("going inside ResourcePools")
|
||||
if debug {
|
||||
stdlog.Println("Going inside ResourcePools")
|
||||
}
|
||||
err = pc.Retrieve(ctx, respoolRefs, []string{"name", "config", "vm"}, &respool)
|
||||
if err != nil {
|
||||
@@ -338,14 +355,14 @@ func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.
|
||||
return
|
||||
}
|
||||
for _, pool := range respool {
|
||||
stdlog.Println(pool.Config.MemoryAllocation.GetResourceAllocationInfo().Limit)
|
||||
stdlog.Println(pool.Config.CpuAllocation.GetResourceAllocationInfo().Limit)
|
||||
if debug == true {
|
||||
if debug {
|
||||
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 == true {
|
||||
if debug {
|
||||
stdlog.Println("--VM ID - you should see every VM ID here--")
|
||||
stdlog.Println(vm)
|
||||
}
|
||||
@@ -357,13 +374,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 VM MOR to cluster reference
|
||||
// Initialize the map that will hold the host MOR to cluster reference
|
||||
hostToCluster := make(map[types.ManagedObjectReference]string)
|
||||
|
||||
// Retrieve properties for clusters, if any
|
||||
if len(clusterRefs) > 0 {
|
||||
if debug == true {
|
||||
stdlog.Println("going inside clusters")
|
||||
if debug {
|
||||
stdlog.Println("Going inside clusters")
|
||||
}
|
||||
|
||||
// Step 1 : Get ObjectContents and Host info for VM
|
||||
@@ -378,6 +395,10 @@ 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 {
|
||||
@@ -400,24 +421,30 @@ func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.
|
||||
respoolSummary[pools.Self]["name"] = pools.Summary.GetResourcePoolSummary().Name
|
||||
}
|
||||
|
||||
// Retrieve properties for the hosts
|
||||
// Initialize the maps that will hold the extra tags and metrics for VMs
|
||||
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
|
||||
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 map that will hold all extra tags
|
||||
// Initialize the maps that will hold the extra tags and metrics for VMs
|
||||
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(`\[(.*?)\]`)
|
||||
@@ -431,7 +458,13 @@ func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.
|
||||
if vmToPool[vm.Self] != "" {
|
||||
vmSummary[vm.Self]["respool"] = vmToPool[vm.Self]
|
||||
}
|
||||
vmSummary[vm.Self]["esx"] = hostSummary[*vm.Summary.Runtime.Host]["name"]
|
||||
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)
|
||||
}
|
||||
|
||||
// get object names
|
||||
@@ -448,16 +481,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
|
||||
}
|
||||
|
||||
@@ -504,8 +537,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
|
||||
}
|
||||
|
||||
@@ -607,15 +640,21 @@ 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(entityName, tags, fields, nowTime)
|
||||
pt, err := influxclient.NewPoint(config.InfluxDB.Prefix+entityName, tags, fields, nowTime)
|
||||
if err != nil {
|
||||
errlog.Println(err)
|
||||
continue
|
||||
@@ -625,7 +664,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(measurement, specialTags[measurement][name][instance], value, time.Now())
|
||||
pt2, err := influxclient.NewPoint(config.InfluxDB.Prefix+measurement, specialTags[measurement][name][instance], value, time.Now())
|
||||
if err != nil {
|
||||
errlog.Println(err)
|
||||
continue
|
||||
@@ -635,12 +674,12 @@ 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
|
||||
// }
|
||||
// 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{}{
|
||||
@@ -648,7 +687,7 @@ func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.
|
||||
"memory_limit": pool.Config.MemoryAllocation.GetResourceAllocationInfo().Limit,
|
||||
}
|
||||
respoolTags := map[string]string{"pool_name": pool.Name}
|
||||
pt3, err := influxclient.NewPoint("resourcepool", respoolTags, respoolFields, time.Now())
|
||||
pt3, err := influxclient.NewPoint(config.InfluxDB.Prefix+"resourcepool", respoolTags, respoolFields, time.Now())
|
||||
if err != nil {
|
||||
errlog.Println(err)
|
||||
continue
|
||||
@@ -662,7 +701,7 @@ func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.
|
||||
"free_space": datastore.Summary.FreeSpace,
|
||||
}
|
||||
datastoreTags := map[string]string{"ds_name": datastore.Summary.Name, "host": vcName}
|
||||
pt4, err := influxclient.NewPoint("datastore", datastoreTags, datastoreFields, time.Now())
|
||||
pt4, err := influxclient.NewPoint(config.InfluxDB.Prefix+"datastore", datastoreTags, datastoreFields, time.Now())
|
||||
if err != nil {
|
||||
errlog.Println(err)
|
||||
continue
|
||||
@@ -672,14 +711,17 @@ func (vcenter *VCenter) Query(config Configuration, InfluxDBClient influxclient.
|
||||
|
||||
}
|
||||
|
||||
//InfluxDB send
|
||||
err = InfluxDBClient.Write(bp)
|
||||
if err != nil {
|
||||
errlog.Println(err)
|
||||
return
|
||||
//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)
|
||||
}
|
||||
|
||||
stdlog.Println("sent data to Influxdb")
|
||||
}
|
||||
|
||||
func min(n ...int64) int64 {
|
||||
@@ -737,20 +779,45 @@ func average(n ...int64) int64 {
|
||||
return int64(math.Floor(favg + .5))
|
||||
}
|
||||
|
||||
func queryVCenter(vcenter VCenter, config Configuration, InfluxDBClient influxclient.Client) {
|
||||
stdlog.Println("Querying vcenter")
|
||||
vcenter.Query(config, InfluxDBClient)
|
||||
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 main() {
|
||||
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()
|
||||
|
||||
baseName := path.Base(os.Args[0])
|
||||
stdlog = log.New(os.Stdout, "", log.Ldate|log.Ltime)
|
||||
errlog = log.New(os.Stderr, "", log.Ldate|log.Ltime)
|
||||
|
||||
stdlog.Println("Starting :", path.Base(os.Args[0]))
|
||||
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 {
|
||||
stdlog.Println("Version:",version)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
stdlog.Println("Starting", baseName, "with config file", *cfgFile)
|
||||
|
||||
// read the configuration
|
||||
file, err := os.Open(*cfgFile)
|
||||
@@ -774,7 +841,6 @@ 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 != "" {
|
||||
@@ -787,28 +853,48 @@ func main() {
|
||||
}
|
||||
|
||||
// Print configuration in debug mode
|
||||
if debug == true {
|
||||
if debug {
|
||||
stdlog.Println("---Configuration - you should see the config here---")
|
||||
spew.Dump(config)
|
||||
}
|
||||
|
||||
for _, vcenter := range config.VCenters {
|
||||
vcenter.Init(config)
|
||||
}
|
||||
|
||||
// Initialize InfluxDB and connect to database
|
||||
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")
|
||||
|
||||
for _, vcenter := range config.VCenters {
|
||||
queryVCenter(*vcenter, config, InfluxDBClient)
|
||||
// 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
|
||||
}
|
||||
close(vcenters)
|
||||
|
||||
for i := 0; i < vcenterCount; i++ {
|
||||
<-results
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,76 +1,81 @@
|
||||
{
|
||||
"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" }
|
||||
"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": {
|
||||
"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": {
|
||||
"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": "*" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user