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

13 Commits

Author SHA1 Message Date
Adrian Todorov
72f628354b bugfix 2018-01-07 16:17:37 +01:00
Adrian Todorov
076f633377 add a version flag 2018-01-07 16:08:06 +01:00
Adrian Todorov
59e2e1d2df bugfix 2018-01-07 15:47:30 +01:00
Adrian Todorov
a461957082 add a -test flag and test mode to output the data collected from vCenter and not send it to Influx 2018-01-07 15:39:49 +01:00
Adrian Todorov
bf09836f04 Add a default "" value for InfluxDB prefix for retrocompatibility post PR #53 2018-01-07 15:11:32 +01:00
Adrian Todorov
c252b28988 Merge pull request #53 from zooplus/master
Nested Folders and measurement prefix support
2018-01-07 15:07:16 +01:00
Artashes Arabajyan
d00ca9ee6d Merged old .gitignore that was somehow overwritten 2018-01-04 12:32:19 +01:00
Artashes Arabajyan
ba0b81c0ef go fmt 2018-01-04 12:25:10 +01:00
Artashes Arabajyan
8b519e50c8 The tool was not able to gather info from the datacenters in nested folders under the root folder - fixed, added config parameter to specify prefix for measurement, cleaned up logging formatting 2018-01-03 21:06:41 +01:00
Adrian Todorov
942b49d61e fix crash on VM cloning 2017-12-10 17:22:33 +01:00
Adrian Todorov
3fe6b1fc22 more bugfixes 2017-11-27 14:56:40 +01:00
Adrian Todorov
01483a5b97 general cleanup; extra checks to avoid segfaults; channels and goroutines for concurrency 2017-11-26 11:32:11 +01:00
Adrian Todorov
65b5bd801f add check to skip clones in progress 2017-11-26 10:50:56 +01:00
3 changed files with 286 additions and 192 deletions

3
.gitignore vendored
View File

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

View File

@@ -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
}
}

View File

@@ -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": "*" }
]
}
]
}