diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e62d594c8d9..a4cdc1af033c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ cross-compilation issue, but will return in v0.13.0. # Main (unreleased) +- [FEATURE] (beta) New integration: windows_exporter (@mattdurham) + - [FEATURE] Official M1 Mac release builds will now be generated! Look for `agent-darwin-arm64` and `agentctl-darwin-arm64` in the release assets. (@rfratto) diff --git a/go.mod b/go.mod index 23de9843e611..a4856f8c7f2f 100644 --- a/go.mod +++ b/go.mod @@ -26,6 +26,7 @@ require ( github.com/opentracing-contrib/go-grpc v0.0.0-20191001143057-db30781987df github.com/opentracing/opentracing-go v1.2.0 github.com/pkg/errors v0.9.1 + github.com/prometheus-community/windows_exporter v0.0.0-00010101000000-000000000000 github.com/prometheus/client_golang v1.9.0 github.com/prometheus/common v0.17.0 github.com/prometheus/consul_exporter v0.7.2-0.20210127095228-584c6de19f23 @@ -83,8 +84,10 @@ replace gopkg.in/yaml.v2 => github.com/rfratto/go-yaml v0.0.0-20200521142311-984 replace ( github.com/google/dnsmasq_exporter => github.com/grafana/dnsmasq_exporter v0.2.1-0.20201029182940-e5169b835a23 github.com/ncabatoff/process-exporter => github.com/grafana/process-exporter v0.7.3-0.20210106202358-831154072e2a + github.com/prometheus-community/windows_exporter => github.com/grafana/windows_exporter v0.15.1-0.20210325142439-9e8f66d53433 github.com/prometheus/mysqld_exporter => github.com/grafana/mysqld_exporter v0.12.2-0.20201015182516-5ac885b2d38a github.com/wrouesnel/postgres_exporter => github.com/grafana/postgres_exporter v0.8.1-0.20201106170118-5eedee00c1db + ) // Required for redis_exporter, which is incompatible with v2.0.0+incompatible. diff --git a/go.sum b/go.sum index cabce23c503c..325873428e53 100644 --- a/go.sum +++ b/go.sum @@ -126,8 +126,11 @@ github.com/Microsoft/ApplicationInsights-Go v0.4.2/go.mod h1:CukZ/G66zxXtI+h/VcV github.com/Microsoft/go-winio v0.4.3/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.9/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= +github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/hcsshim v0.8.6 h1:ZfF0+zZeYdzMIVMZHKtDKJvLHj76XCuVae/jNkjj0IA= +github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.0.1/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= @@ -150,8 +153,9 @@ github.com/Shopify/sarama v1.28.0 h1:lOi3SfE6OcFlW9Trgtked2aHNZ2BIG/d6Do+PEUAqqM github.com/Shopify/sarama v1.28.0/go.mod h1:j/2xTrU39dlzBmsxF1eQ2/DdWrxyBCl6pzz7a81o/ZY= github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/StackExchange/wmi v0.0.0-20180725035823-b12b22c5341f h1:5ZfJxyXo8KyX8DgGXC5B7ILL8y51fci/qYz2B4j8iLY= +github.com/StackExchange/wmi v0.0.0-20180725035823-b12b22c5341f/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af/go.mod h1:5Jv4cbFiHJMsVxt52+i0Ha45fjshj6wxYr1r19tB9bw= @@ -362,6 +366,7 @@ github.com/digitalocean/godo v1.1.1/go.mod h1:h6faOIcZ8lWIwNQ+DN7b3CgX4Kwby5T+nb github.com/digitalocean/godo v1.10.0/go.mod h1:h6faOIcZ8lWIwNQ+DN7b3CgX4Kwby5T+nbpNqkUIozU= github.com/digitalocean/godo v1.57.0 h1:uCpe0sRIZ/sJWxWDsJyBPBjUfSvxop+WHkHiSf+tjjM= github.com/digitalocean/godo v1.57.0/go.mod h1:p7dOjjtSBqCTUksqtA5Fd3uaKs9kyTq2xcz76ulEJRU= +github.com/dimchansky/utfbom v1.1.0 h1:FcM3g+nofKgUteL8dm/UpdRXNC9KmADgTpLKsu0TRo4= github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= github.com/docker/distribution v2.6.0-rc.1.0.20170726174610-edc3ab29cdff+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= @@ -772,6 +777,10 @@ github.com/grafana/prometheus v1.8.2-0.20210218144103-50bc1c15f0c7 h1:Zq7JXdYsCH github.com/grafana/prometheus v1.8.2-0.20210218144103-50bc1c15f0c7/go.mod h1:dv3B1syqmkrkmo665MPCU6L8PbTXIiUeg/OEQULLNxA= github.com/grafana/tail v0.0.0-20201004203643-7aa4e4a91f03 h1:fGgFrAraMB0BaPfYumu+iulfDXwHm+GFyHA4xEtBqI8= github.com/grafana/tail v0.0.0-20201004203643-7aa4e4a91f03/go.mod h1:GIMXMPB/lRAllP5rVDvcGif87ryO2hgD7tCtHMdHrho= +github.com/grafana/windows_exporter v0.15.1-0.20210322180643-3fd7f2178962 h1:QCmiK4yBLpLsdC7iVLhA6AmJei7ARkSg0CRR1us/0Tw= +github.com/grafana/windows_exporter v0.15.1-0.20210322180643-3fd7f2178962/go.mod h1:FZy59lGh3jUzgaaS6jYzzTfk1NTNrH5+UK3NCeQF4Ao= +github.com/grafana/windows_exporter v0.15.1-0.20210325142439-9e8f66d53433 h1:3WaMH1VOp8T2gCwjM5iHtH2SW3BpN8pAmRhzy9TYVAA= +github.com/grafana/windows_exporter v0.15.1-0.20210325142439-9e8f66d53433/go.mod h1:FZy59lGh3jUzgaaS6jYzzTfk1NTNrH5+UK3NCeQF4Ao= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grobie/gomemcache v0.0.0-20201204163352-08d7c80fcac6 h1:vqwzYov9hrRoGAmy61um8mVteOCD0bEbKgXr1mmkTlI= github.com/grobie/gomemcache v0.0.0-20201204163352-08d7c80fcac6/go.mod h1:L69/dBlPQlWkcnU76WgcppK5e4rrxzQdi6LhLnK/ytA= diff --git a/pkg/integrations/install/install.go b/pkg/integrations/install/install.go index 73390a845532..04a1b8e26be0 100644 --- a/pkg/integrations/install/install.go +++ b/pkg/integrations/install/install.go @@ -13,4 +13,5 @@ import ( _ "github.com/grafana/agent/pkg/integrations/process_exporter" // register process_exporter _ "github.com/grafana/agent/pkg/integrations/redis_exporter" // register redis_exporter _ "github.com/grafana/agent/pkg/integrations/statsd_exporter" // register statsd_exporter + _ "github.com/grafana/agent/pkg/integrations/windows_exporter" // register windows_exporter ) diff --git a/pkg/integrations/windows_exporter/config.go b/pkg/integrations/windows_exporter/config.go new file mode 100644 index 000000000000..39c648da62e5 --- /dev/null +++ b/pkg/integrations/windows_exporter/config.go @@ -0,0 +1,101 @@ +package windows_exporter //nolint:golint +import ( + "github.com/go-kit/kit/log" + "github.com/grafana/agent/pkg/integrations" + "github.com/grafana/agent/pkg/integrations/config" +) + +func init() { + integrations.RegisterIntegration(&Config{}) +} + +// Config controls the windows_exporter integration. +// All of these and their child fields are pointers so we can determine if the value was set or not. +type Config struct { + Common config.Common `yaml:",inline"` + + EnabledCollectors string `yaml:"enabled_collectors"` + + Exchange ExchangeConfig `yaml:"exchange"` + IIS IISConfig `yaml:"iis"` + TextFile TextFileConfig `yaml:"text_file"` + SMTP SMTPConfig `yaml:"smtp"` + Service ServiceConfig `yaml:"service"` + Process ProcessConfig `yaml:"process"` + Network NetworkConfig `yaml:"network"` + MSSQL MSSQLConfig `yaml:"mssql"` + MSMQ MSMQConfig `yaml:"msmq"` + LogicalDisk LogicalDiskConfig `yaml:"logical_disk"` +} + +// Name returns the name used, "windows_explorer" +func (c *Config) Name() string { + return "windows_exporter" +} + +// CommonConfig returns the common fields that all integrations have +func (c *Config) CommonConfig() config.Common { + return c.Common +} + +// NewIntegration creates an integration based on the given configuration +func (c *Config) NewIntegration(l log.Logger) (integrations.Integration, error) { + return New(l, c) +} + +// ExchangeConfig handles settings for the windows_exporter Exchange collector +type ExchangeConfig struct { + EnabledList string `yaml:"enabled_list"` +} + +// IISConfig handles settings for the windows_exporter IIS collector +type IISConfig struct { + SiteWhiteList string `yaml:"site_whitelist"` + SiteBlackList string `yaml:"site_blacklist"` + AppWhiteList string `yaml:"app_whitelist"` + AppBlackList string `yaml:"app_blacklist"` +} + +// TextFileConfig handles settings for the windows_exporter Text File collector +type TextFileConfig struct { + TextFileDirectory string `yaml:"text_file_directory"` +} + +// SMTPConfig handles settings for the windows_exporter SMTP collector +type SMTPConfig struct { + WhiteList string `yaml:"whitelist"` + BlackList string `yaml:"blacklist"` +} + +// ServiceConfig handles settings for the windows_exporter service collector +type ServiceConfig struct { + Where string `yaml:"where_clause"` +} + +// ProcessConfig handles settings for the windows_exporter process collector +type ProcessConfig struct { + WhiteList string `yaml:"whitelist"` + BlackList string `yaml:"blacklist"` +} + +// NetworkConfig handles settings for the windows_exporter network collector +type NetworkConfig struct { + WhiteList string `yaml:"whitelist"` + BlackList string `yaml:"blacklist"` +} + +// MSSQLConfig handles settings for the windows_exporter SQL server collector +type MSSQLConfig struct { + EnabledClasses string `yaml:"enabled_classes"` +} + +// MSMQConfig handles settings for the windows_exporter MSMQ collector +type MSMQConfig struct { + Where string `yaml:"where_clause"` +} + +// LogicalDiskConfig handles settings for the windows_exporter logical disk collector +type LogicalDiskConfig struct { + WhiteList string `yaml:"whitelist"` + BlackList string `yaml:"blacklist"` +} diff --git a/pkg/integrations/windows_exporter/config_windows.go b/pkg/integrations/windows_exporter/config_windows.go new file mode 100644 index 000000000000..31555abbfb93 --- /dev/null +++ b/pkg/integrations/windows_exporter/config_windows.go @@ -0,0 +1,136 @@ +package windows_exporter //nolint:golint + +import ( + "reflect" + + "github.com/prometheus-community/windows_exporter/collector" +) + +func (c *Config) applyConfig(exporterConfigs map[string]collector.Config) { + agentConfigs := []translatableConfig{ + &c.Exchange, + &c.IIS, + &c.LogicalDisk, + &c.MSMQ, + &c.MSSQL, + &c.Network, + &c.Process, + &c.Service, + &c.SMTP, + &c.TextFile, + } + // Brute force the syncing, its a bounded set and reduces the code footprint + for _, ac := range agentConfigs { + if ac == nil || reflect.ValueOf(ac).IsNil() { + continue + } + for _, ec := range exporterConfigs { + // Sync will return true if it can handle the exporter config + // which means we can break early + if ac.sync(ec) { + break + } + } + } +} + +// The sync functions are specifically not with their types since they contain windows specific code + +func (c *IISConfig) sync(v interface{}) bool { + other, ok := v.(*collector.IISConfig) + if ok { + setStringIfNotEmpty(c.SiteWhiteList, &other.SiteWhiteList) + setStringIfNotEmpty(c.SiteBlackList, &other.SiteBlackList) + setStringIfNotEmpty(c.AppWhiteList, &other.AppWhiteList) + setStringIfNotEmpty(c.AppBlackList, &other.AppBlackList) + } + return ok +} + +func (c *ExchangeConfig) sync(v interface{}) bool { + other, ok := v.(*collector.ExchangeConfig) + if ok { + setStringIfNotEmpty(c.EnabledList, &other.Enabled) + } + return ok +} + +func (c *TextFileConfig) sync(v interface{}) bool { + other, ok := v.(*collector.TextFileConfig) + if ok { + setStringIfNotEmpty(c.TextFileDirectory, &other.TextFileDirectory) + } + return ok +} + +func (c *SMTPConfig) sync(v interface{}) bool { + other, ok := v.(*collector.SMTPConfig) + if ok { + setStringIfNotEmpty(c.WhiteList, &other.ServerWhiteList) + setStringIfNotEmpty(c.BlackList, &other.ServerBlackList) + } + return ok +} + +func (c *ServiceConfig) sync(v interface{}) bool { + other, ok := v.(*collector.ServiceConfig) + if ok { + setStringIfNotEmpty(c.Where, &other.ServiceWhereClause) + } + return ok +} + +func (c *ProcessConfig) sync(v interface{}) bool { + other, ok := v.(*collector.ProcessConfig) + if ok { + setStringIfNotEmpty(c.WhiteList, &other.ProcessWhiteList) + setStringIfNotEmpty(c.BlackList, &other.ProcessBlackList) + } + return ok +} + +func (c *NetworkConfig) sync(v interface{}) bool { + other, ok := v.(*collector.NetworkConfig) + if ok { + setStringIfNotEmpty(c.WhiteList, &other.NICWhiteList) + setStringIfNotEmpty(c.BlackList, &other.NICBlackList) + } + return ok +} + +func (c *MSSQLConfig) sync(v interface{}) bool { + other, ok := v.(*collector.MSSQLConfig) + if ok { + setStringIfNotEmpty(c.EnabledClasses, &other.MSSQLEnabledCollectors) + } + return ok +} + +func (c *MSMQConfig) sync(v interface{}) bool { + other, ok := v.(*collector.MSMQConfig) + if ok { + setStringIfNotEmpty(c.Where, &other.MSMQWhereClause) + } + return ok +} + +func (c *LogicalDiskConfig) sync(v interface{}) bool { + other, ok := v.(*collector.LogicalDiskConfig) + if ok { + setStringIfNotEmpty(c.WhiteList, &other.VolumeWhiteList) + setStringIfNotEmpty(c.BlackList, &other.VolumeBlackList) + } + return ok +} + +type translatableConfig interface { + sync(v interface{}) bool +} + +// This only works because "" is not a reasonable valid choice for any configurable option currently in windows_exporter +func setStringIfNotEmpty(source string, destination *string) { + if source == "" { + return + } + *destination = source +} diff --git a/pkg/integrations/windows_exporter/windows_exporter.go b/pkg/integrations/windows_exporter/windows_exporter.go new file mode 100644 index 000000000000..1f50bef3644b --- /dev/null +++ b/pkg/integrations/windows_exporter/windows_exporter.go @@ -0,0 +1,42 @@ +// +build !windows + +package windows_exporter //nolint:golint + +import ( + "context" + "net/http" + + "github.com/go-kit/kit/log" + "github.com/go-kit/kit/log/level" + "github.com/grafana/agent/pkg/integrations/config" +) + +// Integration is the windows_exporter integration. On non-Windows platforms, +// this integration does nothing and will print a warning if enabled. +type Integration struct { +} + +// New creates a fake windows_exporter integration. +func New(logger log.Logger, _ *Config) (*Integration, error) { + level.Warn(logger).Log("msg", "the windows_exporter only works on Windows; enabling it otherwise will do nothing") + return &Integration{}, nil +} + +// MetricsHandler satisfies Integration.RegisterRoutes. +func (i *Integration) MetricsHandler() (http.Handler, error) { + return http.NotFoundHandler(), nil +} + +// ScrapeConfigs satisfies Integration.ScrapeConfigs. +func (i *Integration) ScrapeConfigs() []config.ScrapeConfig { + // No-op: nothing to scrape. + return []config.ScrapeConfig{} +} + +// Run satisfies Integration.Run. +func (i *Integration) Run(ctx context.Context) error { + // We don't need to do anything here, so we can just wait for the context to + // finish. + <-ctx.Done() + return ctx.Err() +} diff --git a/pkg/integrations/windows_exporter/windows_exporter_windows.go b/pkg/integrations/windows_exporter/windows_exporter_windows.go new file mode 100644 index 000000000000..d6c012e394e4 --- /dev/null +++ b/pkg/integrations/windows_exporter/windows_exporter_windows.go @@ -0,0 +1,20 @@ +package windows_exporter //nolint:golint + +import ( + "github.com/go-kit/kit/log" + "github.com/go-kit/kit/log/level" + "github.com/grafana/agent/pkg/integrations" + "github.com/prometheus-community/windows_exporter/exporter" +) + +// New creates a new windows_exporter integration. +func New(log log.Logger, c *Config) (integrations.Integration, error) { + configMap := exporter.GenerateConfigs() + c.applyConfig(configMap) + wc, err := exporter.NewWindowsCollector(c.Name(), c.EnabledCollectors, configMap) + if err != nil { + return nil, err + } + _ = level.Info(log).Log("msg", "Enabled windows_exporter collectors") + return integrations.NewCollectorIntegration(c.Name(), integrations.WithCollectors(wc)), nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/.gitignore b/vendor/github.com/Microsoft/hcsshim/.gitignore new file mode 100644 index 000000000000..b883f1fdc6d6 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/.gitignore @@ -0,0 +1 @@ +*.exe diff --git a/vendor/github.com/Microsoft/hcsshim/.gometalinter.json b/vendor/github.com/Microsoft/hcsshim/.gometalinter.json new file mode 100644 index 000000000000..00e9a6e2ecf6 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/.gometalinter.json @@ -0,0 +1,17 @@ +{ + "Vendor": true, + "Deadline": "2m", + "Sort": [ + "linter", + "severity", + "path", + "line" + ], + "Skip": [ + "internal\\schema2" + ], + "EnableGC": true, + "Enable": [ + "gofmt" + ] +} \ No newline at end of file diff --git a/vendor/github.com/Microsoft/hcsshim/LICENSE b/vendor/github.com/Microsoft/hcsshim/LICENSE new file mode 100644 index 000000000000..49d21669aeef --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/vendor/github.com/Microsoft/hcsshim/README.md b/vendor/github.com/Microsoft/hcsshim/README.md new file mode 100644 index 000000000000..15b39181a5df --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/README.md @@ -0,0 +1,41 @@ +# hcsshim + +[![Build status](https://ci.appveyor.com/api/projects/status/nbcw28mnkqml0loa/branch/master?svg=true)](https://ci.appveyor.com/project/WindowsVirtualization/hcsshim/branch/master) + +This package contains the Golang interface for using the Windows [Host Compute Service](https://blogs.technet.microsoft.com/virtualization/2017/01/27/introducing-the-host-compute-service-hcs/) (HCS) to launch and manage [Windows Containers](https://docs.microsoft.com/en-us/virtualization/windowscontainers/about/). It also contains other helpers and functions for managing Windows Containers such as the Golang interface for the Host Network Service (HNS). + +It is primarily used in the [Moby Project](https://github.com/moby/moby), but it can be freely used by other projects as well. + +## Contributing + +This project welcomes contributions and suggestions. Most contributions require you to agree to a +Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us +the rights to use your contribution. For details, visit https://cla.microsoft.com. + +When you submit a pull request, a CLA-bot will automatically determine whether you need to provide +a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions +provided by the bot. You will only need to do this once across all repos using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or +contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. + +## Dependencies + +This project requires Golang 1.9 or newer to build. + +For system requirements to run this project, see the Microsoft docs on [Windows Container requirements](https://docs.microsoft.com/en-us/virtualization/windowscontainers/deploy-containers/system-requirements). + +## Reporting Security Issues + +Security issues and bugs should be reported privately, via email, to the Microsoft Security +Response Center (MSRC) at [secure@microsoft.com](mailto:secure@microsoft.com). You should +receive a response within 24 hours. If for some reason you do not, please follow up via +email to ensure we received your original message. Further information, including the +[MSRC PGP](https://technet.microsoft.com/en-us/security/dn606155) key, can be found in +the [Security TechCenter](https://technet.microsoft.com/en-us/security/default). + +For additional details, see [Report a Computer Security Vulnerability](https://technet.microsoft.com/en-us/security/ff852094.aspx) on Technet + +--------------- +Copyright (c) 2018 Microsoft Corp. All rights reserved. diff --git a/vendor/github.com/Microsoft/hcsshim/appveyor.yml b/vendor/github.com/Microsoft/hcsshim/appveyor.yml new file mode 100644 index 000000000000..a8ec5a593904 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/appveyor.yml @@ -0,0 +1,29 @@ +version: 0.1.{build} + +image: Visual Studio 2017 + +clone_folder: c:\gopath\src\github.com\Microsoft\hcsshim + +environment: + GOPATH: c:\gopath + PATH: C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin;%GOPATH%\bin;C:\gometalinter-2.0.12-windows-amd64;%PATH% + +stack: go 1.11 + +build_script: + - appveyor DownloadFile https://github.com/alecthomas/gometalinter/releases/download/v2.0.12/gometalinter-2.0.12-windows-amd64.zip + - 7z x gometalinter-2.0.12-windows-amd64.zip -y -oC:\ > NUL + - gometalinter.exe --config .gometalinter.json ./... + - go build ./cmd/wclayer + - go build ./cmd/runhcs + - go build ./cmd/tar2ext4 + - go test -v ./... -tags admin + - go test -c ./test/functional/ -tags functional + - go test -c ./test/runhcs/ -tags integration + +artifacts: + - path: 'wclayer.exe' + - path: 'runhcs.exe' + - path: 'tar2ext4.exe' + - path: 'functional.test.exe' + - path: 'runhcs.test.exe' \ No newline at end of file diff --git a/vendor/github.com/Microsoft/hcsshim/container.go b/vendor/github.com/Microsoft/hcsshim/container.go new file mode 100644 index 000000000000..e142c315445a --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/container.go @@ -0,0 +1,192 @@ +package hcsshim + +import ( + "fmt" + "os" + "time" + + "github.com/Microsoft/hcsshim/internal/hcs" + "github.com/Microsoft/hcsshim/internal/mergemaps" + "github.com/Microsoft/hcsshim/internal/schema1" +) + +// ContainerProperties holds the properties for a container and the processes running in that container +type ContainerProperties = schema1.ContainerProperties + +// MemoryStats holds the memory statistics for a container +type MemoryStats = schema1.MemoryStats + +// ProcessorStats holds the processor statistics for a container +type ProcessorStats = schema1.ProcessorStats + +// StorageStats holds the storage statistics for a container +type StorageStats = schema1.StorageStats + +// NetworkStats holds the network statistics for a container +type NetworkStats = schema1.NetworkStats + +// Statistics is the structure returned by a statistics call on a container +type Statistics = schema1.Statistics + +// ProcessList is the structure of an item returned by a ProcessList call on a container +type ProcessListItem = schema1.ProcessListItem + +// MappedVirtualDiskController is the structure of an item returned by a MappedVirtualDiskList call on a container +type MappedVirtualDiskController = schema1.MappedVirtualDiskController + +// Type of Request Support in ModifySystem +type RequestType = schema1.RequestType + +// Type of Resource Support in ModifySystem +type ResourceType = schema1.ResourceType + +// RequestType const +const ( + Add = schema1.Add + Remove = schema1.Remove + Network = schema1.Network +) + +// ResourceModificationRequestResponse is the structure used to send request to the container to modify the system +// Supported resource types are Network and Request Types are Add/Remove +type ResourceModificationRequestResponse = schema1.ResourceModificationRequestResponse + +type container struct { + system *hcs.System +} + +// createComputeSystemAdditionalJSON is read from the environment at initialisation +// time. It allows an environment variable to define additional JSON which +// is merged in the CreateComputeSystem call to HCS. +var createContainerAdditionalJSON []byte + +func init() { + createContainerAdditionalJSON = ([]byte)(os.Getenv("HCSSHIM_CREATECONTAINER_ADDITIONALJSON")) +} + +// CreateContainer creates a new container with the given configuration but does not start it. +func CreateContainer(id string, c *ContainerConfig) (Container, error) { + fullConfig, err := mergemaps.MergeJSON(c, createContainerAdditionalJSON) + if err != nil { + return nil, fmt.Errorf("failed to merge additional JSON '%s': %s", createContainerAdditionalJSON, err) + } + + system, err := hcs.CreateComputeSystem(id, fullConfig) + if err != nil { + return nil, err + } + return &container{system}, err +} + +// OpenContainer opens an existing container by ID. +func OpenContainer(id string) (Container, error) { + system, err := hcs.OpenComputeSystem(id) + if err != nil { + return nil, err + } + return &container{system}, err +} + +// GetContainers gets a list of the containers on the system that match the query +func GetContainers(q ComputeSystemQuery) ([]ContainerProperties, error) { + return hcs.GetComputeSystems(q) +} + +// Start synchronously starts the container. +func (container *container) Start() error { + return convertSystemError(container.system.Start(), container) +} + +// Shutdown requests a container shutdown, but it may not actually be shutdown until Wait() succeeds. +func (container *container) Shutdown() error { + return convertSystemError(container.system.Shutdown(), container) +} + +// Terminate requests a container terminate, but it may not actually be terminated until Wait() succeeds. +func (container *container) Terminate() error { + return convertSystemError(container.system.Terminate(), container) +} + +// Waits synchronously waits for the container to shutdown or terminate. +func (container *container) Wait() error { + return convertSystemError(container.system.Wait(), container) +} + +// WaitTimeout synchronously waits for the container to terminate or the duration to elapse. It +// returns false if timeout occurs. +func (container *container) WaitTimeout(t time.Duration) error { + return convertSystemError(container.system.WaitTimeout(t), container) +} + +// Pause pauses the execution of a container. +func (container *container) Pause() error { + return convertSystemError(container.system.Pause(), container) +} + +// Resume resumes the execution of a container. +func (container *container) Resume() error { + return convertSystemError(container.system.Resume(), container) +} + +// HasPendingUpdates returns true if the container has updates pending to install +func (container *container) HasPendingUpdates() (bool, error) { + return false, nil +} + +// Statistics returns statistics for the container. This is a legacy v1 call +func (container *container) Statistics() (Statistics, error) { + properties, err := container.system.Properties(schema1.PropertyTypeStatistics) + if err != nil { + return Statistics{}, convertSystemError(err, container) + } + + return properties.Statistics, nil +} + +// ProcessList returns an array of ProcessListItems for the container. This is a legacy v1 call +func (container *container) ProcessList() ([]ProcessListItem, error) { + properties, err := container.system.Properties(schema1.PropertyTypeProcessList) + if err != nil { + return nil, convertSystemError(err, container) + } + + return properties.ProcessList, nil +} + +// This is a legacy v1 call +func (container *container) MappedVirtualDisks() (map[int]MappedVirtualDiskController, error) { + properties, err := container.system.Properties(schema1.PropertyTypeMappedVirtualDisk) + if err != nil { + return nil, convertSystemError(err, container) + } + + return properties.MappedVirtualDiskControllers, nil +} + +// CreateProcess launches a new process within the container. +func (container *container) CreateProcess(c *ProcessConfig) (Process, error) { + p, err := container.system.CreateProcess(c) + if err != nil { + return nil, convertSystemError(err, container) + } + return &process{p}, nil +} + +// OpenProcess gets an interface to an existing process within the container. +func (container *container) OpenProcess(pid int) (Process, error) { + p, err := container.system.OpenProcess(pid) + if err != nil { + return nil, convertSystemError(err, container) + } + return &process{p}, nil +} + +// Close cleans up any state associated with the container but does not terminate or wait for it. +func (container *container) Close() error { + return convertSystemError(container.system.Close(), container) +} + +// Modify the System +func (container *container) Modify(config *ResourceModificationRequestResponse) error { + return convertSystemError(container.system.Modify(config), container) +} diff --git a/vendor/github.com/Microsoft/hcsshim/errors.go b/vendor/github.com/Microsoft/hcsshim/errors.go new file mode 100644 index 000000000000..63efa23c7a4e --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/errors.go @@ -0,0 +1,257 @@ +package hcsshim + +import ( + "fmt" + "syscall" + + "github.com/Microsoft/hcsshim/internal/hns" + + "github.com/Microsoft/hcsshim/internal/hcs" + "github.com/Microsoft/hcsshim/internal/hcserror" +) + +var ( + // ErrComputeSystemDoesNotExist is an error encountered when the container being operated on no longer exists = hcs.exist + ErrComputeSystemDoesNotExist = hcs.ErrComputeSystemDoesNotExist + + // ErrElementNotFound is an error encountered when the object being referenced does not exist + ErrElementNotFound = hcs.ErrElementNotFound + + // ErrElementNotFound is an error encountered when the object being referenced does not exist + ErrNotSupported = hcs.ErrNotSupported + + // ErrInvalidData is an error encountered when the request being sent to hcs is invalid/unsupported + // decimal -2147024883 / hex 0x8007000d + ErrInvalidData = hcs.ErrInvalidData + + // ErrHandleClose is an error encountered when the handle generating the notification being waited on has been closed + ErrHandleClose = hcs.ErrHandleClose + + // ErrAlreadyClosed is an error encountered when using a handle that has been closed by the Close method + ErrAlreadyClosed = hcs.ErrAlreadyClosed + + // ErrInvalidNotificationType is an error encountered when an invalid notification type is used + ErrInvalidNotificationType = hcs.ErrInvalidNotificationType + + // ErrInvalidProcessState is an error encountered when the process is not in a valid state for the requested operation + ErrInvalidProcessState = hcs.ErrInvalidProcessState + + // ErrTimeout is an error encountered when waiting on a notification times out + ErrTimeout = hcs.ErrTimeout + + // ErrUnexpectedContainerExit is the error encountered when a container exits while waiting for + // a different expected notification + ErrUnexpectedContainerExit = hcs.ErrUnexpectedContainerExit + + // ErrUnexpectedProcessAbort is the error encountered when communication with the compute service + // is lost while waiting for a notification + ErrUnexpectedProcessAbort = hcs.ErrUnexpectedProcessAbort + + // ErrUnexpectedValue is an error encountered when hcs returns an invalid value + ErrUnexpectedValue = hcs.ErrUnexpectedValue + + // ErrVmcomputeAlreadyStopped is an error encountered when a shutdown or terminate request is made on a stopped container + ErrVmcomputeAlreadyStopped = hcs.ErrVmcomputeAlreadyStopped + + // ErrVmcomputeOperationPending is an error encountered when the operation is being completed asynchronously + ErrVmcomputeOperationPending = hcs.ErrVmcomputeOperationPending + + // ErrVmcomputeOperationInvalidState is an error encountered when the compute system is not in a valid state for the requested operation + ErrVmcomputeOperationInvalidState = hcs.ErrVmcomputeOperationInvalidState + + // ErrProcNotFound is an error encountered when the the process cannot be found + ErrProcNotFound = hcs.ErrProcNotFound + + // ErrVmcomputeOperationAccessIsDenied is an error which can be encountered when enumerating compute systems in RS1/RS2 + // builds when the underlying silo might be in the process of terminating. HCS was fixed in RS3. + ErrVmcomputeOperationAccessIsDenied = hcs.ErrVmcomputeOperationAccessIsDenied + + // ErrVmcomputeInvalidJSON is an error encountered when the compute system does not support/understand the messages sent by management + ErrVmcomputeInvalidJSON = hcs.ErrVmcomputeInvalidJSON + + // ErrVmcomputeUnknownMessage is an error encountered guest compute system doesn't support the message + ErrVmcomputeUnknownMessage = hcs.ErrVmcomputeUnknownMessage + + // ErrNotSupported is an error encountered when hcs doesn't support the request + ErrPlatformNotSupported = hcs.ErrPlatformNotSupported +) + +type EndpointNotFoundError = hns.EndpointNotFoundError +type NetworkNotFoundError = hns.NetworkNotFoundError + +// ProcessError is an error encountered in HCS during an operation on a Process object +type ProcessError struct { + Process *process + Operation string + ExtraInfo string + Err error + Events []hcs.ErrorEvent +} + +// ContainerError is an error encountered in HCS during an operation on a Container object +type ContainerError struct { + Container *container + Operation string + ExtraInfo string + Err error + Events []hcs.ErrorEvent +} + +func (e *ContainerError) Error() string { + if e == nil { + return "" + } + + if e.Container == nil { + return "unexpected nil container for error: " + e.Err.Error() + } + + s := "container " + e.Container.system.ID() + + if e.Operation != "" { + s += " encountered an error during " + e.Operation + } + + switch e.Err.(type) { + case nil: + break + case syscall.Errno: + s += fmt.Sprintf(": failure in a Windows system call: %s (0x%x)", e.Err, hcserror.Win32FromError(e.Err)) + default: + s += fmt.Sprintf(": %s", e.Err.Error()) + } + + for _, ev := range e.Events { + s += "\n" + ev.String() + } + + if e.ExtraInfo != "" { + s += " extra info: " + e.ExtraInfo + } + + return s +} + +func makeContainerError(container *container, operation string, extraInfo string, err error) error { + // Don't double wrap errors + if _, ok := err.(*ContainerError); ok { + return err + } + containerError := &ContainerError{Container: container, Operation: operation, ExtraInfo: extraInfo, Err: err} + return containerError +} + +func (e *ProcessError) Error() string { + if e == nil { + return "" + } + + if e.Process == nil { + return "Unexpected nil process for error: " + e.Err.Error() + } + + s := fmt.Sprintf("process %d in container %s", e.Process.p.Pid(), e.Process.p.SystemID()) + if e.Operation != "" { + s += " encountered an error during " + e.Operation + } + + switch e.Err.(type) { + case nil: + break + case syscall.Errno: + s += fmt.Sprintf(": failure in a Windows system call: %s (0x%x)", e.Err, hcserror.Win32FromError(e.Err)) + default: + s += fmt.Sprintf(": %s", e.Err.Error()) + } + + for _, ev := range e.Events { + s += "\n" + ev.String() + } + + return s +} + +func makeProcessError(process *process, operation string, extraInfo string, err error) error { + // Don't double wrap errors + if _, ok := err.(*ProcessError); ok { + return err + } + processError := &ProcessError{Process: process, Operation: operation, ExtraInfo: extraInfo, Err: err} + return processError +} + +// IsNotExist checks if an error is caused by the Container or Process not existing. +// Note: Currently, ErrElementNotFound can mean that a Process has either +// already exited, or does not exist. Both IsAlreadyStopped and IsNotExist +// will currently return true when the error is ErrElementNotFound or ErrProcNotFound. +func IsNotExist(err error) bool { + if _, ok := err.(EndpointNotFoundError); ok { + return true + } + if _, ok := err.(NetworkNotFoundError); ok { + return true + } + return hcs.IsNotExist(getInnerError(err)) +} + +// IsAlreadyClosed checks if an error is caused by the Container or Process having been +// already closed by a call to the Close() method. +func IsAlreadyClosed(err error) bool { + return hcs.IsAlreadyClosed(getInnerError(err)) +} + +// IsPending returns a boolean indicating whether the error is that +// the requested operation is being completed in the background. +func IsPending(err error) bool { + return hcs.IsPending(getInnerError(err)) +} + +// IsTimeout returns a boolean indicating whether the error is caused by +// a timeout waiting for the operation to complete. +func IsTimeout(err error) bool { + return hcs.IsTimeout(getInnerError(err)) +} + +// IsAlreadyStopped returns a boolean indicating whether the error is caused by +// a Container or Process being already stopped. +// Note: Currently, ErrElementNotFound can mean that a Process has either +// already exited, or does not exist. Both IsAlreadyStopped and IsNotExist +// will currently return true when the error is ErrElementNotFound or ErrProcNotFound. +func IsAlreadyStopped(err error) bool { + return hcs.IsAlreadyStopped(getInnerError(err)) +} + +// IsNotSupported returns a boolean indicating whether the error is caused by +// unsupported platform requests +// Note: Currently Unsupported platform requests can be mean either +// ErrVmcomputeInvalidJSON, ErrInvalidData, ErrNotSupported or ErrVmcomputeUnknownMessage +// is thrown from the Platform +func IsNotSupported(err error) bool { + return hcs.IsNotSupported(getInnerError(err)) +} + +func getInnerError(err error) error { + switch pe := err.(type) { + case nil: + return nil + case *ContainerError: + err = pe.Err + case *ProcessError: + err = pe.Err + } + return err +} + +func convertSystemError(err error, c *container) error { + if serr, ok := err.(*hcs.SystemError); ok { + return &ContainerError{Container: c, Operation: serr.Op, ExtraInfo: serr.Extra, Err: serr.Err, Events: serr.Events} + } + return err +} + +func convertProcessError(err error, p *process) error { + if perr, ok := err.(*hcs.ProcessError); ok { + return &ProcessError{Process: p, Operation: perr.Op, Err: perr.Err, Events: perr.Events} + } + return err +} diff --git a/vendor/github.com/Microsoft/hcsshim/functional_tests.ps1 b/vendor/github.com/Microsoft/hcsshim/functional_tests.ps1 new file mode 100644 index 000000000000..ce6edbcf329c --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/functional_tests.ps1 @@ -0,0 +1,12 @@ +# Requirements so far: +# dockerd running +# - image microsoft/nanoserver (matching host base image) docker load -i c:\baseimages\nanoserver.tar +# - image alpine (linux) docker pull --platform=linux alpine + + +# TODO: Add this a parameter for debugging. ie "functional-tests -debug=$true" +#$env:HCSSHIM_FUNCTIONAL_TESTS_DEBUG="yes please" + +#pushd uvm +go test -v -tags "functional uvmcreate uvmscratch uvmscsi uvmvpmem uvmvsmb uvmp9" ./... +#popd \ No newline at end of file diff --git a/vendor/github.com/Microsoft/hcsshim/hcsshim.go b/vendor/github.com/Microsoft/hcsshim/hcsshim.go new file mode 100644 index 000000000000..ceb3ac85ee46 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/hcsshim.go @@ -0,0 +1,28 @@ +// Shim for the Host Compute Service (HCS) to manage Windows Server +// containers and Hyper-V containers. + +package hcsshim + +import ( + "syscall" + + "github.com/Microsoft/hcsshim/internal/hcserror" +) + +//go:generate go run mksyscall_windows.go -output zsyscall_windows.go hcsshim.go + +//sys SetCurrentThreadCompartmentId(compartmentId uint32) (hr error) = iphlpapi.SetCurrentThreadCompartmentId + +const ( + // Specific user-visible exit codes + WaitErrExecFailed = 32767 + + ERROR_GEN_FAILURE = hcserror.ERROR_GEN_FAILURE + ERROR_SHUTDOWN_IN_PROGRESS = syscall.Errno(1115) + WSAEINVAL = syscall.Errno(10022) + + // Timeout on wait calls + TimeoutInfinite = 0xFFFFFFFF +) + +type HcsError = hcserror.HcsError diff --git a/vendor/github.com/Microsoft/hcsshim/hnsendpoint.go b/vendor/github.com/Microsoft/hcsshim/hnsendpoint.go new file mode 100644 index 000000000000..eb013d2c42ed --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/hnsendpoint.go @@ -0,0 +1,94 @@ +package hcsshim + +import ( + "github.com/Microsoft/hcsshim/internal/hns" +) + +// HNSEndpoint represents a network endpoint in HNS +type HNSEndpoint = hns.HNSEndpoint + +// Namespace represents a Compartment. +type Namespace = hns.Namespace + +//SystemType represents the type of the system on which actions are done +type SystemType string + +// SystemType const +const ( + ContainerType SystemType = "Container" + VirtualMachineType SystemType = "VirtualMachine" + HostType SystemType = "Host" +) + +// EndpointAttachDetachRequest is the structure used to send request to the container to modify the system +// Supported resource types are Network and Request Types are Add/Remove +type EndpointAttachDetachRequest = hns.EndpointAttachDetachRequest + +// EndpointResquestResponse is object to get the endpoint request response +type EndpointResquestResponse = hns.EndpointResquestResponse + +// HNSEndpointRequest makes a HNS call to modify/query a network endpoint +func HNSEndpointRequest(method, path, request string) (*HNSEndpoint, error) { + return hns.HNSEndpointRequest(method, path, request) +} + +// HNSListEndpointRequest makes a HNS call to query the list of available endpoints +func HNSListEndpointRequest() ([]HNSEndpoint, error) { + return hns.HNSListEndpointRequest() +} + +// HotAttachEndpoint makes a HCS Call to attach the endpoint to the container +func HotAttachEndpoint(containerID string, endpointID string) error { + return modifyNetworkEndpoint(containerID, endpointID, Add) +} + +// HotDetachEndpoint makes a HCS Call to detach the endpoint from the container +func HotDetachEndpoint(containerID string, endpointID string) error { + return modifyNetworkEndpoint(containerID, endpointID, Remove) +} + +// ModifyContainer corresponding to the container id, by sending a request +func modifyContainer(id string, request *ResourceModificationRequestResponse) error { + container, err := OpenContainer(id) + if err != nil { + if IsNotExist(err) { + return ErrComputeSystemDoesNotExist + } + return getInnerError(err) + } + defer container.Close() + err = container.Modify(request) + if err != nil { + if IsNotSupported(err) { + return ErrPlatformNotSupported + } + return getInnerError(err) + } + + return nil +} + +func modifyNetworkEndpoint(containerID string, endpointID string, request RequestType) error { + requestMessage := &ResourceModificationRequestResponse{ + Resource: Network, + Request: request, + Data: endpointID, + } + err := modifyContainer(containerID, requestMessage) + + if err != nil { + return err + } + + return nil +} + +// GetHNSEndpointByID get the Endpoint by ID +func GetHNSEndpointByID(endpointID string) (*HNSEndpoint, error) { + return hns.GetHNSEndpointByID(endpointID) +} + +// GetHNSEndpointByName gets the endpoint filtered by Name +func GetHNSEndpointByName(endpointName string) (*HNSEndpoint, error) { + return hns.GetHNSEndpointByName(endpointName) +} diff --git a/vendor/github.com/Microsoft/hcsshim/hnsglobals.go b/vendor/github.com/Microsoft/hcsshim/hnsglobals.go new file mode 100644 index 000000000000..2b538190476e --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/hnsglobals.go @@ -0,0 +1,16 @@ +package hcsshim + +import ( + "github.com/Microsoft/hcsshim/internal/hns" +) + +type HNSGlobals = hns.HNSGlobals +type HNSVersion = hns.HNSVersion + +var ( + HNSVersion1803 = hns.HNSVersion1803 +) + +func GetHNSGlobals() (*HNSGlobals, error) { + return hns.GetHNSGlobals() +} diff --git a/vendor/github.com/Microsoft/hcsshim/hnsnetwork.go b/vendor/github.com/Microsoft/hcsshim/hnsnetwork.go new file mode 100644 index 000000000000..f775fa1d07c9 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/hnsnetwork.go @@ -0,0 +1,36 @@ +package hcsshim + +import ( + "github.com/Microsoft/hcsshim/internal/hns" +) + +// Subnet is assoicated with a network and represents a list +// of subnets available to the network +type Subnet = hns.Subnet + +// MacPool is assoicated with a network and represents a list +// of macaddresses available to the network +type MacPool = hns.MacPool + +// HNSNetwork represents a network in HNS +type HNSNetwork = hns.HNSNetwork + +// HNSNetworkRequest makes a call into HNS to update/query a single network +func HNSNetworkRequest(method, path, request string) (*HNSNetwork, error) { + return hns.HNSNetworkRequest(method, path, request) +} + +// HNSListNetworkRequest makes a HNS call to query the list of available networks +func HNSListNetworkRequest(method, path, request string) ([]HNSNetwork, error) { + return hns.HNSListNetworkRequest(method, path, request) +} + +// GetHNSNetworkByID +func GetHNSNetworkByID(networkID string) (*HNSNetwork, error) { + return hns.GetHNSNetworkByID(networkID) +} + +// GetHNSNetworkName filtered by Name +func GetHNSNetworkByName(networkName string) (*HNSNetwork, error) { + return hns.GetHNSNetworkByName(networkName) +} diff --git a/vendor/github.com/Microsoft/hcsshim/hnspolicy.go b/vendor/github.com/Microsoft/hcsshim/hnspolicy.go new file mode 100644 index 000000000000..a3e03ff8fcf8 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/hnspolicy.go @@ -0,0 +1,57 @@ +package hcsshim + +import ( + "github.com/Microsoft/hcsshim/internal/hns" +) + +// Type of Request Support in ModifySystem +type PolicyType = hns.PolicyType + +// RequestType const +const ( + Nat = hns.Nat + ACL = hns.ACL + PA = hns.PA + VLAN = hns.VLAN + VSID = hns.VSID + VNet = hns.VNet + L2Driver = hns.L2Driver + Isolation = hns.Isolation + QOS = hns.QOS + OutboundNat = hns.OutboundNat + ExternalLoadBalancer = hns.ExternalLoadBalancer + Route = hns.Route +) + +type NatPolicy = hns.NatPolicy + +type QosPolicy = hns.QosPolicy + +type IsolationPolicy = hns.IsolationPolicy + +type VlanPolicy = hns.VlanPolicy + +type VsidPolicy = hns.VsidPolicy + +type PaPolicy = hns.PaPolicy + +type OutboundNatPolicy = hns.OutboundNatPolicy + +type ActionType = hns.ActionType +type DirectionType = hns.DirectionType +type RuleType = hns.RuleType + +const ( + Allow = hns.Allow + Block = hns.Block + + In = hns.In + Out = hns.Out + + Host = hns.Host + Switch = hns.Switch +) + +type ACLPolicy = hns.ACLPolicy + +type Policy = hns.Policy diff --git a/vendor/github.com/Microsoft/hcsshim/hnspolicylist.go b/vendor/github.com/Microsoft/hcsshim/hnspolicylist.go new file mode 100644 index 000000000000..55aaa4a50efb --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/hnspolicylist.go @@ -0,0 +1,47 @@ +package hcsshim + +import ( + "github.com/Microsoft/hcsshim/internal/hns" +) + +// RoutePolicy is a structure defining schema for Route based Policy +type RoutePolicy = hns.RoutePolicy + +// ELBPolicy is a structure defining schema for ELB LoadBalancing based Policy +type ELBPolicy = hns.ELBPolicy + +// LBPolicy is a structure defining schema for LoadBalancing based Policy +type LBPolicy = hns.LBPolicy + +// PolicyList is a structure defining schema for Policy list request +type PolicyList = hns.PolicyList + +// HNSPolicyListRequest makes a call into HNS to update/query a single network +func HNSPolicyListRequest(method, path, request string) (*PolicyList, error) { + return hns.HNSPolicyListRequest(method, path, request) +} + +// HNSListPolicyListRequest gets all the policy list +func HNSListPolicyListRequest() ([]PolicyList, error) { + return hns.HNSListPolicyListRequest() +} + +// PolicyListRequest makes a HNS call to modify/query a network policy list +func PolicyListRequest(method, path, request string) (*PolicyList, error) { + return hns.PolicyListRequest(method, path, request) +} + +// GetPolicyListByID get the policy list by ID +func GetPolicyListByID(policyListID string) (*PolicyList, error) { + return hns.GetPolicyListByID(policyListID) +} + +// AddLoadBalancer policy list for the specified endpoints +func AddLoadBalancer(endpoints []HNSEndpoint, isILB bool, sourceVIP, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*PolicyList, error) { + return hns.AddLoadBalancer(endpoints, isILB, sourceVIP, vip, protocol, internalPort, externalPort) +} + +// AddRoute adds route policy list for the specified endpoints +func AddRoute(endpoints []HNSEndpoint, destinationPrefix string, nextHop string, encapEnabled bool) (*PolicyList, error) { + return hns.AddRoute(endpoints, destinationPrefix, nextHop, encapEnabled) +} diff --git a/vendor/github.com/Microsoft/hcsshim/hnssupport.go b/vendor/github.com/Microsoft/hcsshim/hnssupport.go new file mode 100644 index 000000000000..69405244b673 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/hnssupport.go @@ -0,0 +1,13 @@ +package hcsshim + +import ( + "github.com/Microsoft/hcsshim/internal/hns" +) + +type HNSSupportedFeatures = hns.HNSSupportedFeatures + +type HNSAclFeatures = hns.HNSAclFeatures + +func GetHNSSupportedFeatures() HNSSupportedFeatures { + return hns.GetHNSSupportedFeatures() +} diff --git a/vendor/github.com/Microsoft/hcsshim/interface.go b/vendor/github.com/Microsoft/hcsshim/interface.go new file mode 100644 index 000000000000..5b91e0cc55cf --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/interface.go @@ -0,0 +1,114 @@ +package hcsshim + +import ( + "io" + "time" + + "github.com/Microsoft/hcsshim/internal/schema1" +) + +// ProcessConfig is used as both the input of Container.CreateProcess +// and to convert the parameters to JSON for passing onto the HCS +type ProcessConfig = schema1.ProcessConfig + +type Layer = schema1.Layer +type MappedDir = schema1.MappedDir +type MappedPipe = schema1.MappedPipe +type HvRuntime = schema1.HvRuntime +type MappedVirtualDisk = schema1.MappedVirtualDisk + +// AssignedDevice represents a device that has been directly assigned to a container +// +// NOTE: Support added in RS5 +type AssignedDevice = schema1.AssignedDevice + +// ContainerConfig is used as both the input of CreateContainer +// and to convert the parameters to JSON for passing onto the HCS +type ContainerConfig = schema1.ContainerConfig + +type ComputeSystemQuery = schema1.ComputeSystemQuery + +// Container represents a created (but not necessarily running) container. +type Container interface { + // Start synchronously starts the container. + Start() error + + // Shutdown requests a container shutdown, but it may not actually be shutdown until Wait() succeeds. + Shutdown() error + + // Terminate requests a container terminate, but it may not actually be terminated until Wait() succeeds. + Terminate() error + + // Waits synchronously waits for the container to shutdown or terminate. + Wait() error + + // WaitTimeout synchronously waits for the container to terminate or the duration to elapse. It + // returns false if timeout occurs. + WaitTimeout(time.Duration) error + + // Pause pauses the execution of a container. + Pause() error + + // Resume resumes the execution of a container. + Resume() error + + // HasPendingUpdates returns true if the container has updates pending to install. + HasPendingUpdates() (bool, error) + + // Statistics returns statistics for a container. + Statistics() (Statistics, error) + + // ProcessList returns details for the processes in a container. + ProcessList() ([]ProcessListItem, error) + + // MappedVirtualDisks returns virtual disks mapped to a utility VM, indexed by controller + MappedVirtualDisks() (map[int]MappedVirtualDiskController, error) + + // CreateProcess launches a new process within the container. + CreateProcess(c *ProcessConfig) (Process, error) + + // OpenProcess gets an interface to an existing process within the container. + OpenProcess(pid int) (Process, error) + + // Close cleans up any state associated with the container but does not terminate or wait for it. + Close() error + + // Modify the System + Modify(config *ResourceModificationRequestResponse) error +} + +// Process represents a running or exited process. +type Process interface { + // Pid returns the process ID of the process within the container. + Pid() int + + // Kill signals the process to terminate but does not wait for it to finish terminating. + Kill() error + + // Wait waits for the process to exit. + Wait() error + + // WaitTimeout waits for the process to exit or the duration to elapse. It returns + // false if timeout occurs. + WaitTimeout(time.Duration) error + + // ExitCode returns the exit code of the process. The process must have + // already terminated. + ExitCode() (int, error) + + // ResizeConsole resizes the console of the process. + ResizeConsole(width, height uint16) error + + // Stdio returns the stdin, stdout, and stderr pipes, respectively. Closing + // these pipes does not close the underlying pipes; it should be possible to + // call this multiple times to get multiple interfaces. + Stdio() (io.WriteCloser, io.ReadCloser, io.ReadCloser, error) + + // CloseStdin closes the write side of the stdin pipe so that the process is + // notified on the read side that there is no more data in stdin. + CloseStdin() error + + // Close cleans up any state associated with the process but does not kill + // or wait on it. + Close() error +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/guestrequest/types.go b/vendor/github.com/Microsoft/hcsshim/internal/guestrequest/types.go new file mode 100644 index 000000000000..5d3d0dfef13a --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/guestrequest/types.go @@ -0,0 +1,100 @@ +package guestrequest + +import ( + "github.com/Microsoft/hcsshim/internal/schema2" +) + +// Arguably, many of these (at least CombinedLayers) should have been generated +// by swagger. +// +// This will also change package name due to an inbound breaking change. + +// This class is used by a modify request to add or remove a combined layers +// structure in the guest. For windows, the GCS applies a filter in ContainerRootPath +// using the specified layers as the parent content. Ignores property ScratchPath +// since the container path is already the scratch path. For linux, the GCS unions +// the specified layers and ScratchPath together, placing the resulting union +// filesystem at ContainerRootPath. +type CombinedLayers struct { + ContainerRootPath string `json:"ContainerRootPath,omitempty"` + Layers []hcsschema.Layer `json:"Layers,omitempty"` + ScratchPath string `json:"ScratchPath,omitempty"` +} + +// Defines the schema for hosted settings passed to GCS and/or OpenGCS + +// SCSI. Scratch space for remote file-system commands, or R/W layer for containers +type LCOWMappedVirtualDisk struct { + MountPath string `json:"MountPath,omitempty"` // /tmp/scratch for an LCOW utility VM being used as a service VM + Lun uint8 `json:"Lun,omitempty"` + Controller uint8 `json:"Controller,omitempty"` + ReadOnly bool `json:"ReadOnly,omitempty"` +} + +type WCOWMappedVirtualDisk struct { + ContainerPath string `json:"ContainerPath,omitempty"` + Lun int32 `json:"Lun,omitempty"` +} + +type LCOWMappedDirectory struct { + MountPath string `json:"MountPath,omitempty"` + Port int32 `json:"Port,omitempty"` + ShareName string `json:"ShareName,omitempty"` // If empty not using ANames (not currently supported) + ReadOnly bool `json:"ReadOnly,omitempty"` +} + +// Read-only layers over VPMem +type LCOWMappedVPMemDevice struct { + DeviceNumber uint32 `json:"DeviceNumber,omitempty"` + MountPath string `json:"MountPath,omitempty"` // /tmp/pN +} + +type LCOWNetworkAdapter struct { + NamespaceID string `json:",omitempty"` + ID string `json:",omitempty"` + MacAddress string `json:",omitempty"` + IPAddress string `json:",omitempty"` + PrefixLength uint8 `json:",omitempty"` + GatewayAddress string `json:",omitempty"` + DNSSuffix string `json:",omitempty"` + DNSServerList string `json:",omitempty"` + EnableLowMetric bool `json:",omitempty"` + EncapOverhead uint16 `json:",omitempty"` +} + +type ResourceType string + +const ( + // These are constants for v2 schema modify guest requests. + ResourceTypeMappedDirectory ResourceType = "MappedDirectory" + ResourceTypeMappedVirtualDisk ResourceType = "MappedVirtualDisk" + ResourceTypeNetwork ResourceType = "Network" + ResourceTypeNetworkNamespace ResourceType = "NetworkNamespace" + ResourceTypeCombinedLayers ResourceType = "CombinedLayers" + ResourceTypeVPMemDevice ResourceType = "VPMemDevice" +) + +// GuestRequest is for modify commands passed to the guest. +type GuestRequest struct { + RequestType string `json:"RequestType,omitempty"` + ResourceType ResourceType `json:"ResourceType,omitempty"` + Settings interface{} `json:"Settings,omitempty"` +} + +type NetworkModifyRequest struct { + AdapterId string `json:"AdapterId,omitempty"` + RequestType string `json:"RequestType,omitempty"` + Settings interface{} `json:"Settings,omitempty"` +} + +type RS4NetworkModifyRequest struct { + AdapterInstanceId string `json:"AdapterInstanceId,omitempty"` + RequestType string `json:"RequestType,omitempty"` + Settings interface{} `json:"Settings,omitempty"` +} + +// SignalProcessOptions is the options passed to either WCOW or LCOW +// to signal a given process. +type SignalProcessOptions struct { + Signal int `json:,omitempty` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/guid/guid.go b/vendor/github.com/Microsoft/hcsshim/internal/guid/guid.go new file mode 100644 index 000000000000..e9e45c0306dc --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/guid/guid.go @@ -0,0 +1,69 @@ +package guid + +import ( + "crypto/rand" + "encoding/json" + "fmt" + "io" + "strconv" + "strings" +) + +var _ = (json.Marshaler)(&GUID{}) +var _ = (json.Unmarshaler)(&GUID{}) + +type GUID [16]byte + +func New() GUID { + g := GUID{} + _, err := io.ReadFull(rand.Reader, g[:]) + if err != nil { + panic(err) + } + return g +} + +func (g GUID) String() string { + return fmt.Sprintf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x-%02x", g[3], g[2], g[1], g[0], g[5], g[4], g[7], g[6], g[8:10], g[10:]) +} + +func FromString(s string) GUID { + if len(s) != 36 { + panic(fmt.Sprintf("invalid GUID length: %d", len(s))) + } + if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' { + panic("invalid GUID format") + } + indexOrder := [16]int{ + 0, 2, 4, 6, + 9, 11, + 14, 16, + 19, 21, + 24, 26, 28, 30, 32, 34, + } + byteOrder := [16]int{ + 3, 2, 1, 0, + 5, 4, + 7, 6, + 8, 9, + 10, 11, 12, 13, 14, 15, + } + var g GUID + for i, x := range indexOrder { + b, err := strconv.ParseInt(s[x:x+2], 16, 16) + if err != nil { + panic(err) + } + g[byteOrder[i]] = byte(b) + } + return g +} + +func (g GUID) MarshalJSON() ([]byte, error) { + return json.Marshal(g.String()) +} + +func (g *GUID) UnmarshalJSON(data []byte) error { + *g = FromString(strings.Trim(string(data), "\"")) + return nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/callback.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/callback.go new file mode 100644 index 000000000000..f9a922a4bb95 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/callback.go @@ -0,0 +1,104 @@ +package hcs + +import ( + "sync" + "syscall" + + "github.com/Microsoft/hcsshim/internal/interop" + "github.com/sirupsen/logrus" +) + +var ( + nextCallback uintptr + callbackMap = map[uintptr]*notifcationWatcherContext{} + callbackMapLock = sync.RWMutex{} + + notificationWatcherCallback = syscall.NewCallback(notificationWatcher) + + // Notifications for HCS_SYSTEM handles + hcsNotificationSystemExited hcsNotification = 0x00000001 + hcsNotificationSystemCreateCompleted hcsNotification = 0x00000002 + hcsNotificationSystemStartCompleted hcsNotification = 0x00000003 + hcsNotificationSystemPauseCompleted hcsNotification = 0x00000004 + hcsNotificationSystemResumeCompleted hcsNotification = 0x00000005 + hcsNotificationSystemCrashReport hcsNotification = 0x00000006 + hcsNotificationSystemSiloJobCreated hcsNotification = 0x00000007 + hcsNotificationSystemSaveCompleted hcsNotification = 0x00000008 + hcsNotificationSystemRdpEnhancedModeStateChanged hcsNotification = 0x00000009 + hcsNotificationSystemShutdownFailed hcsNotification = 0x0000000A + hcsNotificationSystemGetPropertiesCompleted hcsNotification = 0x0000000B + hcsNotificationSystemModifyCompleted hcsNotification = 0x0000000C + hcsNotificationSystemCrashInitiated hcsNotification = 0x0000000D + hcsNotificationSystemGuestConnectionClosed hcsNotification = 0x0000000E + + // Notifications for HCS_PROCESS handles + hcsNotificationProcessExited hcsNotification = 0x00010000 + + // Common notifications + hcsNotificationInvalid hcsNotification = 0x00000000 + hcsNotificationServiceDisconnect hcsNotification = 0x01000000 +) + +type hcsNotification uint32 +type notificationChannel chan error + +type notifcationWatcherContext struct { + channels notificationChannels + handle hcsCallback +} + +type notificationChannels map[hcsNotification]notificationChannel + +func newChannels() notificationChannels { + channels := make(notificationChannels) + + channels[hcsNotificationSystemExited] = make(notificationChannel, 1) + channels[hcsNotificationSystemCreateCompleted] = make(notificationChannel, 1) + channels[hcsNotificationSystemStartCompleted] = make(notificationChannel, 1) + channels[hcsNotificationSystemPauseCompleted] = make(notificationChannel, 1) + channels[hcsNotificationSystemResumeCompleted] = make(notificationChannel, 1) + channels[hcsNotificationProcessExited] = make(notificationChannel, 1) + channels[hcsNotificationServiceDisconnect] = make(notificationChannel, 1) + channels[hcsNotificationSystemCrashReport] = make(notificationChannel, 1) + channels[hcsNotificationSystemSiloJobCreated] = make(notificationChannel, 1) + channels[hcsNotificationSystemSaveCompleted] = make(notificationChannel, 1) + channels[hcsNotificationSystemRdpEnhancedModeStateChanged] = make(notificationChannel, 1) + channels[hcsNotificationSystemShutdownFailed] = make(notificationChannel, 1) + channels[hcsNotificationSystemGetPropertiesCompleted] = make(notificationChannel, 1) + channels[hcsNotificationSystemModifyCompleted] = make(notificationChannel, 1) + channels[hcsNotificationSystemCrashInitiated] = make(notificationChannel, 1) + channels[hcsNotificationSystemGuestConnectionClosed] = make(notificationChannel, 1) + + return channels +} + +func closeChannels(channels notificationChannels) { + for _, c := range channels { + close(c) + } +} + +func notificationWatcher(notificationType hcsNotification, callbackNumber uintptr, notificationStatus uintptr, notificationData *uint16) uintptr { + var result error + if int32(notificationStatus) < 0 { + result = interop.Win32FromHresult(notificationStatus) + } + + callbackMapLock.RLock() + context := callbackMap[callbackNumber] + callbackMapLock.RUnlock() + + if context == nil { + return 0 + } + + if channel, ok := context.channels[notificationType]; ok { + channel <- result + } else { + logrus.WithFields(logrus.Fields{ + "notification-type": notificationType, + }).Warn("Received a callback of an unsupported type") + } + + return 0 +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/cgo.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/cgo.go new file mode 100644 index 000000000000..3669c34aa2cc --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/cgo.go @@ -0,0 +1,7 @@ +package hcs + +import "C" + +// This import is needed to make the library compile as CGO because HCSSHIM +// only works with CGO due to callbacks from HCS comming back from a C thread +// which is not supported without CGO. See https://github.com/golang/go/issues/10973 diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/errors.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/errors.go new file mode 100644 index 000000000000..079b565353fa --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/errors.go @@ -0,0 +1,287 @@ +package hcs + +import ( + "encoding/json" + "errors" + "fmt" + "syscall" + + "github.com/Microsoft/hcsshim/internal/interop" + "github.com/Microsoft/hcsshim/internal/logfields" + "github.com/sirupsen/logrus" +) + +var ( + // ErrComputeSystemDoesNotExist is an error encountered when the container being operated on no longer exists + ErrComputeSystemDoesNotExist = syscall.Errno(0xc037010e) + + // ErrElementNotFound is an error encountered when the object being referenced does not exist + ErrElementNotFound = syscall.Errno(0x490) + + // ErrElementNotFound is an error encountered when the object being referenced does not exist + ErrNotSupported = syscall.Errno(0x32) + + // ErrInvalidData is an error encountered when the request being sent to hcs is invalid/unsupported + // decimal -2147024883 / hex 0x8007000d + ErrInvalidData = syscall.Errno(0xd) + + // ErrHandleClose is an error encountered when the handle generating the notification being waited on has been closed + ErrHandleClose = errors.New("hcsshim: the handle generating this notification has been closed") + + // ErrAlreadyClosed is an error encountered when using a handle that has been closed by the Close method + ErrAlreadyClosed = errors.New("hcsshim: the handle has already been closed") + + // ErrInvalidNotificationType is an error encountered when an invalid notification type is used + ErrInvalidNotificationType = errors.New("hcsshim: invalid notification type") + + // ErrInvalidProcessState is an error encountered when the process is not in a valid state for the requested operation + ErrInvalidProcessState = errors.New("the process is in an invalid state for the attempted operation") + + // ErrTimeout is an error encountered when waiting on a notification times out + ErrTimeout = errors.New("hcsshim: timeout waiting for notification") + + // ErrUnexpectedContainerExit is the error encountered when a container exits while waiting for + // a different expected notification + ErrUnexpectedContainerExit = errors.New("unexpected container exit") + + // ErrUnexpectedProcessAbort is the error encountered when communication with the compute service + // is lost while waiting for a notification + ErrUnexpectedProcessAbort = errors.New("lost communication with compute service") + + // ErrUnexpectedValue is an error encountered when hcs returns an invalid value + ErrUnexpectedValue = errors.New("unexpected value returned from hcs") + + // ErrVmcomputeAlreadyStopped is an error encountered when a shutdown or terminate request is made on a stopped container + ErrVmcomputeAlreadyStopped = syscall.Errno(0xc0370110) + + // ErrVmcomputeOperationPending is an error encountered when the operation is being completed asynchronously + ErrVmcomputeOperationPending = syscall.Errno(0xC0370103) + + // ErrVmcomputeOperationInvalidState is an error encountered when the compute system is not in a valid state for the requested operation + ErrVmcomputeOperationInvalidState = syscall.Errno(0xc0370105) + + // ErrProcNotFound is an error encountered when the the process cannot be found + ErrProcNotFound = syscall.Errno(0x7f) + + // ErrVmcomputeOperationAccessIsDenied is an error which can be encountered when enumerating compute systems in RS1/RS2 + // builds when the underlying silo might be in the process of terminating. HCS was fixed in RS3. + ErrVmcomputeOperationAccessIsDenied = syscall.Errno(0x5) + + // ErrVmcomputeInvalidJSON is an error encountered when the compute system does not support/understand the messages sent by management + ErrVmcomputeInvalidJSON = syscall.Errno(0xc037010d) + + // ErrVmcomputeUnknownMessage is an error encountered guest compute system doesn't support the message + ErrVmcomputeUnknownMessage = syscall.Errno(0xc037010b) + + // ErrVmcomputeUnexpectedExit is an error encountered when the compute system terminates unexpectedly + ErrVmcomputeUnexpectedExit = syscall.Errno(0xC0370106) + + // ErrNotSupported is an error encountered when hcs doesn't support the request + ErrPlatformNotSupported = errors.New("unsupported platform request") +) + +type ErrorEvent struct { + Message string `json:"Message,omitempty"` // Fully formated error message + StackTrace string `json:"StackTrace,omitempty"` // Stack trace in string form + Provider string `json:"Provider,omitempty"` + EventID uint16 `json:"EventId,omitempty"` + Flags uint32 `json:"Flags,omitempty"` + Source string `json:"Source,omitempty"` + //Data []EventData `json:"Data,omitempty"` // Omit this as HCS doesn't encode this well. It's more confusing to include. It is however logged in debug mode (see processHcsResult function) +} + +type hcsResult struct { + Error int32 + ErrorMessage string + ErrorEvents []ErrorEvent `json:"ErrorEvents,omitempty"` +} + +func (ev *ErrorEvent) String() string { + evs := "[Event Detail: " + ev.Message + if ev.StackTrace != "" { + evs += " Stack Trace: " + ev.StackTrace + } + if ev.Provider != "" { + evs += " Provider: " + ev.Provider + } + if ev.EventID != 0 { + evs = fmt.Sprintf("%s EventID: %d", evs, ev.EventID) + } + if ev.Flags != 0 { + evs = fmt.Sprintf("%s flags: %d", evs, ev.Flags) + } + if ev.Source != "" { + evs += " Source: " + ev.Source + } + evs += "]" + return evs +} + +func processHcsResult(resultp *uint16) []ErrorEvent { + if resultp != nil { + resultj := interop.ConvertAndFreeCoTaskMemString(resultp) + logrus.WithField(logfields.JSON, resultj). + Debug("HCS Result") + result := &hcsResult{} + if err := json.Unmarshal([]byte(resultj), result); err != nil { + logrus.WithFields(logrus.Fields{ + logfields.JSON: resultj, + logrus.ErrorKey: err, + }).Warning("Could not unmarshal HCS result") + return nil + } + return result.ErrorEvents + } + return nil +} + +type HcsError struct { + Op string + Err error + Events []ErrorEvent +} + +func (e *HcsError) Error() string { + s := e.Op + ": " + e.Err.Error() + for _, ev := range e.Events { + s += "\n" + ev.String() + } + return s +} + +// ProcessError is an error encountered in HCS during an operation on a Process object +type ProcessError struct { + SystemID string + Pid int + Op string + Err error + Events []ErrorEvent +} + +// SystemError is an error encountered in HCS during an operation on a Container object +type SystemError struct { + ID string + Op string + Err error + Extra string + Events []ErrorEvent +} + +func (e *SystemError) Error() string { + s := e.Op + " " + e.ID + ": " + e.Err.Error() + for _, ev := range e.Events { + s += "\n" + ev.String() + } + if e.Extra != "" { + s += "\n(extra info: " + e.Extra + ")" + } + return s +} + +func makeSystemError(system *System, op string, extra string, err error, events []ErrorEvent) error { + // Don't double wrap errors + if _, ok := err.(*SystemError); ok { + return err + } + return &SystemError{ + ID: system.ID(), + Op: op, + Extra: extra, + Err: err, + Events: events, + } +} + +func (e *ProcessError) Error() string { + s := fmt.Sprintf("%s %s:%d: %s", e.Op, e.SystemID, e.Pid, e.Err.Error()) + for _, ev := range e.Events { + s += "\n" + ev.String() + } + return s +} + +func makeProcessError(process *Process, op string, err error, events []ErrorEvent) error { + // Don't double wrap errors + if _, ok := err.(*ProcessError); ok { + return err + } + return &ProcessError{ + Pid: process.Pid(), + SystemID: process.SystemID(), + Op: op, + Err: err, + Events: events, + } +} + +// IsNotExist checks if an error is caused by the Container or Process not existing. +// Note: Currently, ErrElementNotFound can mean that a Process has either +// already exited, or does not exist. Both IsAlreadyStopped and IsNotExist +// will currently return true when the error is ErrElementNotFound or ErrProcNotFound. +func IsNotExist(err error) bool { + err = getInnerError(err) + return err == ErrComputeSystemDoesNotExist || + err == ErrElementNotFound || + err == ErrProcNotFound +} + +// IsAlreadyClosed checks if an error is caused by the Container or Process having been +// already closed by a call to the Close() method. +func IsAlreadyClosed(err error) bool { + err = getInnerError(err) + return err == ErrAlreadyClosed +} + +// IsPending returns a boolean indicating whether the error is that +// the requested operation is being completed in the background. +func IsPending(err error) bool { + err = getInnerError(err) + return err == ErrVmcomputeOperationPending +} + +// IsTimeout returns a boolean indicating whether the error is caused by +// a timeout waiting for the operation to complete. +func IsTimeout(err error) bool { + err = getInnerError(err) + return err == ErrTimeout +} + +// IsAlreadyStopped returns a boolean indicating whether the error is caused by +// a Container or Process being already stopped. +// Note: Currently, ErrElementNotFound can mean that a Process has either +// already exited, or does not exist. Both IsAlreadyStopped and IsNotExist +// will currently return true when the error is ErrElementNotFound or ErrProcNotFound. +func IsAlreadyStopped(err error) bool { + err = getInnerError(err) + return err == ErrVmcomputeAlreadyStopped || + err == ErrElementNotFound || + err == ErrProcNotFound +} + +// IsNotSupported returns a boolean indicating whether the error is caused by +// unsupported platform requests +// Note: Currently Unsupported platform requests can be mean either +// ErrVmcomputeInvalidJSON, ErrInvalidData, ErrNotSupported or ErrVmcomputeUnknownMessage +// is thrown from the Platform +func IsNotSupported(err error) bool { + err = getInnerError(err) + // If Platform doesn't recognize or support the request sent, below errors are seen + return err == ErrVmcomputeInvalidJSON || + err == ErrInvalidData || + err == ErrNotSupported || + err == ErrVmcomputeUnknownMessage +} + +func getInnerError(err error) error { + switch pe := err.(type) { + case nil: + return nil + case *HcsError: + err = pe.Err + case *SystemError: + err = pe.Err + case *ProcessError: + err = pe.Err + } + return err +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/hcs.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/hcs.go new file mode 100644 index 000000000000..b0d49cbcf157 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/hcs.go @@ -0,0 +1,48 @@ +// Shim for the Host Compute Service (HCS) to manage Windows Server +// containers and Hyper-V containers. + +package hcs + +import ( + "syscall" +) + +//go:generate go run ../../mksyscall_windows.go -output zsyscall_windows.go hcs.go + +//sys hcsEnumerateComputeSystems(query string, computeSystems **uint16, result **uint16) (hr error) = vmcompute.HcsEnumerateComputeSystems? +//sys hcsCreateComputeSystem(id string, configuration string, identity syscall.Handle, computeSystem *hcsSystem, result **uint16) (hr error) = vmcompute.HcsCreateComputeSystem? +//sys hcsOpenComputeSystem(id string, computeSystem *hcsSystem, result **uint16) (hr error) = vmcompute.HcsOpenComputeSystem? +//sys hcsCloseComputeSystem(computeSystem hcsSystem) (hr error) = vmcompute.HcsCloseComputeSystem? +//sys hcsStartComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsStartComputeSystem? +//sys hcsShutdownComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsShutdownComputeSystem? +//sys hcsTerminateComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsTerminateComputeSystem? +//sys hcsPauseComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsPauseComputeSystem? +//sys hcsResumeComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsResumeComputeSystem? +//sys hcsGetComputeSystemProperties(computeSystem hcsSystem, propertyQuery string, properties **uint16, result **uint16) (hr error) = vmcompute.HcsGetComputeSystemProperties? +//sys hcsModifyComputeSystem(computeSystem hcsSystem, configuration string, result **uint16) (hr error) = vmcompute.HcsModifyComputeSystem? +//sys hcsRegisterComputeSystemCallback(computeSystem hcsSystem, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) = vmcompute.HcsRegisterComputeSystemCallback? +//sys hcsUnregisterComputeSystemCallback(callbackHandle hcsCallback) (hr error) = vmcompute.HcsUnregisterComputeSystemCallback? + +//sys hcsCreateProcess(computeSystem hcsSystem, processParameters string, processInformation *hcsProcessInformation, process *hcsProcess, result **uint16) (hr error) = vmcompute.HcsCreateProcess? +//sys hcsOpenProcess(computeSystem hcsSystem, pid uint32, process *hcsProcess, result **uint16) (hr error) = vmcompute.HcsOpenProcess? +//sys hcsCloseProcess(process hcsProcess) (hr error) = vmcompute.HcsCloseProcess? +//sys hcsTerminateProcess(process hcsProcess, result **uint16) (hr error) = vmcompute.HcsTerminateProcess? +//sys hcsSignalProcess(process hcsProcess, options string, result **uint16) (hr error) = vmcompute.HcsTerminateProcess? +//sys hcsGetProcessInfo(process hcsProcess, processInformation *hcsProcessInformation, result **uint16) (hr error) = vmcompute.HcsGetProcessInfo? +//sys hcsGetProcessProperties(process hcsProcess, processProperties **uint16, result **uint16) (hr error) = vmcompute.HcsGetProcessProperties? +//sys hcsModifyProcess(process hcsProcess, settings string, result **uint16) (hr error) = vmcompute.HcsModifyProcess? +//sys hcsGetServiceProperties(propertyQuery string, properties **uint16, result **uint16) (hr error) = vmcompute.HcsGetServiceProperties? +//sys hcsRegisterProcessCallback(process hcsProcess, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) = vmcompute.HcsRegisterProcessCallback? +//sys hcsUnregisterProcessCallback(callbackHandle hcsCallback) (hr error) = vmcompute.HcsUnregisterProcessCallback? + +type hcsSystem syscall.Handle +type hcsProcess syscall.Handle +type hcsCallback syscall.Handle + +type hcsProcessInformation struct { + ProcessId uint32 + Reserved uint32 + StdInput syscall.Handle + StdOutput syscall.Handle + StdError syscall.Handle +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/log.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/log.go new file mode 100644 index 000000000000..6d03b17a224c --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/log.go @@ -0,0 +1,20 @@ +package hcs + +import "github.com/sirupsen/logrus" + +func logOperationBegin(ctx logrus.Fields, msg string) { + logrus.WithFields(ctx).Debug(msg) +} + +func logOperationEnd(ctx logrus.Fields, msg string, err error) { + // Copy the log and fields first. + log := logrus.WithFields(ctx) + if err == nil { + log.Debug(msg) + } else { + // Edit only the copied field data to avoid race conditions on the + // write. + log.Data[logrus.ErrorKey] = err + log.Error(msg) + } +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go new file mode 100644 index 000000000000..41e20bbf9922 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go @@ -0,0 +1,459 @@ +package hcs + +import ( + "encoding/json" + "io" + "sync" + "syscall" + "time" + + "github.com/Microsoft/hcsshim/internal/guestrequest" + "github.com/Microsoft/hcsshim/internal/interop" + "github.com/Microsoft/hcsshim/internal/logfields" + "github.com/sirupsen/logrus" +) + +// ContainerError is an error encountered in HCS +type Process struct { + handleLock sync.RWMutex + handle hcsProcess + processID int + system *System + cachedPipes *cachedPipes + callbackNumber uintptr + + logctx logrus.Fields +} + +func newProcess(process hcsProcess, processID int, computeSystem *System) *Process { + return &Process{ + handle: process, + processID: processID, + system: computeSystem, + logctx: logrus.Fields{ + logfields.ContainerID: computeSystem.ID(), + logfields.ProcessID: processID, + }, + } +} + +type cachedPipes struct { + stdIn syscall.Handle + stdOut syscall.Handle + stdErr syscall.Handle +} + +type processModifyRequest struct { + Operation string + ConsoleSize *consoleSize `json:",omitempty"` + CloseHandle *closeHandle `json:",omitempty"` +} + +type consoleSize struct { + Height uint16 + Width uint16 +} + +type closeHandle struct { + Handle string +} + +type ProcessStatus struct { + ProcessID uint32 + Exited bool + ExitCode uint32 + LastWaitResult int32 +} + +const ( + stdIn string = "StdIn" + stdOut string = "StdOut" + stdErr string = "StdErr" +) + +const ( + modifyConsoleSize string = "ConsoleSize" + modifyCloseHandle string = "CloseHandle" +) + +// Pid returns the process ID of the process within the container. +func (process *Process) Pid() int { + return process.processID +} + +// SystemID returns the ID of the process's compute system. +func (process *Process) SystemID() string { + return process.system.ID() +} + +func (process *Process) logOperationBegin(operation string) { + logOperationBegin( + process.logctx, + operation+" - Begin Operation") +} + +func (process *Process) logOperationEnd(operation string, err error) { + var result string + if err == nil { + result = "Success" + } else { + result = "Error" + } + + logOperationEnd( + process.logctx, + operation+" - End Operation - "+result, + err) +} + +// Signal signals the process with `options`. +func (process *Process) Signal(options guestrequest.SignalProcessOptions) (err error) { + process.handleLock.RLock() + defer process.handleLock.RUnlock() + + operation := "hcsshim::Process::Signal" + process.logOperationBegin(operation) + defer func() { process.logOperationEnd(operation, err) }() + + if process.handle == 0 { + return makeProcessError(process, operation, ErrAlreadyClosed, nil) + } + + optionsb, err := json.Marshal(options) + if err != nil { + return err + } + + optionsStr := string(optionsb) + + var resultp *uint16 + syscallWatcher(process.logctx, func() { + err = hcsSignalProcess(process.handle, optionsStr, &resultp) + }) + events := processHcsResult(resultp) + if err != nil { + return makeProcessError(process, operation, err, events) + } + + return nil +} + +// Kill signals the process to terminate but does not wait for it to finish terminating. +func (process *Process) Kill() (err error) { + process.handleLock.RLock() + defer process.handleLock.RUnlock() + + operation := "hcsshim::Process::Kill" + process.logOperationBegin(operation) + defer func() { process.logOperationEnd(operation, err) }() + + if process.handle == 0 { + return makeProcessError(process, operation, ErrAlreadyClosed, nil) + } + + var resultp *uint16 + syscallWatcher(process.logctx, func() { + err = hcsTerminateProcess(process.handle, &resultp) + }) + events := processHcsResult(resultp) + if err != nil { + return makeProcessError(process, operation, err, events) + } + + return nil +} + +// Wait waits for the process to exit. +func (process *Process) Wait() (err error) { + operation := "hcsshim::Process::Wait" + process.logOperationBegin(operation) + defer func() { process.logOperationEnd(operation, err) }() + + err = waitForNotification(process.callbackNumber, hcsNotificationProcessExited, nil) + if err != nil { + return makeProcessError(process, operation, err, nil) + } + + return nil +} + +// WaitTimeout waits for the process to exit or the duration to elapse. It returns +// false if timeout occurs. +func (process *Process) WaitTimeout(timeout time.Duration) (err error) { + operation := "hcssshim::Process::WaitTimeout" + process.logOperationBegin(operation) + defer func() { process.logOperationEnd(operation, err) }() + + err = waitForNotification(process.callbackNumber, hcsNotificationProcessExited, &timeout) + if err != nil { + return makeProcessError(process, operation, err, nil) + } + + return nil +} + +// ResizeConsole resizes the console of the process. +func (process *Process) ResizeConsole(width, height uint16) (err error) { + process.handleLock.RLock() + defer process.handleLock.RUnlock() + + operation := "hcsshim::Process::ResizeConsole" + process.logOperationBegin(operation) + defer func() { process.logOperationEnd(operation, err) }() + + if process.handle == 0 { + return makeProcessError(process, operation, ErrAlreadyClosed, nil) + } + + modifyRequest := processModifyRequest{ + Operation: modifyConsoleSize, + ConsoleSize: &consoleSize{ + Height: height, + Width: width, + }, + } + + modifyRequestb, err := json.Marshal(modifyRequest) + if err != nil { + return err + } + + modifyRequestStr := string(modifyRequestb) + + var resultp *uint16 + err = hcsModifyProcess(process.handle, modifyRequestStr, &resultp) + events := processHcsResult(resultp) + if err != nil { + return makeProcessError(process, operation, err, events) + } + + return nil +} + +func (process *Process) Properties() (_ *ProcessStatus, err error) { + process.handleLock.RLock() + defer process.handleLock.RUnlock() + + operation := "hcsshim::Process::Properties" + process.logOperationBegin(operation) + defer func() { process.logOperationEnd(operation, err) }() + + if process.handle == 0 { + return nil, makeProcessError(process, operation, ErrAlreadyClosed, nil) + } + + var ( + resultp *uint16 + propertiesp *uint16 + ) + syscallWatcher(process.logctx, func() { + err = hcsGetProcessProperties(process.handle, &propertiesp, &resultp) + }) + events := processHcsResult(resultp) + if err != nil { + return nil, makeProcessError(process, operation, err, events) + } + + if propertiesp == nil { + return nil, ErrUnexpectedValue + } + propertiesRaw := interop.ConvertAndFreeCoTaskMemBytes(propertiesp) + + properties := &ProcessStatus{} + if err := json.Unmarshal(propertiesRaw, properties); err != nil { + return nil, makeProcessError(process, operation, err, nil) + } + + return properties, nil +} + +// ExitCode returns the exit code of the process. The process must have +// already terminated. +func (process *Process) ExitCode() (_ int, err error) { + operation := "hcsshim::Process::ExitCode" + process.logOperationBegin(operation) + defer func() { process.logOperationEnd(operation, err) }() + + properties, err := process.Properties() + if err != nil { + return 0, makeProcessError(process, operation, err, nil) + } + + if properties.Exited == false { + return 0, makeProcessError(process, operation, ErrInvalidProcessState, nil) + } + + if properties.LastWaitResult != 0 { + return 0, makeProcessError(process, operation, syscall.Errno(properties.LastWaitResult), nil) + } + + return int(properties.ExitCode), nil +} + +// Stdio returns the stdin, stdout, and stderr pipes, respectively. Closing +// these pipes does not close the underlying pipes; it should be possible to +// call this multiple times to get multiple interfaces. +func (process *Process) Stdio() (_ io.WriteCloser, _ io.ReadCloser, _ io.ReadCloser, err error) { + process.handleLock.RLock() + defer process.handleLock.RUnlock() + + operation := "hcsshim::Process::Stdio" + process.logOperationBegin(operation) + defer func() { process.logOperationEnd(operation, err) }() + + if process.handle == 0 { + return nil, nil, nil, makeProcessError(process, operation, ErrAlreadyClosed, nil) + } + + var stdIn, stdOut, stdErr syscall.Handle + + if process.cachedPipes == nil { + var ( + processInfo hcsProcessInformation + resultp *uint16 + ) + err = hcsGetProcessInfo(process.handle, &processInfo, &resultp) + events := processHcsResult(resultp) + if err != nil { + return nil, nil, nil, makeProcessError(process, operation, err, events) + } + + stdIn, stdOut, stdErr = processInfo.StdInput, processInfo.StdOutput, processInfo.StdError + } else { + // Use cached pipes + stdIn, stdOut, stdErr = process.cachedPipes.stdIn, process.cachedPipes.stdOut, process.cachedPipes.stdErr + + // Invalidate the cache + process.cachedPipes = nil + } + + pipes, err := makeOpenFiles([]syscall.Handle{stdIn, stdOut, stdErr}) + if err != nil { + return nil, nil, nil, makeProcessError(process, operation, err, nil) + } + + return pipes[0], pipes[1], pipes[2], nil +} + +// CloseStdin closes the write side of the stdin pipe so that the process is +// notified on the read side that there is no more data in stdin. +func (process *Process) CloseStdin() (err error) { + process.handleLock.RLock() + defer process.handleLock.RUnlock() + + operation := "hcsshim::Process::CloseStdin" + process.logOperationBegin(operation) + defer func() { process.logOperationEnd(operation, err) }() + + if process.handle == 0 { + return makeProcessError(process, operation, ErrAlreadyClosed, nil) + } + + modifyRequest := processModifyRequest{ + Operation: modifyCloseHandle, + CloseHandle: &closeHandle{ + Handle: stdIn, + }, + } + + modifyRequestb, err := json.Marshal(modifyRequest) + if err != nil { + return err + } + + modifyRequestStr := string(modifyRequestb) + + var resultp *uint16 + err = hcsModifyProcess(process.handle, modifyRequestStr, &resultp) + events := processHcsResult(resultp) + if err != nil { + return makeProcessError(process, operation, err, events) + } + + return nil +} + +// Close cleans up any state associated with the process but does not kill +// or wait on it. +func (process *Process) Close() (err error) { + process.handleLock.Lock() + defer process.handleLock.Unlock() + + operation := "hcsshim::Process::Close" + process.logOperationBegin(operation) + defer func() { process.logOperationEnd(operation, err) }() + + // Don't double free this + if process.handle == 0 { + return nil + } + + if err = process.unregisterCallback(); err != nil { + return makeProcessError(process, operation, err, nil) + } + + if err = hcsCloseProcess(process.handle); err != nil { + return makeProcessError(process, operation, err, nil) + } + + process.handle = 0 + + return nil +} + +func (process *Process) registerCallback() error { + context := ¬ifcationWatcherContext{ + channels: newChannels(), + } + + callbackMapLock.Lock() + callbackNumber := nextCallback + nextCallback++ + callbackMap[callbackNumber] = context + callbackMapLock.Unlock() + + var callbackHandle hcsCallback + err := hcsRegisterProcessCallback(process.handle, notificationWatcherCallback, callbackNumber, &callbackHandle) + if err != nil { + return err + } + context.handle = callbackHandle + process.callbackNumber = callbackNumber + + return nil +} + +func (process *Process) unregisterCallback() error { + callbackNumber := process.callbackNumber + + callbackMapLock.RLock() + context := callbackMap[callbackNumber] + callbackMapLock.RUnlock() + + if context == nil { + return nil + } + + handle := context.handle + + if handle == 0 { + return nil + } + + // hcsUnregisterProcessCallback has its own syncronization + // to wait for all callbacks to complete. We must NOT hold the callbackMapLock. + err := hcsUnregisterProcessCallback(handle) + if err != nil { + return err + } + + closeChannels(context.channels) + + callbackMapLock.Lock() + callbackMap[callbackNumber] = nil + callbackMapLock.Unlock() + + handle = 0 + + return nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/system.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/system.go new file mode 100644 index 000000000000..20b242524d04 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/system.go @@ -0,0 +1,685 @@ +package hcs + +import ( + "encoding/json" + "os" + "strconv" + "sync" + "syscall" + "time" + + "github.com/Microsoft/hcsshim/internal/interop" + "github.com/Microsoft/hcsshim/internal/logfields" + "github.com/Microsoft/hcsshim/internal/schema1" + "github.com/Microsoft/hcsshim/internal/timeout" + "github.com/sirupsen/logrus" +) + +// currentContainerStarts is used to limit the number of concurrent container +// starts. +var currentContainerStarts containerStarts + +type containerStarts struct { + maxParallel int + inProgress int + sync.Mutex +} + +func init() { + mpsS := os.Getenv("HCSSHIM_MAX_PARALLEL_START") + if len(mpsS) > 0 { + mpsI, err := strconv.Atoi(mpsS) + if err != nil || mpsI < 0 { + return + } + currentContainerStarts.maxParallel = mpsI + } +} + +type System struct { + handleLock sync.RWMutex + handle hcsSystem + id string + callbackNumber uintptr + + logctx logrus.Fields +} + +func newSystem(id string) *System { + return &System{ + id: id, + logctx: logrus.Fields{ + logfields.ContainerID: id, + }, + } +} + +func (computeSystem *System) logOperationBegin(operation string) { + logOperationBegin( + computeSystem.logctx, + operation+" - Begin Operation") +} + +func (computeSystem *System) logOperationEnd(operation string, err error) { + var result string + if err == nil { + result = "Success" + } else { + result = "Error" + } + + logOperationEnd( + computeSystem.logctx, + operation+" - End Operation - "+result, + err) +} + +// CreateComputeSystem creates a new compute system with the given configuration but does not start it. +func CreateComputeSystem(id string, hcsDocumentInterface interface{}) (_ *System, err error) { + operation := "hcsshim::CreateComputeSystem" + + computeSystem := newSystem(id) + computeSystem.logOperationBegin(operation) + defer func() { computeSystem.logOperationEnd(operation, err) }() + + hcsDocumentB, err := json.Marshal(hcsDocumentInterface) + if err != nil { + return nil, err + } + + hcsDocument := string(hcsDocumentB) + + logrus.WithFields(computeSystem.logctx). + WithField(logfields.JSON, hcsDocument). + Debug("HCS ComputeSystem Document") + + var ( + resultp *uint16 + identity syscall.Handle + createError error + ) + syscallWatcher(computeSystem.logctx, func() { + createError = hcsCreateComputeSystem(id, hcsDocument, identity, &computeSystem.handle, &resultp) + }) + + if createError == nil || IsPending(createError) { + if err = computeSystem.registerCallback(); err != nil { + // Terminate the compute system if it still exists. We're okay to + // ignore a failure here. + computeSystem.Terminate() + return nil, makeSystemError(computeSystem, operation, "", err, nil) + } + } + + events, err := processAsyncHcsResult(createError, resultp, computeSystem.callbackNumber, hcsNotificationSystemCreateCompleted, &timeout.SystemCreate) + if err != nil { + if err == ErrTimeout { + // Terminate the compute system if it still exists. We're okay to + // ignore a failure here. + computeSystem.Terminate() + } + return nil, makeSystemError(computeSystem, operation, hcsDocument, err, events) + } + + return computeSystem, nil +} + +// OpenComputeSystem opens an existing compute system by ID. +func OpenComputeSystem(id string) (_ *System, err error) { + operation := "hcsshim::OpenComputeSystem" + + computeSystem := newSystem(id) + computeSystem.logOperationBegin(operation) + defer func() { + if IsNotExist(err) { + computeSystem.logOperationEnd(operation, nil) + } else { + computeSystem.logOperationEnd(operation, err) + } + }() + + var ( + handle hcsSystem + resultp *uint16 + ) + err = hcsOpenComputeSystem(id, &handle, &resultp) + events := processHcsResult(resultp) + if err != nil { + return nil, makeSystemError(computeSystem, operation, "", err, events) + } + + computeSystem.handle = handle + + if err = computeSystem.registerCallback(); err != nil { + return nil, makeSystemError(computeSystem, operation, "", err, nil) + } + + return computeSystem, nil +} + +// GetComputeSystems gets a list of the compute systems on the system that match the query +func GetComputeSystems(q schema1.ComputeSystemQuery) (_ []schema1.ContainerProperties, err error) { + operation := "hcsshim::GetComputeSystems" + fields := logrus.Fields{} + logOperationBegin( + fields, + operation+" - Begin Operation") + + defer func() { + var result string + if err == nil { + result = "Success" + } else { + result = "Error" + } + + logOperationEnd( + fields, + operation+" - End Operation - "+result, + err) + }() + + queryb, err := json.Marshal(q) + if err != nil { + return nil, err + } + + query := string(queryb) + + logrus.WithFields(fields). + WithField(logfields.JSON, query). + Debug("HCS ComputeSystem Query") + + var ( + resultp *uint16 + computeSystemsp *uint16 + ) + + syscallWatcher(fields, func() { + err = hcsEnumerateComputeSystems(query, &computeSystemsp, &resultp) + }) + events := processHcsResult(resultp) + if err != nil { + return nil, &HcsError{Op: operation, Err: err, Events: events} + } + + if computeSystemsp == nil { + return nil, ErrUnexpectedValue + } + computeSystemsRaw := interop.ConvertAndFreeCoTaskMemBytes(computeSystemsp) + computeSystems := []schema1.ContainerProperties{} + if err = json.Unmarshal(computeSystemsRaw, &computeSystems); err != nil { + return nil, err + } + + return computeSystems, nil +} + +// Start synchronously starts the computeSystem. +func (computeSystem *System) Start() (err error) { + computeSystem.handleLock.RLock() + defer computeSystem.handleLock.RUnlock() + + operation := "hcsshim::ComputeSystem::Start" + computeSystem.logOperationBegin(operation) + defer func() { computeSystem.logOperationEnd(operation, err) }() + + if computeSystem.handle == 0 { + return makeSystemError(computeSystem, "Start", "", ErrAlreadyClosed, nil) + } + + // This is a very simple backoff-retry loop to limit the number + // of parallel container starts if environment variable + // HCSSHIM_MAX_PARALLEL_START is set to a positive integer. + // It should generally only be used as a workaround to various + // platform issues that exist between RS1 and RS4 as of Aug 2018 + if currentContainerStarts.maxParallel > 0 { + for { + currentContainerStarts.Lock() + if currentContainerStarts.inProgress < currentContainerStarts.maxParallel { + currentContainerStarts.inProgress++ + currentContainerStarts.Unlock() + break + } + if currentContainerStarts.inProgress == currentContainerStarts.maxParallel { + currentContainerStarts.Unlock() + time.Sleep(100 * time.Millisecond) + } + } + // Make sure we decrement the count when we are done. + defer func() { + currentContainerStarts.Lock() + currentContainerStarts.inProgress-- + currentContainerStarts.Unlock() + }() + } + + var resultp *uint16 + syscallWatcher(computeSystem.logctx, func() { + err = hcsStartComputeSystem(computeSystem.handle, "", &resultp) + }) + events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemStartCompleted, &timeout.SystemStart) + if err != nil { + return makeSystemError(computeSystem, "Start", "", err, events) + } + + return nil +} + +// ID returns the compute system's identifier. +func (computeSystem *System) ID() string { + return computeSystem.id +} + +// Shutdown requests a compute system shutdown, if IsPending() on the error returned is true, +// it may not actually be shut down until Wait() succeeds. +func (computeSystem *System) Shutdown() (err error) { + computeSystem.handleLock.RLock() + defer computeSystem.handleLock.RUnlock() + + operation := "hcsshim::ComputeSystem::Shutdown" + computeSystem.logOperationBegin(operation) + defer func() { + if IsAlreadyStopped(err) { + computeSystem.logOperationEnd(operation, nil) + } else { + computeSystem.logOperationEnd(operation, err) + } + }() + + if computeSystem.handle == 0 { + return makeSystemError(computeSystem, "Shutdown", "", ErrAlreadyClosed, nil) + } + + var resultp *uint16 + syscallWatcher(computeSystem.logctx, func() { + err = hcsShutdownComputeSystem(computeSystem.handle, "", &resultp) + }) + events := processHcsResult(resultp) + if err != nil { + return makeSystemError(computeSystem, "Shutdown", "", err, events) + } + + return nil +} + +// Terminate requests a compute system terminate, if IsPending() on the error returned is true, +// it may not actually be shut down until Wait() succeeds. +func (computeSystem *System) Terminate() (err error) { + computeSystem.handleLock.RLock() + defer computeSystem.handleLock.RUnlock() + + operation := "hcsshim::ComputeSystem::Terminate" + computeSystem.logOperationBegin(operation) + defer func() { + if IsPending(err) { + computeSystem.logOperationEnd(operation, nil) + } else { + computeSystem.logOperationEnd(operation, err) + } + }() + + if computeSystem.handle == 0 { + return makeSystemError(computeSystem, "Terminate", "", ErrAlreadyClosed, nil) + } + + var resultp *uint16 + syscallWatcher(computeSystem.logctx, func() { + err = hcsTerminateComputeSystem(computeSystem.handle, "", &resultp) + }) + events := processHcsResult(resultp) + if err != nil && err != ErrVmcomputeAlreadyStopped { + return makeSystemError(computeSystem, "Terminate", "", err, events) + } + + return nil +} + +// Wait synchronously waits for the compute system to shutdown or terminate. +func (computeSystem *System) Wait() (err error) { + operation := "hcsshim::ComputeSystem::Wait" + computeSystem.logOperationBegin(operation) + defer func() { computeSystem.logOperationEnd(operation, err) }() + + err = waitForNotification(computeSystem.callbackNumber, hcsNotificationSystemExited, nil) + if err != nil { + return makeSystemError(computeSystem, "Wait", "", err, nil) + } + + return nil +} + +// WaitExpectedError synchronously waits for the compute system to shutdown or +// terminate, and ignores the passed error if it occurs. +func (computeSystem *System) WaitExpectedError(expected error) (err error) { + operation := "hcsshim::ComputeSystem::WaitExpectedError" + computeSystem.logOperationBegin(operation) + defer func() { computeSystem.logOperationEnd(operation, err) }() + + err = waitForNotification(computeSystem.callbackNumber, hcsNotificationSystemExited, nil) + if err != nil && getInnerError(err) != expected { + return makeSystemError(computeSystem, "WaitExpectedError", "", err, nil) + } + + return nil +} + +// WaitTimeout synchronously waits for the compute system to terminate or the duration to elapse. +// If the timeout expires, IsTimeout(err) == true +func (computeSystem *System) WaitTimeout(timeout time.Duration) (err error) { + operation := "hcsshim::ComputeSystem::WaitTimeout" + computeSystem.logOperationBegin(operation) + defer func() { computeSystem.logOperationEnd(operation, err) }() + + err = waitForNotification(computeSystem.callbackNumber, hcsNotificationSystemExited, &timeout) + if err != nil { + return makeSystemError(computeSystem, "WaitTimeout", "", err, nil) + } + + return nil +} + +func (computeSystem *System) Properties(types ...schema1.PropertyType) (_ *schema1.ContainerProperties, err error) { + computeSystem.handleLock.RLock() + defer computeSystem.handleLock.RUnlock() + + operation := "hcsshim::ComputeSystem::Properties" + computeSystem.logOperationBegin(operation) + defer func() { computeSystem.logOperationEnd(operation, err) }() + + queryj, err := json.Marshal(schema1.PropertyQuery{types}) + if err != nil { + return nil, makeSystemError(computeSystem, "Properties", "", err, nil) + } + + logrus.WithFields(computeSystem.logctx). + WithField(logfields.JSON, queryj). + Debug("HCS ComputeSystem Properties Query") + + var resultp, propertiesp *uint16 + syscallWatcher(computeSystem.logctx, func() { + err = hcsGetComputeSystemProperties(computeSystem.handle, string(queryj), &propertiesp, &resultp) + }) + events := processHcsResult(resultp) + if err != nil { + return nil, makeSystemError(computeSystem, "Properties", "", err, events) + } + + if propertiesp == nil { + return nil, ErrUnexpectedValue + } + propertiesRaw := interop.ConvertAndFreeCoTaskMemBytes(propertiesp) + properties := &schema1.ContainerProperties{} + if err := json.Unmarshal(propertiesRaw, properties); err != nil { + return nil, makeSystemError(computeSystem, "Properties", "", err, nil) + } + + return properties, nil +} + +// Pause pauses the execution of the computeSystem. This feature is not enabled in TP5. +func (computeSystem *System) Pause() (err error) { + computeSystem.handleLock.RLock() + defer computeSystem.handleLock.RUnlock() + + operation := "hcsshim::ComputeSystem::Pause" + computeSystem.logOperationBegin(operation) + defer func() { computeSystem.logOperationEnd(operation, err) }() + + if computeSystem.handle == 0 { + return makeSystemError(computeSystem, "Pause", "", ErrAlreadyClosed, nil) + } + + var resultp *uint16 + syscallWatcher(computeSystem.logctx, func() { + err = hcsPauseComputeSystem(computeSystem.handle, "", &resultp) + }) + events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemPauseCompleted, &timeout.SystemPause) + if err != nil { + return makeSystemError(computeSystem, "Pause", "", err, events) + } + + return nil +} + +// Resume resumes the execution of the computeSystem. This feature is not enabled in TP5. +func (computeSystem *System) Resume() (err error) { + computeSystem.handleLock.RLock() + defer computeSystem.handleLock.RUnlock() + + operation := "hcsshim::ComputeSystem::Resume" + computeSystem.logOperationBegin(operation) + defer func() { computeSystem.logOperationEnd(operation, err) }() + + if computeSystem.handle == 0 { + return makeSystemError(computeSystem, "Resume", "", ErrAlreadyClosed, nil) + } + + var resultp *uint16 + syscallWatcher(computeSystem.logctx, func() { + err = hcsResumeComputeSystem(computeSystem.handle, "", &resultp) + }) + events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemResumeCompleted, &timeout.SystemResume) + if err != nil { + return makeSystemError(computeSystem, "Resume", "", err, events) + } + + return nil +} + +// CreateProcess launches a new process within the computeSystem. +func (computeSystem *System) CreateProcess(c interface{}) (_ *Process, err error) { + computeSystem.handleLock.RLock() + defer computeSystem.handleLock.RUnlock() + + operation := "hcsshim::ComputeSystem::CreateProcess" + computeSystem.logOperationBegin(operation) + defer func() { computeSystem.logOperationEnd(operation, err) }() + + var ( + processInfo hcsProcessInformation + processHandle hcsProcess + resultp *uint16 + ) + + if computeSystem.handle == 0 { + return nil, makeSystemError(computeSystem, "CreateProcess", "", ErrAlreadyClosed, nil) + } + + configurationb, err := json.Marshal(c) + if err != nil { + return nil, makeSystemError(computeSystem, "CreateProcess", "", err, nil) + } + + configuration := string(configurationb) + + logrus.WithFields(computeSystem.logctx). + WithField(logfields.JSON, configuration). + Debug("HCS ComputeSystem Process Document") + + syscallWatcher(computeSystem.logctx, func() { + err = hcsCreateProcess(computeSystem.handle, configuration, &processInfo, &processHandle, &resultp) + }) + events := processHcsResult(resultp) + if err != nil { + return nil, makeSystemError(computeSystem, "CreateProcess", configuration, err, events) + } + + logrus.WithFields(computeSystem.logctx). + WithField(logfields.ProcessID, processInfo.ProcessId). + Debug("HCS ComputeSystem CreateProcess PID") + + process := newProcess(processHandle, int(processInfo.ProcessId), computeSystem) + process.cachedPipes = &cachedPipes{ + stdIn: processInfo.StdInput, + stdOut: processInfo.StdOutput, + stdErr: processInfo.StdError, + } + + if err = process.registerCallback(); err != nil { + return nil, makeSystemError(computeSystem, "CreateProcess", "", err, nil) + } + + return process, nil +} + +// OpenProcess gets an interface to an existing process within the computeSystem. +func (computeSystem *System) OpenProcess(pid int) (_ *Process, err error) { + computeSystem.handleLock.RLock() + defer computeSystem.handleLock.RUnlock() + + // Add PID for the context of this operation + computeSystem.logctx[logfields.ProcessID] = pid + defer delete(computeSystem.logctx, logfields.ProcessID) + + operation := "hcsshim::ComputeSystem::OpenProcess" + computeSystem.logOperationBegin(operation) + defer func() { computeSystem.logOperationEnd(operation, err) }() + + var ( + processHandle hcsProcess + resultp *uint16 + ) + + if computeSystem.handle == 0 { + return nil, makeSystemError(computeSystem, "OpenProcess", "", ErrAlreadyClosed, nil) + } + + syscallWatcher(computeSystem.logctx, func() { + err = hcsOpenProcess(computeSystem.handle, uint32(pid), &processHandle, &resultp) + }) + events := processHcsResult(resultp) + if err != nil { + return nil, makeSystemError(computeSystem, "OpenProcess", "", err, events) + } + + process := newProcess(processHandle, pid, computeSystem) + if err = process.registerCallback(); err != nil { + return nil, makeSystemError(computeSystem, "OpenProcess", "", err, nil) + } + + return process, nil +} + +// Close cleans up any state associated with the compute system but does not terminate or wait for it. +func (computeSystem *System) Close() (err error) { + computeSystem.handleLock.Lock() + defer computeSystem.handleLock.Unlock() + + operation := "hcsshim::ComputeSystem::Close" + computeSystem.logOperationBegin(operation) + defer func() { computeSystem.logOperationEnd(operation, err) }() + + // Don't double free this + if computeSystem.handle == 0 { + return nil + } + + if err = computeSystem.unregisterCallback(); err != nil { + return makeSystemError(computeSystem, "Close", "", err, nil) + } + + syscallWatcher(computeSystem.logctx, func() { + err = hcsCloseComputeSystem(computeSystem.handle) + }) + if err != nil { + return makeSystemError(computeSystem, "Close", "", err, nil) + } + + computeSystem.handle = 0 + + return nil +} + +func (computeSystem *System) registerCallback() error { + context := ¬ifcationWatcherContext{ + channels: newChannels(), + } + + callbackMapLock.Lock() + callbackNumber := nextCallback + nextCallback++ + callbackMap[callbackNumber] = context + callbackMapLock.Unlock() + + var callbackHandle hcsCallback + err := hcsRegisterComputeSystemCallback(computeSystem.handle, notificationWatcherCallback, callbackNumber, &callbackHandle) + if err != nil { + return err + } + context.handle = callbackHandle + computeSystem.callbackNumber = callbackNumber + + return nil +} + +func (computeSystem *System) unregisterCallback() error { + callbackNumber := computeSystem.callbackNumber + + callbackMapLock.RLock() + context := callbackMap[callbackNumber] + callbackMapLock.RUnlock() + + if context == nil { + return nil + } + + handle := context.handle + + if handle == 0 { + return nil + } + + // hcsUnregisterComputeSystemCallback has its own syncronization + // to wait for all callbacks to complete. We must NOT hold the callbackMapLock. + err := hcsUnregisterComputeSystemCallback(handle) + if err != nil { + return err + } + + closeChannels(context.channels) + + callbackMapLock.Lock() + callbackMap[callbackNumber] = nil + callbackMapLock.Unlock() + + handle = 0 + + return nil +} + +// Modify the System by sending a request to HCS +func (computeSystem *System) Modify(config interface{}) (err error) { + computeSystem.handleLock.RLock() + defer computeSystem.handleLock.RUnlock() + + operation := "hcsshim::ComputeSystem::Modify" + computeSystem.logOperationBegin(operation) + defer func() { computeSystem.logOperationEnd(operation, err) }() + + if computeSystem.handle == 0 { + return makeSystemError(computeSystem, "Modify", "", ErrAlreadyClosed, nil) + } + + requestJSON, err := json.Marshal(config) + if err != nil { + return err + } + + requestString := string(requestJSON) + + logrus.WithFields(computeSystem.logctx). + WithField(logfields.JSON, requestString). + Debug("HCS ComputeSystem Modify Document") + + var resultp *uint16 + syscallWatcher(computeSystem.logctx, func() { + err = hcsModifyComputeSystem(computeSystem.handle, requestString, &resultp) + }) + events := processHcsResult(resultp) + if err != nil { + return makeSystemError(computeSystem, "Modify", requestString, err, events) + } + + return nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/utils.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/utils.go new file mode 100644 index 000000000000..a638677ed5af --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/utils.go @@ -0,0 +1,33 @@ +package hcs + +import ( + "io" + "syscall" + + "github.com/Microsoft/go-winio" +) + +// makeOpenFiles calls winio.MakeOpenFile for each handle in a slice but closes all the handles +// if there is an error. +func makeOpenFiles(hs []syscall.Handle) (_ []io.ReadWriteCloser, err error) { + fs := make([]io.ReadWriteCloser, len(hs)) + for i, h := range hs { + if h != syscall.Handle(0) { + if err == nil { + fs[i], err = winio.MakeOpenFile(h) + } + if err != nil { + syscall.Close(h) + } + } + } + if err != nil { + for _, f := range fs { + if f != nil { + f.Close() + } + } + return nil, err + } + return fs, nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/waithelper.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/waithelper.go new file mode 100644 index 000000000000..91e212c57482 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/waithelper.go @@ -0,0 +1,63 @@ +package hcs + +import ( + "time" + + "github.com/sirupsen/logrus" +) + +func processAsyncHcsResult(err error, resultp *uint16, callbackNumber uintptr, expectedNotification hcsNotification, timeout *time.Duration) ([]ErrorEvent, error) { + events := processHcsResult(resultp) + if IsPending(err) { + return nil, waitForNotification(callbackNumber, expectedNotification, timeout) + } + + return events, err +} + +func waitForNotification(callbackNumber uintptr, expectedNotification hcsNotification, timeout *time.Duration) error { + callbackMapLock.RLock() + channels := callbackMap[callbackNumber].channels + callbackMapLock.RUnlock() + + expectedChannel := channels[expectedNotification] + if expectedChannel == nil { + logrus.Errorf("unknown notification type in waitForNotification %x", expectedNotification) + return ErrInvalidNotificationType + } + + var c <-chan time.Time + if timeout != nil { + timer := time.NewTimer(*timeout) + c = timer.C + defer timer.Stop() + } + + select { + case err, ok := <-expectedChannel: + if !ok { + return ErrHandleClose + } + return err + case err, ok := <-channels[hcsNotificationSystemExited]: + if !ok { + return ErrHandleClose + } + // If the expected notification is hcsNotificationSystemExited which of the two selects + // chosen is random. Return the raw error if hcsNotificationSystemExited is expected + if channels[hcsNotificationSystemExited] == expectedChannel { + return err + } + return ErrUnexpectedContainerExit + case _, ok := <-channels[hcsNotificationServiceDisconnect]: + if !ok { + return ErrHandleClose + } + // hcsNotificationServiceDisconnect should never be an expected notification + // it does not need the same handling as hcsNotificationSystemExited + return ErrUnexpectedProcessAbort + case <-c: + return ErrTimeout + } + return nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/watcher.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/watcher.go new file mode 100644 index 000000000000..f85ed31874c8 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/watcher.go @@ -0,0 +1,41 @@ +package hcs + +import ( + "context" + + "github.com/Microsoft/hcsshim/internal/logfields" + "github.com/Microsoft/hcsshim/internal/timeout" + "github.com/sirupsen/logrus" +) + +// syscallWatcher is used as a very simple goroutine around calls into +// the platform. In some cases, we have seen HCS APIs not returning due to +// various bugs, and the goroutine making the syscall ends up not returning, +// prior to its async callback. By spinning up a syscallWatcher, it allows +// us to at least log a warning if a syscall doesn't complete in a reasonable +// amount of time. +// +// Usage is: +// +// syscallWatcher(logContext, func() { +// err = (args...) +// }) +// + +func syscallWatcher(logContext logrus.Fields, syscallLambda func()) { + ctx, cancel := context.WithTimeout(context.Background(), timeout.SyscallWatcher) + defer cancel() + go watchFunc(ctx, logContext) + syscallLambda() +} + +func watchFunc(ctx context.Context, logContext logrus.Fields) { + select { + case <-ctx.Done(): + if ctx.Err() != context.Canceled { + logrus.WithFields(logContext). + WithField(logfields.Timeout, timeout.SyscallWatcher). + Warning("Syscall did not complete within operation timeout. This may indicate a platform issue. If it appears to be making no forward progress, obtain the stacks and see if there is a syscall stuck in the platform API for a significant length of time.") + } + } +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/zsyscall_windows.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/zsyscall_windows.go new file mode 100644 index 000000000000..fcd5cdc87f60 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/zsyscall_windows.go @@ -0,0 +1,533 @@ +// Code generated mksyscall_windows.exe DO NOT EDIT + +package hcs + +import ( + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +var _ unsafe.Pointer + +// Do the interface allocations only once for common +// Errno values. +const ( + errnoERROR_IO_PENDING = 997 +) + +var ( + errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) +) + +// errnoErr returns common boxed Errno values, to prevent +// allocations at runtime. +func errnoErr(e syscall.Errno) error { + switch e { + case 0: + return nil + case errnoERROR_IO_PENDING: + return errERROR_IO_PENDING + } + // TODO: add more here, after collecting data on the common + // error values see on Windows. (perhaps when running + // all.bat?) + return e +} + +var ( + modvmcompute = windows.NewLazySystemDLL("vmcompute.dll") + + procHcsEnumerateComputeSystems = modvmcompute.NewProc("HcsEnumerateComputeSystems") + procHcsCreateComputeSystem = modvmcompute.NewProc("HcsCreateComputeSystem") + procHcsOpenComputeSystem = modvmcompute.NewProc("HcsOpenComputeSystem") + procHcsCloseComputeSystem = modvmcompute.NewProc("HcsCloseComputeSystem") + procHcsStartComputeSystem = modvmcompute.NewProc("HcsStartComputeSystem") + procHcsShutdownComputeSystem = modvmcompute.NewProc("HcsShutdownComputeSystem") + procHcsTerminateComputeSystem = modvmcompute.NewProc("HcsTerminateComputeSystem") + procHcsPauseComputeSystem = modvmcompute.NewProc("HcsPauseComputeSystem") + procHcsResumeComputeSystem = modvmcompute.NewProc("HcsResumeComputeSystem") + procHcsGetComputeSystemProperties = modvmcompute.NewProc("HcsGetComputeSystemProperties") + procHcsModifyComputeSystem = modvmcompute.NewProc("HcsModifyComputeSystem") + procHcsRegisterComputeSystemCallback = modvmcompute.NewProc("HcsRegisterComputeSystemCallback") + procHcsUnregisterComputeSystemCallback = modvmcompute.NewProc("HcsUnregisterComputeSystemCallback") + procHcsCreateProcess = modvmcompute.NewProc("HcsCreateProcess") + procHcsOpenProcess = modvmcompute.NewProc("HcsOpenProcess") + procHcsCloseProcess = modvmcompute.NewProc("HcsCloseProcess") + procHcsTerminateProcess = modvmcompute.NewProc("HcsTerminateProcess") + + procHcsGetProcessInfo = modvmcompute.NewProc("HcsGetProcessInfo") + procHcsGetProcessProperties = modvmcompute.NewProc("HcsGetProcessProperties") + procHcsModifyProcess = modvmcompute.NewProc("HcsModifyProcess") + procHcsGetServiceProperties = modvmcompute.NewProc("HcsGetServiceProperties") + procHcsRegisterProcessCallback = modvmcompute.NewProc("HcsRegisterProcessCallback") + procHcsUnregisterProcessCallback = modvmcompute.NewProc("HcsUnregisterProcessCallback") +) + +func hcsEnumerateComputeSystems(query string, computeSystems **uint16, result **uint16) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(query) + if hr != nil { + return + } + return _hcsEnumerateComputeSystems(_p0, computeSystems, result) +} + +func _hcsEnumerateComputeSystems(query *uint16, computeSystems **uint16, result **uint16) (hr error) { + if hr = procHcsEnumerateComputeSystems.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procHcsEnumerateComputeSystems.Addr(), 3, uintptr(unsafe.Pointer(query)), uintptr(unsafe.Pointer(computeSystems)), uintptr(unsafe.Pointer(result))) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func hcsCreateComputeSystem(id string, configuration string, identity syscall.Handle, computeSystem *hcsSystem, result **uint16) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + var _p1 *uint16 + _p1, hr = syscall.UTF16PtrFromString(configuration) + if hr != nil { + return + } + return _hcsCreateComputeSystem(_p0, _p1, identity, computeSystem, result) +} + +func _hcsCreateComputeSystem(id *uint16, configuration *uint16, identity syscall.Handle, computeSystem *hcsSystem, result **uint16) (hr error) { + if hr = procHcsCreateComputeSystem.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall6(procHcsCreateComputeSystem.Addr(), 5, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(configuration)), uintptr(identity), uintptr(unsafe.Pointer(computeSystem)), uintptr(unsafe.Pointer(result)), 0) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func hcsOpenComputeSystem(id string, computeSystem *hcsSystem, result **uint16) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + return _hcsOpenComputeSystem(_p0, computeSystem, result) +} + +func _hcsOpenComputeSystem(id *uint16, computeSystem *hcsSystem, result **uint16) (hr error) { + if hr = procHcsOpenComputeSystem.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procHcsOpenComputeSystem.Addr(), 3, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(computeSystem)), uintptr(unsafe.Pointer(result))) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func hcsCloseComputeSystem(computeSystem hcsSystem) (hr error) { + if hr = procHcsCloseComputeSystem.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procHcsCloseComputeSystem.Addr(), 1, uintptr(computeSystem), 0, 0) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func hcsStartComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(options) + if hr != nil { + return + } + return _hcsStartComputeSystem(computeSystem, _p0, result) +} + +func _hcsStartComputeSystem(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) { + if hr = procHcsStartComputeSystem.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procHcsStartComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result))) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func hcsShutdownComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(options) + if hr != nil { + return + } + return _hcsShutdownComputeSystem(computeSystem, _p0, result) +} + +func _hcsShutdownComputeSystem(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) { + if hr = procHcsShutdownComputeSystem.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procHcsShutdownComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result))) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func hcsTerminateComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(options) + if hr != nil { + return + } + return _hcsTerminateComputeSystem(computeSystem, _p0, result) +} + +func _hcsTerminateComputeSystem(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) { + if hr = procHcsTerminateComputeSystem.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procHcsTerminateComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result))) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func hcsPauseComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(options) + if hr != nil { + return + } + return _hcsPauseComputeSystem(computeSystem, _p0, result) +} + +func _hcsPauseComputeSystem(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) { + if hr = procHcsPauseComputeSystem.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procHcsPauseComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result))) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func hcsResumeComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(options) + if hr != nil { + return + } + return _hcsResumeComputeSystem(computeSystem, _p0, result) +} + +func _hcsResumeComputeSystem(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) { + if hr = procHcsResumeComputeSystem.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procHcsResumeComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result))) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func hcsGetComputeSystemProperties(computeSystem hcsSystem, propertyQuery string, properties **uint16, result **uint16) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(propertyQuery) + if hr != nil { + return + } + return _hcsGetComputeSystemProperties(computeSystem, _p0, properties, result) +} + +func _hcsGetComputeSystemProperties(computeSystem hcsSystem, propertyQuery *uint16, properties **uint16, result **uint16) (hr error) { + if hr = procHcsGetComputeSystemProperties.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall6(procHcsGetComputeSystemProperties.Addr(), 4, uintptr(computeSystem), uintptr(unsafe.Pointer(propertyQuery)), uintptr(unsafe.Pointer(properties)), uintptr(unsafe.Pointer(result)), 0, 0) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func hcsModifyComputeSystem(computeSystem hcsSystem, configuration string, result **uint16) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(configuration) + if hr != nil { + return + } + return _hcsModifyComputeSystem(computeSystem, _p0, result) +} + +func _hcsModifyComputeSystem(computeSystem hcsSystem, configuration *uint16, result **uint16) (hr error) { + if hr = procHcsModifyComputeSystem.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procHcsModifyComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(configuration)), uintptr(unsafe.Pointer(result))) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func hcsRegisterComputeSystemCallback(computeSystem hcsSystem, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) { + if hr = procHcsRegisterComputeSystemCallback.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall6(procHcsRegisterComputeSystemCallback.Addr(), 4, uintptr(computeSystem), uintptr(callback), uintptr(context), uintptr(unsafe.Pointer(callbackHandle)), 0, 0) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func hcsUnregisterComputeSystemCallback(callbackHandle hcsCallback) (hr error) { + if hr = procHcsUnregisterComputeSystemCallback.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procHcsUnregisterComputeSystemCallback.Addr(), 1, uintptr(callbackHandle), 0, 0) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func hcsCreateProcess(computeSystem hcsSystem, processParameters string, processInformation *hcsProcessInformation, process *hcsProcess, result **uint16) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(processParameters) + if hr != nil { + return + } + return _hcsCreateProcess(computeSystem, _p0, processInformation, process, result) +} + +func _hcsCreateProcess(computeSystem hcsSystem, processParameters *uint16, processInformation *hcsProcessInformation, process *hcsProcess, result **uint16) (hr error) { + if hr = procHcsCreateProcess.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall6(procHcsCreateProcess.Addr(), 5, uintptr(computeSystem), uintptr(unsafe.Pointer(processParameters)), uintptr(unsafe.Pointer(processInformation)), uintptr(unsafe.Pointer(process)), uintptr(unsafe.Pointer(result)), 0) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func hcsOpenProcess(computeSystem hcsSystem, pid uint32, process *hcsProcess, result **uint16) (hr error) { + if hr = procHcsOpenProcess.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall6(procHcsOpenProcess.Addr(), 4, uintptr(computeSystem), uintptr(pid), uintptr(unsafe.Pointer(process)), uintptr(unsafe.Pointer(result)), 0, 0) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func hcsCloseProcess(process hcsProcess) (hr error) { + if hr = procHcsCloseProcess.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procHcsCloseProcess.Addr(), 1, uintptr(process), 0, 0) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func hcsTerminateProcess(process hcsProcess, result **uint16) (hr error) { + if hr = procHcsTerminateProcess.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procHcsTerminateProcess.Addr(), 2, uintptr(process), uintptr(unsafe.Pointer(result)), 0) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func hcsSignalProcess(process hcsProcess, options string, result **uint16) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(options) + if hr != nil { + return + } + return _hcsSignalProcess(process, _p0, result) +} + +func _hcsSignalProcess(process hcsProcess, options *uint16, result **uint16) (hr error) { + if hr = procHcsTerminateProcess.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procHcsTerminateProcess.Addr(), 3, uintptr(process), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result))) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func hcsGetProcessInfo(process hcsProcess, processInformation *hcsProcessInformation, result **uint16) (hr error) { + if hr = procHcsGetProcessInfo.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procHcsGetProcessInfo.Addr(), 3, uintptr(process), uintptr(unsafe.Pointer(processInformation)), uintptr(unsafe.Pointer(result))) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func hcsGetProcessProperties(process hcsProcess, processProperties **uint16, result **uint16) (hr error) { + if hr = procHcsGetProcessProperties.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procHcsGetProcessProperties.Addr(), 3, uintptr(process), uintptr(unsafe.Pointer(processProperties)), uintptr(unsafe.Pointer(result))) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func hcsModifyProcess(process hcsProcess, settings string, result **uint16) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(settings) + if hr != nil { + return + } + return _hcsModifyProcess(process, _p0, result) +} + +func _hcsModifyProcess(process hcsProcess, settings *uint16, result **uint16) (hr error) { + if hr = procHcsModifyProcess.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procHcsModifyProcess.Addr(), 3, uintptr(process), uintptr(unsafe.Pointer(settings)), uintptr(unsafe.Pointer(result))) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func hcsGetServiceProperties(propertyQuery string, properties **uint16, result **uint16) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(propertyQuery) + if hr != nil { + return + } + return _hcsGetServiceProperties(_p0, properties, result) +} + +func _hcsGetServiceProperties(propertyQuery *uint16, properties **uint16, result **uint16) (hr error) { + if hr = procHcsGetServiceProperties.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procHcsGetServiceProperties.Addr(), 3, uintptr(unsafe.Pointer(propertyQuery)), uintptr(unsafe.Pointer(properties)), uintptr(unsafe.Pointer(result))) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func hcsRegisterProcessCallback(process hcsProcess, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) { + if hr = procHcsRegisterProcessCallback.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall6(procHcsRegisterProcessCallback.Addr(), 4, uintptr(process), uintptr(callback), uintptr(context), uintptr(unsafe.Pointer(callbackHandle)), 0, 0) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func hcsUnregisterProcessCallback(callbackHandle hcsCallback) (hr error) { + if hr = procHcsUnregisterProcessCallback.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procHcsUnregisterProcessCallback.Addr(), 1, uintptr(callbackHandle), 0, 0) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcserror/hcserror.go b/vendor/github.com/Microsoft/hcsshim/internal/hcserror/hcserror.go new file mode 100644 index 000000000000..921c2c8556c2 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/hcserror/hcserror.go @@ -0,0 +1,47 @@ +package hcserror + +import ( + "fmt" + "syscall" +) + +const ERROR_GEN_FAILURE = syscall.Errno(31) + +type HcsError struct { + title string + rest string + Err error +} + +func (e *HcsError) Error() string { + s := e.title + if len(s) > 0 && s[len(s)-1] != ' ' { + s += " " + } + s += fmt.Sprintf("failed in Win32: %s (0x%x)", e.Err, Win32FromError(e.Err)) + if e.rest != "" { + if e.rest[0] != ' ' { + s += " " + } + s += e.rest + } + return s +} + +func New(err error, title, rest string) error { + // Pass through DLL errors directly since they do not originate from HCS. + if _, ok := err.(*syscall.DLLError); ok { + return err + } + return &HcsError{title, rest, err} +} + +func Win32FromError(err error) uint32 { + if herr, ok := err.(*HcsError); ok { + return Win32FromError(herr.Err) + } + if code, ok := err.(syscall.Errno); ok { + return uint32(code) + } + return uint32(ERROR_GEN_FAILURE) +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hns/hns.go b/vendor/github.com/Microsoft/hcsshim/internal/hns/hns.go new file mode 100644 index 000000000000..b2e475f53c66 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/hns/hns.go @@ -0,0 +1,23 @@ +package hns + +import "fmt" + +//go:generate go run ../../mksyscall_windows.go -output zsyscall_windows.go hns.go + +//sys _hnsCall(method string, path string, object string, response **uint16) (hr error) = vmcompute.HNSCall? + +type EndpointNotFoundError struct { + EndpointName string +} + +func (e EndpointNotFoundError) Error() string { + return fmt.Sprintf("Endpoint %s not found", e.EndpointName) +} + +type NetworkNotFoundError struct { + NetworkName string +} + +func (e NetworkNotFoundError) Error() string { + return fmt.Sprintf("Network %s not found", e.NetworkName) +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hns/hnsendpoint.go b/vendor/github.com/Microsoft/hcsshim/internal/hns/hnsendpoint.go new file mode 100644 index 000000000000..59ec7004c3d8 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/hns/hnsendpoint.go @@ -0,0 +1,262 @@ +package hns + +import ( + "encoding/json" + "net" + + "github.com/sirupsen/logrus" +) + +// HNSEndpoint represents a network endpoint in HNS +type HNSEndpoint struct { + Id string `json:"ID,omitempty"` + Name string `json:",omitempty"` + VirtualNetwork string `json:",omitempty"` + VirtualNetworkName string `json:",omitempty"` + Policies []json.RawMessage `json:",omitempty"` + MacAddress string `json:",omitempty"` + IPAddress net.IP `json:",omitempty"` + DNSSuffix string `json:",omitempty"` + DNSServerList string `json:",omitempty"` + GatewayAddress string `json:",omitempty"` + EnableInternalDNS bool `json:",omitempty"` + DisableICC bool `json:",omitempty"` + PrefixLength uint8 `json:",omitempty"` + IsRemoteEndpoint bool `json:",omitempty"` + EnableLowMetric bool `json:",omitempty"` + Namespace *Namespace `json:",omitempty"` + EncapOverhead uint16 `json:",omitempty"` +} + +//SystemType represents the type of the system on which actions are done +type SystemType string + +// SystemType const +const ( + ContainerType SystemType = "Container" + VirtualMachineType SystemType = "VirtualMachine" + HostType SystemType = "Host" +) + +// EndpointAttachDetachRequest is the structure used to send request to the container to modify the system +// Supported resource types are Network and Request Types are Add/Remove +type EndpointAttachDetachRequest struct { + ContainerID string `json:"ContainerId,omitempty"` + SystemType SystemType `json:"SystemType"` + CompartmentID uint16 `json:"CompartmentId,omitempty"` + VirtualNICName string `json:"VirtualNicName,omitempty"` +} + +// EndpointResquestResponse is object to get the endpoint request response +type EndpointResquestResponse struct { + Success bool + Error string +} + +// HNSEndpointRequest makes a HNS call to modify/query a network endpoint +func HNSEndpointRequest(method, path, request string) (*HNSEndpoint, error) { + endpoint := &HNSEndpoint{} + err := hnsCall(method, "/endpoints/"+path, request, &endpoint) + if err != nil { + return nil, err + } + + return endpoint, nil +} + +// HNSListEndpointRequest makes a HNS call to query the list of available endpoints +func HNSListEndpointRequest() ([]HNSEndpoint, error) { + var endpoint []HNSEndpoint + err := hnsCall("GET", "/endpoints/", "", &endpoint) + if err != nil { + return nil, err + } + + return endpoint, nil +} + +// GetHNSEndpointByID get the Endpoint by ID +func GetHNSEndpointByID(endpointID string) (*HNSEndpoint, error) { + return HNSEndpointRequest("GET", endpointID, "") +} + +// GetHNSEndpointByName gets the endpoint filtered by Name +func GetHNSEndpointByName(endpointName string) (*HNSEndpoint, error) { + hnsResponse, err := HNSListEndpointRequest() + if err != nil { + return nil, err + } + for _, hnsEndpoint := range hnsResponse { + if hnsEndpoint.Name == endpointName { + return &hnsEndpoint, nil + } + } + return nil, EndpointNotFoundError{EndpointName: endpointName} +} + +// Create Endpoint by sending EndpointRequest to HNS. TODO: Create a separate HNS interface to place all these methods +func (endpoint *HNSEndpoint) Create() (*HNSEndpoint, error) { + operation := "Create" + title := "hcsshim::HNSEndpoint::" + operation + logrus.Debugf(title+" id=%s", endpoint.Id) + + jsonString, err := json.Marshal(endpoint) + if err != nil { + return nil, err + } + return HNSEndpointRequest("POST", "", string(jsonString)) +} + +// Delete Endpoint by sending EndpointRequest to HNS +func (endpoint *HNSEndpoint) Delete() (*HNSEndpoint, error) { + operation := "Delete" + title := "hcsshim::HNSEndpoint::" + operation + logrus.Debugf(title+" id=%s", endpoint.Id) + + return HNSEndpointRequest("DELETE", endpoint.Id, "") +} + +// Update Endpoint +func (endpoint *HNSEndpoint) Update() (*HNSEndpoint, error) { + operation := "Update" + title := "hcsshim::HNSEndpoint::" + operation + logrus.Debugf(title+" id=%s", endpoint.Id) + jsonString, err := json.Marshal(endpoint) + if err != nil { + return nil, err + } + err = hnsCall("POST", "/endpoints/"+endpoint.Id, string(jsonString), &endpoint) + + return endpoint, err +} + +// ApplyACLPolicy applies a set of ACL Policies on the Endpoint +func (endpoint *HNSEndpoint) ApplyACLPolicy(policies ...*ACLPolicy) error { + operation := "ApplyACLPolicy" + title := "hcsshim::HNSEndpoint::" + operation + logrus.Debugf(title+" id=%s", endpoint.Id) + + for _, policy := range policies { + if policy == nil { + continue + } + jsonString, err := json.Marshal(policy) + if err != nil { + return err + } + endpoint.Policies = append(endpoint.Policies, jsonString) + } + + _, err := endpoint.Update() + return err +} + +// ContainerAttach attaches an endpoint to container +func (endpoint *HNSEndpoint) ContainerAttach(containerID string, compartmentID uint16) error { + operation := "ContainerAttach" + title := "hcsshim::HNSEndpoint::" + operation + logrus.Debugf(title+" id=%s", endpoint.Id) + + requestMessage := &EndpointAttachDetachRequest{ + ContainerID: containerID, + CompartmentID: compartmentID, + SystemType: ContainerType, + } + response := &EndpointResquestResponse{} + jsonString, err := json.Marshal(requestMessage) + if err != nil { + return err + } + return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response) +} + +// ContainerDetach detaches an endpoint from container +func (endpoint *HNSEndpoint) ContainerDetach(containerID string) error { + operation := "ContainerDetach" + title := "hcsshim::HNSEndpoint::" + operation + logrus.Debugf(title+" id=%s", endpoint.Id) + + requestMessage := &EndpointAttachDetachRequest{ + ContainerID: containerID, + SystemType: ContainerType, + } + response := &EndpointResquestResponse{} + + jsonString, err := json.Marshal(requestMessage) + if err != nil { + return err + } + return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response) +} + +// HostAttach attaches a nic on the host +func (endpoint *HNSEndpoint) HostAttach(compartmentID uint16) error { + operation := "HostAttach" + title := "hcsshim::HNSEndpoint::" + operation + logrus.Debugf(title+" id=%s", endpoint.Id) + requestMessage := &EndpointAttachDetachRequest{ + CompartmentID: compartmentID, + SystemType: HostType, + } + response := &EndpointResquestResponse{} + + jsonString, err := json.Marshal(requestMessage) + if err != nil { + return err + } + return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response) + +} + +// HostDetach detaches a nic on the host +func (endpoint *HNSEndpoint) HostDetach() error { + operation := "HostDetach" + title := "hcsshim::HNSEndpoint::" + operation + logrus.Debugf(title+" id=%s", endpoint.Id) + requestMessage := &EndpointAttachDetachRequest{ + SystemType: HostType, + } + response := &EndpointResquestResponse{} + + jsonString, err := json.Marshal(requestMessage) + if err != nil { + return err + } + return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response) +} + +// VirtualMachineNICAttach attaches a endpoint to a virtual machine +func (endpoint *HNSEndpoint) VirtualMachineNICAttach(virtualMachineNICName string) error { + operation := "VirtualMachineNicAttach" + title := "hcsshim::HNSEndpoint::" + operation + logrus.Debugf(title+" id=%s", endpoint.Id) + requestMessage := &EndpointAttachDetachRequest{ + VirtualNICName: virtualMachineNICName, + SystemType: VirtualMachineType, + } + response := &EndpointResquestResponse{} + + jsonString, err := json.Marshal(requestMessage) + if err != nil { + return err + } + return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response) +} + +// VirtualMachineNICDetach detaches a endpoint from a virtual machine +func (endpoint *HNSEndpoint) VirtualMachineNICDetach() error { + operation := "VirtualMachineNicDetach" + title := "hcsshim::HNSEndpoint::" + operation + logrus.Debugf(title+" id=%s", endpoint.Id) + + requestMessage := &EndpointAttachDetachRequest{ + SystemType: VirtualMachineType, + } + response := &EndpointResquestResponse{} + + jsonString, err := json.Marshal(requestMessage) + if err != nil { + return err + } + return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response) +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hns/hnsfuncs.go b/vendor/github.com/Microsoft/hcsshim/internal/hns/hnsfuncs.go new file mode 100644 index 000000000000..969d1b263bcb --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/hns/hnsfuncs.go @@ -0,0 +1,42 @@ +package hns + +import ( + "encoding/json" + "fmt" + + "github.com/Microsoft/hcsshim/internal/hcserror" + "github.com/Microsoft/hcsshim/internal/interop" + "github.com/sirupsen/logrus" +) + +func hnsCall(method, path, request string, returnResponse interface{}) error { + var responseBuffer *uint16 + logrus.Debugf("[%s]=>[%s] Request : %s", method, path, request) + + err := _hnsCall(method, path, request, &responseBuffer) + if err != nil { + return hcserror.New(err, "hnsCall ", "") + } + response := interop.ConvertAndFreeCoTaskMemString(responseBuffer) + + hnsresponse := &hnsResponse{} + if err = json.Unmarshal([]byte(response), &hnsresponse); err != nil { + return err + } + + if !hnsresponse.Success { + return fmt.Errorf("HNS failed with error : %s", hnsresponse.Error) + } + + if len(hnsresponse.Output) == 0 { + return nil + } + + logrus.Debugf("Network Response : %s", hnsresponse.Output) + err = json.Unmarshal(hnsresponse.Output, returnResponse) + if err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hns/hnsglobals.go b/vendor/github.com/Microsoft/hcsshim/internal/hns/hnsglobals.go new file mode 100644 index 000000000000..a8d8cc56aea8 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/hns/hnsglobals.go @@ -0,0 +1,28 @@ +package hns + +type HNSGlobals struct { + Version HNSVersion `json:"Version"` +} + +type HNSVersion struct { + Major int `json:"Major"` + Minor int `json:"Minor"` +} + +var ( + HNSVersion1803 = HNSVersion{Major: 7, Minor: 2} +) + +func GetHNSGlobals() (*HNSGlobals, error) { + var version HNSVersion + err := hnsCall("GET", "/globals/version", "", &version) + if err != nil { + return nil, err + } + + globals := &HNSGlobals{ + Version: version, + } + + return globals, nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hns/hnsnetwork.go b/vendor/github.com/Microsoft/hcsshim/internal/hns/hnsnetwork.go new file mode 100644 index 000000000000..7e859de9124b --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/hns/hnsnetwork.go @@ -0,0 +1,141 @@ +package hns + +import ( + "encoding/json" + "net" + + "github.com/sirupsen/logrus" +) + +// Subnet is assoicated with a network and represents a list +// of subnets available to the network +type Subnet struct { + AddressPrefix string `json:",omitempty"` + GatewayAddress string `json:",omitempty"` + Policies []json.RawMessage `json:",omitempty"` +} + +// MacPool is assoicated with a network and represents a list +// of macaddresses available to the network +type MacPool struct { + StartMacAddress string `json:",omitempty"` + EndMacAddress string `json:",omitempty"` +} + +// HNSNetwork represents a network in HNS +type HNSNetwork struct { + Id string `json:"ID,omitempty"` + Name string `json:",omitempty"` + Type string `json:",omitempty"` + NetworkAdapterName string `json:",omitempty"` + SourceMac string `json:",omitempty"` + Policies []json.RawMessage `json:",omitempty"` + MacPools []MacPool `json:",omitempty"` + Subnets []Subnet `json:",omitempty"` + DNSSuffix string `json:",omitempty"` + DNSServerList string `json:",omitempty"` + DNSServerCompartment uint32 `json:",omitempty"` + ManagementIP string `json:",omitempty"` + AutomaticDNS bool `json:",omitempty"` +} + +type hnsNetworkResponse struct { + Success bool + Error string + Output HNSNetwork +} + +type hnsResponse struct { + Success bool + Error string + Output json.RawMessage +} + +// HNSNetworkRequest makes a call into HNS to update/query a single network +func HNSNetworkRequest(method, path, request string) (*HNSNetwork, error) { + var network HNSNetwork + err := hnsCall(method, "/networks/"+path, request, &network) + if err != nil { + return nil, err + } + + return &network, nil +} + +// HNSListNetworkRequest makes a HNS call to query the list of available networks +func HNSListNetworkRequest(method, path, request string) ([]HNSNetwork, error) { + var network []HNSNetwork + err := hnsCall(method, "/networks/"+path, request, &network) + if err != nil { + return nil, err + } + + return network, nil +} + +// GetHNSNetworkByID +func GetHNSNetworkByID(networkID string) (*HNSNetwork, error) { + return HNSNetworkRequest("GET", networkID, "") +} + +// GetHNSNetworkName filtered by Name +func GetHNSNetworkByName(networkName string) (*HNSNetwork, error) { + hsnnetworks, err := HNSListNetworkRequest("GET", "", "") + if err != nil { + return nil, err + } + for _, hnsnetwork := range hsnnetworks { + if hnsnetwork.Name == networkName { + return &hnsnetwork, nil + } + } + return nil, NetworkNotFoundError{NetworkName: networkName} +} + +// Create Network by sending NetworkRequest to HNS. +func (network *HNSNetwork) Create() (*HNSNetwork, error) { + operation := "Create" + title := "hcsshim::HNSNetwork::" + operation + logrus.Debugf(title+" id=%s", network.Id) + + jsonString, err := json.Marshal(network) + if err != nil { + return nil, err + } + return HNSNetworkRequest("POST", "", string(jsonString)) +} + +// Delete Network by sending NetworkRequest to HNS +func (network *HNSNetwork) Delete() (*HNSNetwork, error) { + operation := "Delete" + title := "hcsshim::HNSNetwork::" + operation + logrus.Debugf(title+" id=%s", network.Id) + + return HNSNetworkRequest("DELETE", network.Id, "") +} + +// Creates an endpoint on the Network. +func (network *HNSNetwork) NewEndpoint(ipAddress net.IP, macAddress net.HardwareAddr) *HNSEndpoint { + return &HNSEndpoint{ + VirtualNetwork: network.Id, + IPAddress: ipAddress, + MacAddress: string(macAddress), + } +} + +func (network *HNSNetwork) CreateEndpoint(endpoint *HNSEndpoint) (*HNSEndpoint, error) { + operation := "CreateEndpoint" + title := "hcsshim::HNSNetwork::" + operation + logrus.Debugf(title+" id=%s, endpointId=%s", network.Id, endpoint.Id) + + endpoint.VirtualNetwork = network.Id + return endpoint.Create() +} + +func (network *HNSNetwork) CreateRemoteEndpoint(endpoint *HNSEndpoint) (*HNSEndpoint, error) { + operation := "CreateRemoteEndpoint" + title := "hcsshim::HNSNetwork::" + operation + logrus.Debugf(title+" id=%s", network.Id) + endpoint.IsRemoteEndpoint = true + return network.CreateEndpoint(endpoint) +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hns/hnspolicy.go b/vendor/github.com/Microsoft/hcsshim/internal/hns/hnspolicy.go new file mode 100644 index 000000000000..2318a4fce2b6 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/hns/hnspolicy.go @@ -0,0 +1,98 @@ +package hns + +// Type of Request Support in ModifySystem +type PolicyType string + +// RequestType const +const ( + Nat PolicyType = "NAT" + ACL PolicyType = "ACL" + PA PolicyType = "PA" + VLAN PolicyType = "VLAN" + VSID PolicyType = "VSID" + VNet PolicyType = "VNET" + L2Driver PolicyType = "L2Driver" + Isolation PolicyType = "Isolation" + QOS PolicyType = "QOS" + OutboundNat PolicyType = "OutBoundNAT" + ExternalLoadBalancer PolicyType = "ELB" + Route PolicyType = "ROUTE" +) + +type NatPolicy struct { + Type PolicyType `json:"Type"` + Protocol string + InternalPort uint16 + ExternalPort uint16 +} + +type QosPolicy struct { + Type PolicyType `json:"Type"` + MaximumOutgoingBandwidthInBytes uint64 +} + +type IsolationPolicy struct { + Type PolicyType `json:"Type"` + VLAN uint + VSID uint + InDefaultIsolation bool +} + +type VlanPolicy struct { + Type PolicyType `json:"Type"` + VLAN uint +} + +type VsidPolicy struct { + Type PolicyType `json:"Type"` + VSID uint +} + +type PaPolicy struct { + Type PolicyType `json:"Type"` + PA string `json:"PA"` +} + +type OutboundNatPolicy struct { + Policy + VIP string `json:"VIP,omitempty"` + Exceptions []string `json:"ExceptionList,omitempty"` +} + +type ActionType string +type DirectionType string +type RuleType string + +const ( + Allow ActionType = "Allow" + Block ActionType = "Block" + + In DirectionType = "In" + Out DirectionType = "Out" + + Host RuleType = "Host" + Switch RuleType = "Switch" +) + +type ACLPolicy struct { + Type PolicyType `json:"Type"` + Id string `json:"Id,omitempty"` + Protocol uint16 + Protocols string `json:"Protocols,omitempty"` + InternalPort uint16 + Action ActionType + Direction DirectionType + LocalAddresses string + RemoteAddresses string + LocalPorts string `json:"LocalPorts,omitempty"` + LocalPort uint16 + RemotePorts string `json:"RemotePorts,omitempty"` + RemotePort uint16 + RuleType RuleType `json:"RuleType,omitempty"` + Priority uint16 + ServiceName string +} + +type Policy struct { + Type PolicyType `json:"Type"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hns/hnspolicylist.go b/vendor/github.com/Microsoft/hcsshim/internal/hns/hnspolicylist.go new file mode 100644 index 000000000000..31322a68167c --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/hns/hnspolicylist.go @@ -0,0 +1,201 @@ +package hns + +import ( + "encoding/json" + + "github.com/sirupsen/logrus" +) + +// RoutePolicy is a structure defining schema for Route based Policy +type RoutePolicy struct { + Policy + DestinationPrefix string `json:"DestinationPrefix,omitempty"` + NextHop string `json:"NextHop,omitempty"` + EncapEnabled bool `json:"NeedEncap,omitempty"` +} + +// ELBPolicy is a structure defining schema for ELB LoadBalancing based Policy +type ELBPolicy struct { + LBPolicy + SourceVIP string `json:"SourceVIP,omitempty"` + VIPs []string `json:"VIPs,omitempty"` + ILB bool `json:"ILB,omitempty"` + DSR bool `json:"IsDSR,omitempty"` +} + +// LBPolicy is a structure defining schema for LoadBalancing based Policy +type LBPolicy struct { + Policy + Protocol uint16 `json:"Protocol,omitempty"` + InternalPort uint16 + ExternalPort uint16 +} + +// PolicyList is a structure defining schema for Policy list request +type PolicyList struct { + ID string `json:"ID,omitempty"` + EndpointReferences []string `json:"References,omitempty"` + Policies []json.RawMessage `json:"Policies,omitempty"` +} + +// HNSPolicyListRequest makes a call into HNS to update/query a single network +func HNSPolicyListRequest(method, path, request string) (*PolicyList, error) { + var policy PolicyList + err := hnsCall(method, "/policylists/"+path, request, &policy) + if err != nil { + return nil, err + } + + return &policy, nil +} + +// HNSListPolicyListRequest gets all the policy list +func HNSListPolicyListRequest() ([]PolicyList, error) { + var plist []PolicyList + err := hnsCall("GET", "/policylists/", "", &plist) + if err != nil { + return nil, err + } + + return plist, nil +} + +// PolicyListRequest makes a HNS call to modify/query a network policy list +func PolicyListRequest(method, path, request string) (*PolicyList, error) { + policylist := &PolicyList{} + err := hnsCall(method, "/policylists/"+path, request, &policylist) + if err != nil { + return nil, err + } + + return policylist, nil +} + +// GetPolicyListByID get the policy list by ID +func GetPolicyListByID(policyListID string) (*PolicyList, error) { + return PolicyListRequest("GET", policyListID, "") +} + +// Create PolicyList by sending PolicyListRequest to HNS. +func (policylist *PolicyList) Create() (*PolicyList, error) { + operation := "Create" + title := "hcsshim::PolicyList::" + operation + logrus.Debugf(title+" id=%s", policylist.ID) + jsonString, err := json.Marshal(policylist) + if err != nil { + return nil, err + } + return PolicyListRequest("POST", "", string(jsonString)) +} + +// Delete deletes PolicyList +func (policylist *PolicyList) Delete() (*PolicyList, error) { + operation := "Delete" + title := "hcsshim::PolicyList::" + operation + logrus.Debugf(title+" id=%s", policylist.ID) + + return PolicyListRequest("DELETE", policylist.ID, "") +} + +// AddEndpoint add an endpoint to a Policy List +func (policylist *PolicyList) AddEndpoint(endpoint *HNSEndpoint) (*PolicyList, error) { + operation := "AddEndpoint" + title := "hcsshim::PolicyList::" + operation + logrus.Debugf(title+" id=%s, endpointId:%s", policylist.ID, endpoint.Id) + + _, err := policylist.Delete() + if err != nil { + return nil, err + } + + // Add Endpoint to the Existing List + policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id) + + return policylist.Create() +} + +// RemoveEndpoint removes an endpoint from the Policy List +func (policylist *PolicyList) RemoveEndpoint(endpoint *HNSEndpoint) (*PolicyList, error) { + operation := "RemoveEndpoint" + title := "hcsshim::PolicyList::" + operation + logrus.Debugf(title+" id=%s, endpointId:%s", policylist.ID, endpoint.Id) + + _, err := policylist.Delete() + if err != nil { + return nil, err + } + + elementToRemove := "/endpoints/" + endpoint.Id + + var references []string + + for _, endpointReference := range policylist.EndpointReferences { + if endpointReference == elementToRemove { + continue + } + references = append(references, endpointReference) + } + policylist.EndpointReferences = references + return policylist.Create() +} + +// AddLoadBalancer policy list for the specified endpoints +func AddLoadBalancer(endpoints []HNSEndpoint, isILB bool, sourceVIP, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*PolicyList, error) { + operation := "AddLoadBalancer" + title := "hcsshim::PolicyList::" + operation + logrus.Debugf(title+" endpointId=%v, isILB=%v, sourceVIP=%s, vip=%s, protocol=%v, internalPort=%v, externalPort=%v", endpoints, isILB, sourceVIP, vip, protocol, internalPort, externalPort) + + policylist := &PolicyList{} + + elbPolicy := &ELBPolicy{ + SourceVIP: sourceVIP, + ILB: isILB, + } + + if len(vip) > 0 { + elbPolicy.VIPs = []string{vip} + } + elbPolicy.Type = ExternalLoadBalancer + elbPolicy.Protocol = protocol + elbPolicy.InternalPort = internalPort + elbPolicy.ExternalPort = externalPort + + for _, endpoint := range endpoints { + policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id) + } + + jsonString, err := json.Marshal(elbPolicy) + if err != nil { + return nil, err + } + policylist.Policies = append(policylist.Policies, jsonString) + return policylist.Create() +} + +// AddRoute adds route policy list for the specified endpoints +func AddRoute(endpoints []HNSEndpoint, destinationPrefix string, nextHop string, encapEnabled bool) (*PolicyList, error) { + operation := "AddRoute" + title := "hcsshim::PolicyList::" + operation + logrus.Debugf(title+" destinationPrefix:%s", destinationPrefix) + + policylist := &PolicyList{} + + rPolicy := &RoutePolicy{ + DestinationPrefix: destinationPrefix, + NextHop: nextHop, + EncapEnabled: encapEnabled, + } + rPolicy.Type = Route + + for _, endpoint := range endpoints { + policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id) + } + + jsonString, err := json.Marshal(rPolicy) + if err != nil { + return nil, err + } + + policylist.Policies = append(policylist.Policies, jsonString) + return policylist.Create() +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hns/hnssupport.go b/vendor/github.com/Microsoft/hcsshim/internal/hns/hnssupport.go new file mode 100644 index 000000000000..d5efba7f2841 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/hns/hnssupport.go @@ -0,0 +1,49 @@ +package hns + +import ( + "github.com/sirupsen/logrus" +) + +type HNSSupportedFeatures struct { + Acl HNSAclFeatures `json:"ACL"` +} + +type HNSAclFeatures struct { + AclAddressLists bool `json:"AclAddressLists"` + AclNoHostRulePriority bool `json:"AclHostRulePriority"` + AclPortRanges bool `json:"AclPortRanges"` + AclRuleId bool `json:"AclRuleId"` +} + +func GetHNSSupportedFeatures() HNSSupportedFeatures { + var hnsFeatures HNSSupportedFeatures + + globals, err := GetHNSGlobals() + if err != nil { + // Expected on pre-1803 builds, all features will be false/unsupported + logrus.Debugf("Unable to obtain HNS globals: %s", err) + return hnsFeatures + } + + hnsFeatures.Acl = HNSAclFeatures{ + AclAddressLists: isHNSFeatureSupported(globals.Version, HNSVersion1803), + AclNoHostRulePriority: isHNSFeatureSupported(globals.Version, HNSVersion1803), + AclPortRanges: isHNSFeatureSupported(globals.Version, HNSVersion1803), + AclRuleId: isHNSFeatureSupported(globals.Version, HNSVersion1803), + } + + return hnsFeatures +} + +func isHNSFeatureSupported(currentVersion HNSVersion, minVersionSupported HNSVersion) bool { + if currentVersion.Major < minVersionSupported.Major { + return false + } + if currentVersion.Major > minVersionSupported.Major { + return true + } + if currentVersion.Minor < minVersionSupported.Minor { + return false + } + return true +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hns/namespace.go b/vendor/github.com/Microsoft/hcsshim/internal/hns/namespace.go new file mode 100644 index 000000000000..45e2281b0781 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/hns/namespace.go @@ -0,0 +1,110 @@ +package hns + +import ( + "encoding/json" + "fmt" + "os" + "path" + "strings" +) + +type namespaceRequest struct { + IsDefault bool `json:",omitempty"` +} + +type namespaceEndpointRequest struct { + ID string `json:"Id"` +} + +type NamespaceResource struct { + Type string + Data json.RawMessage +} + +type namespaceResourceRequest struct { + Type string + Data interface{} +} + +type Namespace struct { + ID string + IsDefault bool `json:",omitempty"` + ResourceList []NamespaceResource `json:",omitempty"` +} + +func issueNamespaceRequest(id *string, method, subpath string, request interface{}) (*Namespace, error) { + var err error + hnspath := "/namespaces/" + if id != nil { + hnspath = path.Join(hnspath, *id) + } + if subpath != "" { + hnspath = path.Join(hnspath, subpath) + } + var reqJSON []byte + if request != nil { + if reqJSON, err = json.Marshal(request); err != nil { + return nil, err + } + } + var ns Namespace + err = hnsCall(method, hnspath, string(reqJSON), &ns) + if err != nil { + if strings.Contains(err.Error(), "Element not found.") { + return nil, os.ErrNotExist + } + return nil, fmt.Errorf("%s %s: %s", method, hnspath, err) + } + return &ns, err +} + +func CreateNamespace() (string, error) { + req := namespaceRequest{} + ns, err := issueNamespaceRequest(nil, "POST", "", &req) + if err != nil { + return "", err + } + return ns.ID, nil +} + +func RemoveNamespace(id string) error { + _, err := issueNamespaceRequest(&id, "DELETE", "", nil) + return err +} + +func GetNamespaceEndpoints(id string) ([]string, error) { + ns, err := issueNamespaceRequest(&id, "GET", "", nil) + if err != nil { + return nil, err + } + var endpoints []string + for _, rsrc := range ns.ResourceList { + if rsrc.Type == "Endpoint" { + var endpoint namespaceEndpointRequest + err = json.Unmarshal(rsrc.Data, &endpoint) + if err != nil { + return nil, fmt.Errorf("unmarshal endpoint: %s", err) + } + endpoints = append(endpoints, endpoint.ID) + } + } + return endpoints, nil +} + +func AddNamespaceEndpoint(id string, endpointID string) error { + resource := namespaceResourceRequest{ + Type: "Endpoint", + Data: namespaceEndpointRequest{endpointID}, + } + _, err := issueNamespaceRequest(&id, "POST", "addresource", &resource) + return err +} + +func RemoveNamespaceEndpoint(id string, endpointID string) error { + resource := namespaceResourceRequest{ + Type: "Endpoint", + Data: namespaceEndpointRequest{endpointID}, + } + _, err := issueNamespaceRequest(&id, "POST", "removeresource", &resource) + return err +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hns/zsyscall_windows.go b/vendor/github.com/Microsoft/hcsshim/internal/hns/zsyscall_windows.go new file mode 100644 index 000000000000..204633a4887d --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/hns/zsyscall_windows.go @@ -0,0 +1,76 @@ +// Code generated mksyscall_windows.exe DO NOT EDIT + +package hns + +import ( + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +var _ unsafe.Pointer + +// Do the interface allocations only once for common +// Errno values. +const ( + errnoERROR_IO_PENDING = 997 +) + +var ( + errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) +) + +// errnoErr returns common boxed Errno values, to prevent +// allocations at runtime. +func errnoErr(e syscall.Errno) error { + switch e { + case 0: + return nil + case errnoERROR_IO_PENDING: + return errERROR_IO_PENDING + } + // TODO: add more here, after collecting data on the common + // error values see on Windows. (perhaps when running + // all.bat?) + return e +} + +var ( + modvmcompute = windows.NewLazySystemDLL("vmcompute.dll") + + procHNSCall = modvmcompute.NewProc("HNSCall") +) + +func _hnsCall(method string, path string, object string, response **uint16) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(method) + if hr != nil { + return + } + var _p1 *uint16 + _p1, hr = syscall.UTF16PtrFromString(path) + if hr != nil { + return + } + var _p2 *uint16 + _p2, hr = syscall.UTF16PtrFromString(object) + if hr != nil { + return + } + return __hnsCall(_p0, _p1, _p2, response) +} + +func __hnsCall(method *uint16, path *uint16, object *uint16, response **uint16) (hr error) { + if hr = procHNSCall.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall6(procHNSCall.Addr(), 4, uintptr(unsafe.Pointer(method)), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(object)), uintptr(unsafe.Pointer(response)), 0, 0) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/interop/interop.go b/vendor/github.com/Microsoft/hcsshim/internal/interop/interop.go new file mode 100644 index 000000000000..2f6ec029ecf9 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/interop/interop.go @@ -0,0 +1,27 @@ +package interop + +import ( + "syscall" + "unsafe" +) + +//go:generate go run ../../mksyscall_windows.go -output zsyscall_windows.go interop.go + +//sys coTaskMemFree(buffer unsafe.Pointer) = api_ms_win_core_com_l1_1_0.CoTaskMemFree + +func ConvertAndFreeCoTaskMemString(buffer *uint16) string { + str := syscall.UTF16ToString((*[1 << 29]uint16)(unsafe.Pointer(buffer))[:]) + coTaskMemFree(unsafe.Pointer(buffer)) + return str +} + +func ConvertAndFreeCoTaskMemBytes(buffer *uint16) []byte { + return []byte(ConvertAndFreeCoTaskMemString(buffer)) +} + +func Win32FromHresult(hr uintptr) syscall.Errno { + if hr&0x1fff0000 == 0x00070000 { + return syscall.Errno(hr & 0xffff) + } + return syscall.Errno(hr) +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/interop/zsyscall_windows.go b/vendor/github.com/Microsoft/hcsshim/internal/interop/zsyscall_windows.go new file mode 100644 index 000000000000..12b0c71c5ae0 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/interop/zsyscall_windows.go @@ -0,0 +1,48 @@ +// Code generated mksyscall_windows.exe DO NOT EDIT + +package interop + +import ( + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +var _ unsafe.Pointer + +// Do the interface allocations only once for common +// Errno values. +const ( + errnoERROR_IO_PENDING = 997 +) + +var ( + errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) +) + +// errnoErr returns common boxed Errno values, to prevent +// allocations at runtime. +func errnoErr(e syscall.Errno) error { + switch e { + case 0: + return nil + case errnoERROR_IO_PENDING: + return errERROR_IO_PENDING + } + // TODO: add more here, after collecting data on the common + // error values see on Windows. (perhaps when running + // all.bat?) + return e +} + +var ( + modapi_ms_win_core_com_l1_1_0 = windows.NewLazySystemDLL("api-ms-win-core-com-l1-1-0.dll") + + procCoTaskMemFree = modapi_ms_win_core_com_l1_1_0.NewProc("CoTaskMemFree") +) + +func coTaskMemFree(buffer unsafe.Pointer) { + syscall.Syscall(procCoTaskMemFree.Addr(), 1, uintptr(buffer), 0, 0) + return +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/logfields/fields.go b/vendor/github.com/Microsoft/hcsshim/internal/logfields/fields.go new file mode 100644 index 000000000000..cf2c166d9b83 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/logfields/fields.go @@ -0,0 +1,32 @@ +package logfields + +const ( + // Identifiers + + ContainerID = "cid" + UVMID = "uvm-id" + ProcessID = "pid" + + // Common Misc + + // Timeout represents an operation timeout. + Timeout = "timeout" + JSON = "json" + + // Keys/values + + Field = "field" + OCIAnnotation = "oci-annotation" + Value = "value" + + // Golang type's + + ExpectedType = "expected-type" + Bool = "bool" + Uint32 = "uint32" + Uint64 = "uint64" + + // runhcs + + VMShimOperation = "vmshim-op" +) diff --git a/vendor/github.com/Microsoft/hcsshim/internal/longpath/longpath.go b/vendor/github.com/Microsoft/hcsshim/internal/longpath/longpath.go new file mode 100644 index 000000000000..e5b8b85e09ae --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/longpath/longpath.go @@ -0,0 +1,24 @@ +package longpath + +import ( + "path/filepath" + "strings" +) + +// LongAbs makes a path absolute and returns it in NT long path form. +func LongAbs(path string) (string, error) { + if strings.HasPrefix(path, `\\?\`) || strings.HasPrefix(path, `\\.\`) { + return path, nil + } + if !filepath.IsAbs(path) { + absPath, err := filepath.Abs(path) + if err != nil { + return "", err + } + path = absPath + } + if strings.HasPrefix(path, `\\`) { + return `\\?\UNC\` + path[2:], nil + } + return `\\?\` + path, nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/mergemaps/merge.go b/vendor/github.com/Microsoft/hcsshim/internal/mergemaps/merge.go new file mode 100644 index 000000000000..7e95efb30d73 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/mergemaps/merge.go @@ -0,0 +1,52 @@ +package mergemaps + +import "encoding/json" + +// Merge recursively merges map `fromMap` into map `ToMap`. Any pre-existing values +// in ToMap are overwritten. Values in fromMap are added to ToMap. +// From http://stackoverflow.com/questions/40491438/merging-two-json-strings-in-golang +func Merge(fromMap, ToMap interface{}) interface{} { + switch fromMap := fromMap.(type) { + case map[string]interface{}: + ToMap, ok := ToMap.(map[string]interface{}) + if !ok { + return fromMap + } + for keyToMap, valueToMap := range ToMap { + if valueFromMap, ok := fromMap[keyToMap]; ok { + fromMap[keyToMap] = Merge(valueFromMap, valueToMap) + } else { + fromMap[keyToMap] = valueToMap + } + } + case nil: + // merge(nil, map[string]interface{...}) -> map[string]interface{...} + ToMap, ok := ToMap.(map[string]interface{}) + if ok { + return ToMap + } + } + return fromMap +} + +// MergeJSON merges the contents of a JSON string into an object representation, +// returning a new object suitable for translating to JSON. +func MergeJSON(object interface{}, additionalJSON []byte) (interface{}, error) { + if len(additionalJSON) == 0 { + return object, nil + } + objectJSON, err := json.Marshal(object) + if err != nil { + return nil, err + } + var objectMap, newMap map[string]interface{} + err = json.Unmarshal(objectJSON, &objectMap) + if err != nil { + return nil, err + } + err = json.Unmarshal(additionalJSON, &newMap) + if err != nil { + return nil, err + } + return Merge(newMap, objectMap), nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/safefile/safeopen.go b/vendor/github.com/Microsoft/hcsshim/internal/safefile/safeopen.go new file mode 100644 index 000000000000..f31edfaf8674 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/safefile/safeopen.go @@ -0,0 +1,431 @@ +package safefile + +import ( + "errors" + "io" + "os" + "path/filepath" + "strings" + "syscall" + "unicode/utf16" + "unsafe" + + "github.com/Microsoft/hcsshim/internal/longpath" + + winio "github.com/Microsoft/go-winio" +) + +//go:generate go run $GOROOT\src\syscall\mksyscall_windows.go -output zsyscall_windows.go safeopen.go + +//sys ntCreateFile(handle *uintptr, accessMask uint32, oa *objectAttributes, iosb *ioStatusBlock, allocationSize *uint64, fileAttributes uint32, shareAccess uint32, createDisposition uint32, createOptions uint32, eaBuffer *byte, eaLength uint32) (status uint32) = ntdll.NtCreateFile +//sys ntSetInformationFile(handle uintptr, iosb *ioStatusBlock, information uintptr, length uint32, class uint32) (status uint32) = ntdll.NtSetInformationFile +//sys rtlNtStatusToDosError(status uint32) (winerr error) = ntdll.RtlNtStatusToDosErrorNoTeb +//sys localAlloc(flags uint32, size int) (ptr uintptr) = kernel32.LocalAlloc +//sys localFree(ptr uintptr) = kernel32.LocalFree + +type ioStatusBlock struct { + Status, Information uintptr +} + +type objectAttributes struct { + Length uintptr + RootDirectory uintptr + ObjectName uintptr + Attributes uintptr + SecurityDescriptor uintptr + SecurityQoS uintptr +} + +type unicodeString struct { + Length uint16 + MaximumLength uint16 + Buffer uintptr +} + +type fileLinkInformation struct { + ReplaceIfExists bool + RootDirectory uintptr + FileNameLength uint32 + FileName [1]uint16 +} + +type fileDispositionInformationEx struct { + Flags uintptr +} + +const ( + _FileLinkInformation = 11 + _FileDispositionInformationEx = 64 + + FILE_READ_ATTRIBUTES = 0x0080 + FILE_WRITE_ATTRIBUTES = 0x0100 + DELETE = 0x10000 + + FILE_OPEN = 1 + FILE_CREATE = 2 + + FILE_DIRECTORY_FILE = 0x00000001 + FILE_SYNCHRONOUS_IO_NONALERT = 0x00000020 + FILE_DELETE_ON_CLOSE = 0x00001000 + FILE_OPEN_FOR_BACKUP_INTENT = 0x00004000 + FILE_OPEN_REPARSE_POINT = 0x00200000 + + FILE_DISPOSITION_DELETE = 0x00000001 + + _OBJ_DONT_REPARSE = 0x1000 + + _STATUS_REPARSE_POINT_ENCOUNTERED = 0xC000050B +) + +func OpenRoot(path string) (*os.File, error) { + longpath, err := longpath.LongAbs(path) + if err != nil { + return nil, err + } + return winio.OpenForBackup(longpath, syscall.GENERIC_READ, syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, syscall.OPEN_EXISTING) +} + +func ntRelativePath(path string) ([]uint16, error) { + path = filepath.Clean(path) + if strings.Contains(path, ":") { + // Since alternate data streams must follow the file they + // are attached to, finding one here (out of order) is invalid. + return nil, errors.New("path contains invalid character `:`") + } + fspath := filepath.FromSlash(path) + if len(fspath) > 0 && fspath[0] == '\\' { + return nil, errors.New("expected relative path") + } + + path16 := utf16.Encode(([]rune)(fspath)) + if len(path16) > 32767 { + return nil, syscall.ENAMETOOLONG + } + + return path16, nil +} + +// openRelativeInternal opens a relative path from the given root, failing if +// any of the intermediate path components are reparse points. +func openRelativeInternal(path string, root *os.File, accessMask uint32, shareFlags uint32, createDisposition uint32, flags uint32) (*os.File, error) { + var ( + h uintptr + iosb ioStatusBlock + oa objectAttributes + ) + + path16, err := ntRelativePath(path) + if err != nil { + return nil, err + } + + if root == nil || root.Fd() == 0 { + return nil, errors.New("missing root directory") + } + + upathBuffer := localAlloc(0, int(unsafe.Sizeof(unicodeString{}))+len(path16)*2) + defer localFree(upathBuffer) + + upath := (*unicodeString)(unsafe.Pointer(upathBuffer)) + upath.Length = uint16(len(path16) * 2) + upath.MaximumLength = upath.Length + upath.Buffer = upathBuffer + unsafe.Sizeof(*upath) + copy((*[32768]uint16)(unsafe.Pointer(upath.Buffer))[:], path16) + + oa.Length = unsafe.Sizeof(oa) + oa.ObjectName = upathBuffer + oa.RootDirectory = uintptr(root.Fd()) + oa.Attributes = _OBJ_DONT_REPARSE + status := ntCreateFile( + &h, + accessMask|syscall.SYNCHRONIZE, + &oa, + &iosb, + nil, + 0, + shareFlags, + createDisposition, + FILE_OPEN_FOR_BACKUP_INTENT|FILE_SYNCHRONOUS_IO_NONALERT|flags, + nil, + 0, + ) + if status != 0 { + return nil, rtlNtStatusToDosError(status) + } + + fullPath, err := longpath.LongAbs(filepath.Join(root.Name(), path)) + if err != nil { + syscall.Close(syscall.Handle(h)) + return nil, err + } + + return os.NewFile(h, fullPath), nil +} + +// OpenRelative opens a relative path from the given root, failing if +// any of the intermediate path components are reparse points. +func OpenRelative(path string, root *os.File, accessMask uint32, shareFlags uint32, createDisposition uint32, flags uint32) (*os.File, error) { + f, err := openRelativeInternal(path, root, accessMask, shareFlags, createDisposition, flags) + if err != nil { + err = &os.PathError{Op: "open", Path: filepath.Join(root.Name(), path), Err: err} + } + return f, err +} + +// LinkRelative creates a hard link from oldname to newname (relative to oldroot +// and newroot), failing if any of the intermediate path components are reparse +// points. +func LinkRelative(oldname string, oldroot *os.File, newname string, newroot *os.File) error { + // Open the old file. + oldf, err := openRelativeInternal( + oldname, + oldroot, + syscall.FILE_WRITE_ATTRIBUTES, + syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, + FILE_OPEN, + 0, + ) + if err != nil { + return &os.LinkError{Op: "link", Old: filepath.Join(oldroot.Name(), oldname), New: filepath.Join(newroot.Name(), newname), Err: err} + } + defer oldf.Close() + + // Open the parent of the new file. + var parent *os.File + parentPath := filepath.Dir(newname) + if parentPath != "." { + parent, err = openRelativeInternal( + parentPath, + newroot, + syscall.GENERIC_READ, + syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, + FILE_OPEN, + FILE_DIRECTORY_FILE) + if err != nil { + return &os.LinkError{Op: "link", Old: oldf.Name(), New: filepath.Join(newroot.Name(), newname), Err: err} + } + defer parent.Close() + + fi, err := winio.GetFileBasicInfo(parent) + if err != nil { + return err + } + if (fi.FileAttributes & syscall.FILE_ATTRIBUTE_REPARSE_POINT) != 0 { + return &os.LinkError{Op: "link", Old: oldf.Name(), New: filepath.Join(newroot.Name(), newname), Err: rtlNtStatusToDosError(_STATUS_REPARSE_POINT_ENCOUNTERED)} + } + + } else { + parent = newroot + } + + // Issue an NT call to create the link. This will be safe because NT will + // not open any more directories to create the link, so it cannot walk any + // more reparse points. + newbase := filepath.Base(newname) + newbase16, err := ntRelativePath(newbase) + if err != nil { + return err + } + + size := int(unsafe.Offsetof(fileLinkInformation{}.FileName)) + len(newbase16)*2 + linkinfoBuffer := localAlloc(0, size) + defer localFree(linkinfoBuffer) + linkinfo := (*fileLinkInformation)(unsafe.Pointer(linkinfoBuffer)) + linkinfo.RootDirectory = parent.Fd() + linkinfo.FileNameLength = uint32(len(newbase16) * 2) + copy((*[32768]uint16)(unsafe.Pointer(&linkinfo.FileName[0]))[:], newbase16) + + var iosb ioStatusBlock + status := ntSetInformationFile( + oldf.Fd(), + &iosb, + linkinfoBuffer, + uint32(size), + _FileLinkInformation, + ) + if status != 0 { + return &os.LinkError{Op: "link", Old: oldf.Name(), New: filepath.Join(parent.Name(), newbase), Err: rtlNtStatusToDosError(status)} + } + + return nil +} + +// deleteOnClose marks a file to be deleted when the handle is closed. +func deleteOnClose(f *os.File) error { + disposition := fileDispositionInformationEx{Flags: FILE_DISPOSITION_DELETE} + var iosb ioStatusBlock + status := ntSetInformationFile( + f.Fd(), + &iosb, + uintptr(unsafe.Pointer(&disposition)), + uint32(unsafe.Sizeof(disposition)), + _FileDispositionInformationEx, + ) + if status != 0 { + return rtlNtStatusToDosError(status) + } + return nil +} + +// clearReadOnly clears the readonly attribute on a file. +func clearReadOnly(f *os.File) error { + bi, err := winio.GetFileBasicInfo(f) + if err != nil { + return err + } + if bi.FileAttributes&syscall.FILE_ATTRIBUTE_READONLY == 0 { + return nil + } + sbi := winio.FileBasicInfo{ + FileAttributes: bi.FileAttributes &^ syscall.FILE_ATTRIBUTE_READONLY, + } + if sbi.FileAttributes == 0 { + sbi.FileAttributes = syscall.FILE_ATTRIBUTE_NORMAL + } + return winio.SetFileBasicInfo(f, &sbi) +} + +// RemoveRelative removes a file or directory relative to a root, failing if any +// intermediate path components are reparse points. +func RemoveRelative(path string, root *os.File) error { + f, err := openRelativeInternal( + path, + root, + FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES|DELETE, + syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, + FILE_OPEN, + FILE_OPEN_REPARSE_POINT) + if err == nil { + defer f.Close() + err = deleteOnClose(f) + if err == syscall.ERROR_ACCESS_DENIED { + // Maybe the file is marked readonly. Clear the bit and retry. + clearReadOnly(f) + err = deleteOnClose(f) + } + } + if err != nil { + return &os.PathError{Op: "remove", Path: filepath.Join(root.Name(), path), Err: err} + } + return nil +} + +// RemoveAllRelative removes a directory tree relative to a root, failing if any +// intermediate path components are reparse points. +func RemoveAllRelative(path string, root *os.File) error { + fi, err := LstatRelative(path, root) + if err != nil { + if os.IsNotExist(err) { + return nil + } + return err + } + fileAttributes := fi.Sys().(*syscall.Win32FileAttributeData).FileAttributes + if fileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY == 0 || fileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT != 0 { + // If this is a reparse point, it can't have children. Simple remove will do. + err := RemoveRelative(path, root) + if err == nil || os.IsNotExist(err) { + return nil + } + return err + } + + // It is necessary to use os.Open as Readdirnames does not work with + // OpenRelative. This is safe because the above lstatrelative fails + // if the target is outside the root, and we know this is not a + // symlink from the above FILE_ATTRIBUTE_REPARSE_POINT check. + fd, err := os.Open(filepath.Join(root.Name(), path)) + if err != nil { + if os.IsNotExist(err) { + // Race. It was deleted between the Lstat and Open. + // Return nil per RemoveAll's docs. + return nil + } + return err + } + + // Remove contents & return first error. + for { + names, err1 := fd.Readdirnames(100) + for _, name := range names { + err1 := RemoveAllRelative(path+string(os.PathSeparator)+name, root) + if err == nil { + err = err1 + } + } + if err1 == io.EOF { + break + } + // If Readdirnames returned an error, use it. + if err == nil { + err = err1 + } + if len(names) == 0 { + break + } + } + fd.Close() + + // Remove directory. + err1 := RemoveRelative(path, root) + if err1 == nil || os.IsNotExist(err1) { + return nil + } + if err == nil { + err = err1 + } + return err +} + +// MkdirRelative creates a directory relative to a root, failing if any +// intermediate path components are reparse points. +func MkdirRelative(path string, root *os.File) error { + f, err := openRelativeInternal( + path, + root, + 0, + syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, + FILE_CREATE, + FILE_DIRECTORY_FILE) + if err == nil { + f.Close() + } else { + err = &os.PathError{Op: "mkdir", Path: filepath.Join(root.Name(), path), Err: err} + } + return err +} + +// LstatRelative performs a stat operation on a file relative to a root, failing +// if any intermediate path components are reparse points. +func LstatRelative(path string, root *os.File) (os.FileInfo, error) { + f, err := openRelativeInternal( + path, + root, + FILE_READ_ATTRIBUTES, + syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, + FILE_OPEN, + FILE_OPEN_REPARSE_POINT) + if err != nil { + return nil, &os.PathError{Op: "stat", Path: filepath.Join(root.Name(), path), Err: err} + } + defer f.Close() + return f.Stat() +} + +// EnsureNotReparsePointRelative validates that a given file (relative to a +// root) and all intermediate path components are not a reparse points. +func EnsureNotReparsePointRelative(path string, root *os.File) error { + // Perform an open with OBJ_DONT_REPARSE but without specifying FILE_OPEN_REPARSE_POINT. + f, err := OpenRelative( + path, + root, + 0, + syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, + FILE_OPEN, + 0) + if err != nil { + return err + } + f.Close() + return nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/safefile/zsyscall_windows.go b/vendor/github.com/Microsoft/hcsshim/internal/safefile/zsyscall_windows.go new file mode 100644 index 000000000000..709b9d3475d1 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/safefile/zsyscall_windows.go @@ -0,0 +1,79 @@ +// Code generated by 'go generate'; DO NOT EDIT. + +package safefile + +import ( + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +var _ unsafe.Pointer + +// Do the interface allocations only once for common +// Errno values. +const ( + errnoERROR_IO_PENDING = 997 +) + +var ( + errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) +) + +// errnoErr returns common boxed Errno values, to prevent +// allocations at runtime. +func errnoErr(e syscall.Errno) error { + switch e { + case 0: + return nil + case errnoERROR_IO_PENDING: + return errERROR_IO_PENDING + } + // TODO: add more here, after collecting data on the common + // error values see on Windows. (perhaps when running + // all.bat?) + return e +} + +var ( + modntdll = windows.NewLazySystemDLL("ntdll.dll") + modkernel32 = windows.NewLazySystemDLL("kernel32.dll") + + procNtCreateFile = modntdll.NewProc("NtCreateFile") + procNtSetInformationFile = modntdll.NewProc("NtSetInformationFile") + procRtlNtStatusToDosErrorNoTeb = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb") + procLocalAlloc = modkernel32.NewProc("LocalAlloc") + procLocalFree = modkernel32.NewProc("LocalFree") +) + +func ntCreateFile(handle *uintptr, accessMask uint32, oa *objectAttributes, iosb *ioStatusBlock, allocationSize *uint64, fileAttributes uint32, shareAccess uint32, createDisposition uint32, createOptions uint32, eaBuffer *byte, eaLength uint32) (status uint32) { + r0, _, _ := syscall.Syscall12(procNtCreateFile.Addr(), 11, uintptr(unsafe.Pointer(handle)), uintptr(accessMask), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(unsafe.Pointer(allocationSize)), uintptr(fileAttributes), uintptr(shareAccess), uintptr(createDisposition), uintptr(createOptions), uintptr(unsafe.Pointer(eaBuffer)), uintptr(eaLength), 0) + status = uint32(r0) + return +} + +func ntSetInformationFile(handle uintptr, iosb *ioStatusBlock, information uintptr, length uint32, class uint32) (status uint32) { + r0, _, _ := syscall.Syscall6(procNtSetInformationFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(iosb)), uintptr(information), uintptr(length), uintptr(class), 0) + status = uint32(r0) + return +} + +func rtlNtStatusToDosError(status uint32) (winerr error) { + r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(status), 0, 0) + if r0 != 0 { + winerr = syscall.Errno(r0) + } + return +} + +func localAlloc(flags uint32, size int) (ptr uintptr) { + r0, _, _ := syscall.Syscall(procLocalAlloc.Addr(), 2, uintptr(flags), uintptr(size), 0) + ptr = uintptr(r0) + return +} + +func localFree(ptr uintptr) { + syscall.Syscall(procLocalFree.Addr(), 1, uintptr(ptr), 0, 0) + return +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema1/schema1.go b/vendor/github.com/Microsoft/hcsshim/internal/schema1/schema1.go new file mode 100644 index 000000000000..995433ace6f5 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema1/schema1.go @@ -0,0 +1,245 @@ +package schema1 + +import ( + "encoding/json" + "time" + + "github.com/Microsoft/hcsshim/internal/schema2" +) + +// ProcessConfig is used as both the input of Container.CreateProcess +// and to convert the parameters to JSON for passing onto the HCS +type ProcessConfig struct { + ApplicationName string `json:",omitempty"` + CommandLine string `json:",omitempty"` + CommandArgs []string `json:",omitempty"` // Used by Linux Containers on Windows + User string `json:",omitempty"` + WorkingDirectory string `json:",omitempty"` + Environment map[string]string `json:",omitempty"` + EmulateConsole bool `json:",omitempty"` + CreateStdInPipe bool `json:",omitempty"` + CreateStdOutPipe bool `json:",omitempty"` + CreateStdErrPipe bool `json:",omitempty"` + ConsoleSize [2]uint `json:",omitempty"` + CreateInUtilityVm bool `json:",omitempty"` // Used by Linux Containers on Windows + OCISpecification *json.RawMessage `json:",omitempty"` // Used by Linux Containers on Windows +} + +type Layer struct { + ID string + Path string +} + +type MappedDir struct { + HostPath string + ContainerPath string + ReadOnly bool + BandwidthMaximum uint64 + IOPSMaximum uint64 + CreateInUtilityVM bool + // LinuxMetadata - Support added in 1803/RS4+. + LinuxMetadata bool `json:",omitempty"` +} + +type MappedPipe struct { + HostPath string + ContainerPipeName string +} + +type HvRuntime struct { + ImagePath string `json:",omitempty"` + SkipTemplate bool `json:",omitempty"` + LinuxInitrdFile string `json:",omitempty"` // File under ImagePath on host containing an initrd image for starting a Linux utility VM + LinuxKernelFile string `json:",omitempty"` // File under ImagePath on host containing a kernel for starting a Linux utility VM + LinuxBootParameters string `json:",omitempty"` // Additional boot parameters for starting a Linux Utility VM in initrd mode + BootSource string `json:",omitempty"` // "Vhd" for Linux Utility VM booting from VHD + WritableBootSource bool `json:",omitempty"` // Linux Utility VM booting from VHD +} + +type MappedVirtualDisk struct { + HostPath string `json:",omitempty"` // Path to VHD on the host + ContainerPath string // Platform-specific mount point path in the container + CreateInUtilityVM bool `json:",omitempty"` + ReadOnly bool `json:",omitempty"` + Cache string `json:",omitempty"` // "" (Unspecified); "Disabled"; "Enabled"; "Private"; "PrivateAllowSharing" + AttachOnly bool `json:",omitempty:` +} + +// AssignedDevice represents a device that has been directly assigned to a container +// +// NOTE: Support added in RS5 +type AssignedDevice struct { + // InterfaceClassGUID of the device to assign to container. + InterfaceClassGUID string `json:"InterfaceClassGuid,omitempty"` +} + +// ContainerConfig is used as both the input of CreateContainer +// and to convert the parameters to JSON for passing onto the HCS +type ContainerConfig struct { + SystemType string // HCS requires this to be hard-coded to "Container" + Name string // Name of the container. We use the docker ID. + Owner string `json:",omitempty"` // The management platform that created this container + VolumePath string `json:",omitempty"` // Windows volume path for scratch space. Used by Windows Server Containers only. Format \\?\\Volume{GUID} + IgnoreFlushesDuringBoot bool `json:",omitempty"` // Optimization hint for container startup in Windows + LayerFolderPath string `json:",omitempty"` // Where the layer folders are located. Used by Windows Server Containers only. Format %root%\windowsfilter\containerID + Layers []Layer // List of storage layers. Required for Windows Server and Hyper-V Containers. Format ID=GUID;Path=%root%\windowsfilter\layerID + Credentials string `json:",omitempty"` // Credentials information + ProcessorCount uint32 `json:",omitempty"` // Number of processors to assign to the container. + ProcessorWeight uint64 `json:",omitempty"` // CPU shares (relative weight to other containers with cpu shares). Range is from 1 to 10000. A value of 0 results in default shares. + ProcessorMaximum int64 `json:",omitempty"` // Specifies the portion of processor cycles that this container can use as a percentage times 100. Range is from 1 to 10000. A value of 0 results in no limit. + StorageIOPSMaximum uint64 `json:",omitempty"` // Maximum Storage IOPS + StorageBandwidthMaximum uint64 `json:",omitempty"` // Maximum Storage Bandwidth in bytes per second + StorageSandboxSize uint64 `json:",omitempty"` // Size in bytes that the container system drive should be expanded to if smaller + MemoryMaximumInMB int64 `json:",omitempty"` // Maximum memory available to the container in Megabytes + HostName string `json:",omitempty"` // Hostname + MappedDirectories []MappedDir `json:",omitempty"` // List of mapped directories (volumes/mounts) + MappedPipes []MappedPipe `json:",omitempty"` // List of mapped Windows named pipes + HvPartition bool // True if it a Hyper-V Container + NetworkSharedContainerName string `json:",omitempty"` // Name (ID) of the container that we will share the network stack with. + EndpointList []string `json:",omitempty"` // List of networking endpoints to be attached to container + HvRuntime *HvRuntime `json:",omitempty"` // Hyper-V container settings. Used by Hyper-V containers only. Format ImagePath=%root%\BaseLayerID\UtilityVM + Servicing bool `json:",omitempty"` // True if this container is for servicing + AllowUnqualifiedDNSQuery bool `json:",omitempty"` // True to allow unqualified DNS name resolution + DNSSearchList string `json:",omitempty"` // Comma seperated list of DNS suffixes to use for name resolution + ContainerType string `json:",omitempty"` // "Linux" for Linux containers on Windows. Omitted otherwise. + TerminateOnLastHandleClosed bool `json:",omitempty"` // Should HCS terminate the container once all handles have been closed + MappedVirtualDisks []MappedVirtualDisk `json:",omitempty"` // Array of virtual disks to mount at start + AssignedDevices []AssignedDevice `json:",omitempty"` // Array of devices to assign. NOTE: Support added in RS5 +} + +type ComputeSystemQuery struct { + IDs []string `json:"Ids,omitempty"` + Types []string `json:",omitempty"` + Names []string `json:",omitempty"` + Owners []string `json:",omitempty"` +} + +type PropertyType string + +const ( + PropertyTypeStatistics PropertyType = "Statistics" // V1 and V2 + PropertyTypeProcessList = "ProcessList" // V1 and V2 + PropertyTypeMappedVirtualDisk = "MappedVirtualDisk" // Not supported in V2 schema call + PropertyTypeGuestConnection = "GuestConnection" // V1 and V2. Nil return from HCS before RS5 +) + +type PropertyQuery struct { + PropertyTypes []PropertyType `json:",omitempty"` +} + +// ContainerProperties holds the properties for a container and the processes running in that container +type ContainerProperties struct { + ID string `json:"Id"` + State string + Name string + SystemType string + Owner string + SiloGUID string `json:"SiloGuid,omitempty"` + RuntimeID string `json:"RuntimeId,omitempty"` + IsRuntimeTemplate bool `json:",omitempty"` + RuntimeImagePath string `json:",omitempty"` + Stopped bool `json:",omitempty"` + ExitType string `json:",omitempty"` + AreUpdatesPending bool `json:",omitempty"` + ObRoot string `json:",omitempty"` + Statistics Statistics `json:",omitempty"` + ProcessList []ProcessListItem `json:",omitempty"` + MappedVirtualDiskControllers map[int]MappedVirtualDiskController `json:",omitempty"` + GuestConnectionInfo GuestConnectionInfo `json:",omitempty"` +} + +// MemoryStats holds the memory statistics for a container +type MemoryStats struct { + UsageCommitBytes uint64 `json:"MemoryUsageCommitBytes,omitempty"` + UsageCommitPeakBytes uint64 `json:"MemoryUsageCommitPeakBytes,omitempty"` + UsagePrivateWorkingSetBytes uint64 `json:"MemoryUsagePrivateWorkingSetBytes,omitempty"` +} + +// ProcessorStats holds the processor statistics for a container +type ProcessorStats struct { + TotalRuntime100ns uint64 `json:",omitempty"` + RuntimeUser100ns uint64 `json:",omitempty"` + RuntimeKernel100ns uint64 `json:",omitempty"` +} + +// StorageStats holds the storage statistics for a container +type StorageStats struct { + ReadCountNormalized uint64 `json:",omitempty"` + ReadSizeBytes uint64 `json:",omitempty"` + WriteCountNormalized uint64 `json:",omitempty"` + WriteSizeBytes uint64 `json:",omitempty"` +} + +// NetworkStats holds the network statistics for a container +type NetworkStats struct { + BytesReceived uint64 `json:",omitempty"` + BytesSent uint64 `json:",omitempty"` + PacketsReceived uint64 `json:",omitempty"` + PacketsSent uint64 `json:",omitempty"` + DroppedPacketsIncoming uint64 `json:",omitempty"` + DroppedPacketsOutgoing uint64 `json:",omitempty"` + EndpointId string `json:",omitempty"` + InstanceId string `json:",omitempty"` +} + +// Statistics is the structure returned by a statistics call on a container +type Statistics struct { + Timestamp time.Time `json:",omitempty"` + ContainerStartTime time.Time `json:",omitempty"` + Uptime100ns uint64 `json:",omitempty"` + Memory MemoryStats `json:",omitempty"` + Processor ProcessorStats `json:",omitempty"` + Storage StorageStats `json:",omitempty"` + Network []NetworkStats `json:",omitempty"` +} + +// ProcessList is the structure of an item returned by a ProcessList call on a container +type ProcessListItem struct { + CreateTimestamp time.Time `json:",omitempty"` + ImageName string `json:",omitempty"` + KernelTime100ns uint64 `json:",omitempty"` + MemoryCommitBytes uint64 `json:",omitempty"` + MemoryWorkingSetPrivateBytes uint64 `json:",omitempty"` + MemoryWorkingSetSharedBytes uint64 `json:",omitempty"` + ProcessId uint32 `json:",omitempty"` + UserTime100ns uint64 `json:",omitempty"` +} + +// MappedVirtualDiskController is the structure of an item returned by a MappedVirtualDiskList call on a container +type MappedVirtualDiskController struct { + MappedVirtualDisks map[int]MappedVirtualDisk `json:",omitempty"` +} + +// GuestDefinedCapabilities is part of the GuestConnectionInfo returned by a GuestConnection call on a utility VM +type GuestDefinedCapabilities struct { + NamespaceAddRequestSupported bool `json:",omitempty"` + SignalProcessSupported bool `json:",omitempty"` +} + +// GuestConnectionInfo is the structure of an iterm return by a GuestConnection call on a utility VM +type GuestConnectionInfo struct { + SupportedSchemaVersions []hcsschema.Version `json:",omitempty"` + ProtocolVersion uint32 `json:",omitempty"` + GuestDefinedCapabilities GuestDefinedCapabilities `json:",omitempty"` +} + +// Type of Request Support in ModifySystem +type RequestType string + +// Type of Resource Support in ModifySystem +type ResourceType string + +// RequestType const +const ( + Add RequestType = "Add" + Remove RequestType = "Remove" + Network ResourceType = "Network" +) + +// ResourceModificationRequestResponse is the structure used to send request to the container to modify the system +// Supported resource types are Network and Request Types are Add/Remove +type ResourceModificationRequestResponse struct { + Resource ResourceType `json:"ResourceType"` + Data interface{} `json:"Settings"` + Request RequestType `json:"RequestType,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/attachment.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/attachment.go new file mode 100644 index 000000000000..09456cbc2197 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/attachment.go @@ -0,0 +1,31 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type Attachment struct { + + Type_ string `json:"Type,omitempty"` + + Path string `json:"Path,omitempty"` + + IgnoreFlushes bool `json:"IgnoreFlushes,omitempty"` + + CachingMode string `json:"CachingMode,omitempty"` + + NoWriteHardening bool `json:"NoWriteHardening,omitempty"` + + DisableExpansionOptimization bool `json:"DisableExpansionOptimization,omitempty"` + + IgnoreRelativeLocator bool `json:"IgnoreRelativeLocator,omitempty"` + + CaptureIoAttributionContext bool `json:"CaptureIoAttributionContext,omitempty"` + + ReadOnly bool `json:"ReadOnly,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/battery.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/battery.go new file mode 100644 index 000000000000..ecbbed4c233f --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/battery.go @@ -0,0 +1,13 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type Battery struct { +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/cache_query_stats_response.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/cache_query_stats_response.go new file mode 100644 index 000000000000..243779eab678 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/cache_query_stats_response.go @@ -0,0 +1,19 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type CacheQueryStatsResponse struct { + + L3OccupancyBytes int32 `json:"L3OccupancyBytes,omitempty"` + + L3TotalBwBytes int32 `json:"L3TotalBwBytes,omitempty"` + + L3LocalBwBytes int32 `json:"L3LocalBwBytes,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/chipset.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/chipset.go new file mode 100644 index 000000000000..ca75277a3f25 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/chipset.go @@ -0,0 +1,27 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type Chipset struct { + Uefi *Uefi `json:"Uefi,omitempty"` + + IsNumLockDisabled bool `json:"IsNumLockDisabled,omitempty"` + + BaseBoardSerialNumber string `json:"BaseBoardSerialNumber,omitempty"` + + ChassisSerialNumber string `json:"ChassisSerialNumber,omitempty"` + + ChassisAssetTag string `json:"ChassisAssetTag,omitempty"` + + UseUtc bool `json:"UseUtc,omitempty"` + + // LinuxKernelDirect - Added in v2.2 Builds >=181117 + LinuxKernelDirect *LinuxKernelDirect `json:"LinuxKernelDirect,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/close_handle.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/close_handle.go new file mode 100644 index 000000000000..88f01707a732 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/close_handle.go @@ -0,0 +1,15 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type CloseHandle struct { + + Handle string `json:"Handle,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/com_port.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/com_port.go new file mode 100644 index 000000000000..c665be3d5a38 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/com_port.go @@ -0,0 +1,18 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +// ComPort specifies the named pipe that will be used for the port, with empty string indicating a disconnected port. +type ComPort struct { + + NamedPipe string `json:"NamedPipe,omitempty"` + + OptimizeForDebugger bool `json:"OptimizeForDebugger,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/compute_system.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/compute_system.go new file mode 100644 index 000000000000..85785d285853 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/compute_system.go @@ -0,0 +1,27 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type ComputeSystem struct { + + Owner string `json:"Owner,omitempty"` + + SchemaVersion *Version `json:"SchemaVersion,omitempty"` + + HostingSystemId string `json:"HostingSystemId,omitempty"` + + HostedSystem *HostedSystem `json:"HostedSystem,omitempty"` + + Container *Container `json:"Container,omitempty"` + + VirtualMachine *VirtualMachine `json:"VirtualMachine,omitempty"` + + ShouldTerminateOnLastHandleClosed bool `json:"ShouldTerminateOnLastHandleClosed,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/configuration.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/configuration.go new file mode 100644 index 000000000000..1a47db7d955f --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/configuration.go @@ -0,0 +1,72 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +import ( + "net/http" +) + +// contextKeys are used to identify the type of value in the context. +// Since these are string, it is possible to get a short description of the +// context key for logging and debugging using key.String(). + +type contextKey string + +func (c contextKey) String() string { + return "auth " + string(c) +} + +var ( + // ContextOAuth2 takes a oauth2.TokenSource as authentication for the request. + ContextOAuth2 = contextKey("token") + + // ContextBasicAuth takes BasicAuth as authentication for the request. + ContextBasicAuth = contextKey("basic") + + // ContextAccessToken takes a string oauth2 access token as authentication for the request. + ContextAccessToken = contextKey("accesstoken") + + // ContextAPIKey takes an APIKey as authentication for the request + ContextAPIKey = contextKey("apikey") +) + +// BasicAuth provides basic http authentication to a request passed via context using ContextBasicAuth +type BasicAuth struct { + UserName string `json:"userName,omitempty"` + Password string `json:"password,omitempty"` +} + +// APIKey provides API key based authentication to a request passed via context using ContextAPIKey +type APIKey struct { + Key string + Prefix string +} + +type Configuration struct { + BasePath string `json:"basePath,omitempty"` + Host string `json:"host,omitempty"` + Scheme string `json:"scheme,omitempty"` + DefaultHeader map[string]string `json:"defaultHeader,omitempty"` + UserAgent string `json:"userAgent,omitempty"` + HTTPClient *http.Client +} + +func NewConfiguration() *Configuration { + cfg := &Configuration{ + BasePath: "https://localhost", + DefaultHeader: make(map[string]string), + UserAgent: "Swagger-Codegen/2.1.0/go", + } + return cfg +} + +func (c *Configuration) AddDefaultHeader(key string, value string) { + c.DefaultHeader[key] = value +} \ No newline at end of file diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/console_size.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/console_size.go new file mode 100644 index 000000000000..adbe07fe5594 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/console_size.go @@ -0,0 +1,17 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type ConsoleSize struct { + + Height int32 `json:"Height,omitempty"` + + Width int32 `json:"Width,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/container.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/container.go new file mode 100644 index 000000000000..17dce28bc721 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/container.go @@ -0,0 +1,35 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type Container struct { + + GuestOs *GuestOs `json:"GuestOs,omitempty"` + + Storage *Storage `json:"Storage,omitempty"` + + MappedDirectories []MappedDirectory `json:"MappedDirectories,omitempty"` + + MappedPipes []MappedPipe `json:"MappedPipes,omitempty"` + + Memory *Memory `json:"Memory,omitempty"` + + Processor *Processor `json:"Processor,omitempty"` + + Networking *Networking `json:"Networking,omitempty"` + + HvSocket *HvSocket `json:"HvSocket,omitempty"` + + ContainerCredentialGuard *ContainerCredentialGuardState `json:"ContainerCredentialGuard,omitempty"` + + RegistryChanges *RegistryChanges `json:"RegistryChanges,omitempty"` + + AssignedDevices []Device `json:"AssignedDevices,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/container_credential_guard_state.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/container_credential_guard_state.go new file mode 100644 index 000000000000..0f8f644379ce --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/container_credential_guard_state.go @@ -0,0 +1,25 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type ContainerCredentialGuardState struct { + + // Authentication cookie for calls to a Container Credential Guard instance. + Cookie string `json:"Cookie,omitempty"` + + // Name of the RPC endpoint of the Container Credential Guard instance. + RpcEndpoint string `json:"RpcEndpoint,omitempty"` + + // Transport used for the configured Container Credential Guard instance. + Transport string `json:"Transport,omitempty"` + + // Credential spec used for the configured Container Credential Guard instance. + CredentialSpec string `json:"CredentialSpec,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/container_memory_information.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/container_memory_information.go new file mode 100644 index 000000000000..754797e213f6 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/container_memory_information.go @@ -0,0 +1,26 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +// memory usage as viewed from within the container +type ContainerMemoryInformation struct { + + TotalPhysicalBytes int32 `json:"TotalPhysicalBytes,omitempty"` + + TotalUsage int32 `json:"TotalUsage,omitempty"` + + CommittedBytes int32 `json:"CommittedBytes,omitempty"` + + SharedCommittedBytes int32 `json:"SharedCommittedBytes,omitempty"` + + CommitLimitBytes int32 `json:"CommitLimitBytes,omitempty"` + + PeakCommitmentBytes int32 `json:"PeakCommitmentBytes,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/device.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/device.go new file mode 100644 index 000000000000..ca319bbbcea2 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/device.go @@ -0,0 +1,16 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type Device struct { + + // The interface class guid of the device to assign to container. + InterfaceClassGuid string `json:"InterfaceClassGuid,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/devices.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/devices.go new file mode 100644 index 000000000000..b2191c571dba --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/devices.go @@ -0,0 +1,43 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type Devices struct { + + ComPorts map[string]ComPort `json:"ComPorts,omitempty"` + + Scsi map[string]Scsi `json:"Scsi,omitempty"` + + VirtualPMem *VirtualPMemController `json:"VirtualPMem,omitempty"` + + NetworkAdapters map[string]NetworkAdapter `json:"NetworkAdapters,omitempty"` + + VideoMonitor *VideoMonitor `json:"VideoMonitor,omitempty"` + + Keyboard *Keyboard `json:"Keyboard,omitempty"` + + Mouse *Mouse `json:"Mouse,omitempty"` + + HvSocket *HvSocket2 `json:"HvSocket,omitempty"` + + EnhancedModeVideo *EnhancedModeVideo `json:"EnhancedModeVideo,omitempty"` + + GuestCrashReporting *GuestCrashReporting `json:"GuestCrashReporting,omitempty"` + + VirtualSmb *VirtualSmb `json:"VirtualSmb,omitempty"` + + Plan9 *Plan9 `json:"Plan9,omitempty"` + + Battery *Battery `json:"Battery,omitempty"` + + FlexibleIov map[string]FlexibleIoDevice `json:"FlexibleIov,omitempty"` + + SharedMemory *SharedMemoryConfiguration `json:"SharedMemory,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/enhanced_mode_video.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/enhanced_mode_video.go new file mode 100644 index 000000000000..4fe592f71176 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/enhanced_mode_video.go @@ -0,0 +1,15 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type EnhancedModeVideo struct { + + ConnectionOptions *RdpConnectionOptions `json:"ConnectionOptions,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/flexible_io_device.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/flexible_io_device.go new file mode 100644 index 000000000000..51011afe407a --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/flexible_io_device.go @@ -0,0 +1,19 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type FlexibleIoDevice struct { + + EmulatorId string `json:"EmulatorId,omitempty"` + + HostingModel string `json:"HostingModel,omitempty"` + + Configuration []string `json:"Configuration,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/guest_connection.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/guest_connection.go new file mode 100644 index 000000000000..7db29495b3e6 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/guest_connection.go @@ -0,0 +1,19 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type GuestConnection struct { + + // Use Vsock rather than Hyper-V sockets to communicate with the guest service. + UseVsock bool `json:"UseVsock,omitempty"` + + // Don't disconnect the guest connection when pausing the virtual machine. + UseConnectedSuspend bool `json:"UseConnectedSuspend,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/guest_connection_info.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/guest_connection_info.go new file mode 100644 index 000000000000..8a369bab71c4 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/guest_connection_info.go @@ -0,0 +1,21 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +// Information about the guest. +type GuestConnectionInfo struct { + + // Each schema version x.y stands for the range of versions a.b where a==x and b<=y. This list comes from the SupportedSchemaVersions field in GcsCapabilities. + SupportedSchemaVersions []Version `json:"SupportedSchemaVersions,omitempty"` + + ProtocolVersion int32 `json:"ProtocolVersion,omitempty"` + + GuestDefinedCapabilities *interface{} `json:"GuestDefinedCapabilities,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/guest_crash_reporting.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/guest_crash_reporting.go new file mode 100644 index 000000000000..c5fa767352e6 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/guest_crash_reporting.go @@ -0,0 +1,15 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type GuestCrashReporting struct { + + WindowsCrashSettings *WindowsCrashReporting `json:"WindowsCrashSettings,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/guest_os.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/guest_os.go new file mode 100644 index 000000000000..c708fc7c3f96 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/guest_os.go @@ -0,0 +1,15 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type GuestOs struct { + + HostName string `json:"HostName,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/guest_state.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/guest_state.go new file mode 100644 index 000000000000..ef1eec88656f --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/guest_state.go @@ -0,0 +1,22 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type GuestState struct { + + // The path to an existing file uses for persistent guest state storage. An empty string indicates the system should initialize new transient, in-memory guest state. + GuestStateFilePath string `json:"GuestStateFilePath,omitempty"` + + // The path to an existing file for persistent runtime state storage. An empty string indicates the system should initialize new transient, in-memory runtime state. + RuntimeStateFilePath string `json:"RuntimeStateFilePath,omitempty"` + + // If true, the guest state and runtime state files will be used as templates to populate transient, in-memory state instead of using the files as persistent backing store. + ForceTransientState bool `json:"ForceTransientState,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/hosted_system.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/hosted_system.go new file mode 100644 index 000000000000..0797584c51d2 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/hosted_system.go @@ -0,0 +1,17 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type HostedSystem struct { + + SchemaVersion *Version `json:"SchemaVersion,omitempty"` + + Container *Container `json:"Container,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/hv_socket.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/hv_socket.go new file mode 100644 index 000000000000..ef9ffb8dd93f --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/hv_socket.go @@ -0,0 +1,17 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type HvSocket struct { + + Config *HvSocketSystemConfig `json:"Config,omitempty"` + + EnablePowerShellDirect bool `json:"EnablePowerShellDirect,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/hv_socket_2.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/hv_socket_2.go new file mode 100644 index 000000000000..a19ba15c15bf --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/hv_socket_2.go @@ -0,0 +1,16 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +// HvSocket configuration for a VM +type HvSocket2 struct { + + HvSocketConfig *HvSocketSystemConfig `json:"HvSocketConfig,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/hv_socket_service_config.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/hv_socket_service_config.go new file mode 100644 index 000000000000..a848e91e69b6 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/hv_socket_service_config.go @@ -0,0 +1,22 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type HvSocketServiceConfig struct { + + // SDDL string that HvSocket will check before allowing a host process to bind to this specific service. If not specified, defaults to the system DefaultBindSecurityDescriptor, defined in HvSocketSystemWpConfig in V1. + BindSecurityDescriptor string `json:"BindSecurityDescriptor,omitempty"` + + // SDDL string that HvSocket will check before allowing a host process to connect to this specific service. If not specified, defaults to the system DefaultConnectSecurityDescriptor, defined in HvSocketSystemWpConfig in V1. + ConnectSecurityDescriptor string `json:"ConnectSecurityDescriptor,omitempty"` + + // If true, HvSocket will process wildcard binds for this service/system combination. Wildcard binds are secured in the registry at SOFTWARE/Microsoft/Windows NT/CurrentVersion/Virtualization/HvSocket/WildcardDescriptors + AllowWildcardBinds bool `json:"AllowWildcardBinds,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/hv_socket_system_config.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/hv_socket_system_config.go new file mode 100644 index 000000000000..69f4f9d39b9a --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/hv_socket_system_config.go @@ -0,0 +1,22 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +// This is the HCS Schema version of the HvSocket configuration. The VMWP version is located in Config.Devices.IC in V1. +type HvSocketSystemConfig struct { + + // SDDL string that HvSocket will check before allowing a host process to bind to an unlisted service for this specific container/VM (not wildcard binds). + DefaultBindSecurityDescriptor string `json:"DefaultBindSecurityDescriptor,omitempty"` + + // SDDL string that HvSocket will check before allowing a host process to connect to an unlisted service in the VM/container. + DefaultConnectSecurityDescriptor string `json:"DefaultConnectSecurityDescriptor,omitempty"` + + ServiceTable map[string]HvSocketServiceConfig `json:"ServiceTable,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/keyboard.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/keyboard.go new file mode 100644 index 000000000000..3d3fa3b1c732 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/keyboard.go @@ -0,0 +1,13 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type Keyboard struct { +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/layer.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/layer.go new file mode 100644 index 000000000000..b63b8ef12c86 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/layer.go @@ -0,0 +1,22 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type Layer struct { + + Id string `json:"Id,omitempty"` + + Path string `json:"Path,omitempty"` + + PathType string `json:"PathType,omitempty"` + + // Unspecified defaults to Enabled + Cache string `json:"Cache,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/linux_kernel_direct.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/linux_kernel_direct.go new file mode 100644 index 000000000000..0ab6c280fc8d --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/linux_kernel_direct.go @@ -0,0 +1,18 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.2 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type LinuxKernelDirect struct { + KernelFilePath string `json:"KernelFilePath,omitempty"` + + InitRdPath string `json:"InitRdPath,omitempty"` + + KernelCmdLine string `json:"KernelCmdLine,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/mapped_directory.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/mapped_directory.go new file mode 100644 index 000000000000..a823a6d3b894 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/mapped_directory.go @@ -0,0 +1,21 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type MappedDirectory struct { + + HostPath string `json:"HostPath,omitempty"` + + HostPathType string `json:"HostPathType,omitempty"` + + ContainerPath string `json:"ContainerPath,omitempty"` + + ReadOnly bool `json:"ReadOnly,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/mapped_pipe.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/mapped_pipe.go new file mode 100644 index 000000000000..2d1d2604a9b0 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/mapped_pipe.go @@ -0,0 +1,19 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type MappedPipe struct { + + ContainerPipeName string `json:"ContainerPipeName,omitempty"` + + HostPath string `json:"HostPath,omitempty"` + + HostPathType string `json:"HostPathType,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/memory.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/memory.go new file mode 100644 index 000000000000..e1d135a3a4b6 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/memory.go @@ -0,0 +1,15 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type Memory struct { + + SizeInMB int32 `json:"SizeInMB,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/memory_2.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/memory_2.go new file mode 100644 index 000000000000..27d0b8c48387 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/memory_2.go @@ -0,0 +1,25 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type Memory2 struct { + SizeInMB int32 `json:"SizeInMB,omitempty"` + + AllowOvercommit bool `json:"AllowOvercommit,omitempty"` + + EnableHotHint bool `json:"EnableHotHint,omitempty"` + + EnableColdHint bool `json:"EnableColdHint,omitempty"` + + EnableEpf bool `json:"EnableEpf,omitempty"` + + // EnableDeferredCommit is private in the schema. If regenerated need to add back. + EnableDeferredCommit bool `json:"EnableDeferredCommit,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/memory_information_for_vm.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/memory_information_for_vm.go new file mode 100644 index 000000000000..bdd87dffd85a --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/memory_information_for_vm.go @@ -0,0 +1,19 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type MemoryInformationForVm struct { + + VirtualNodeCount int32 `json:"VirtualNodeCount,omitempty"` + + VirtualMachineMemory *VmMemory `json:"VirtualMachineMemory,omitempty"` + + VirtualNodes []VirtualNodeInfo `json:"VirtualNodes,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/memory_stats.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/memory_stats.go new file mode 100644 index 000000000000..6214970f6972 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/memory_stats.go @@ -0,0 +1,20 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +// Memory runtime statistics +type MemoryStats struct { + + MemoryUsageCommitBytes int32 `json:"MemoryUsageCommitBytes,omitempty"` + + MemoryUsageCommitPeakBytes int32 `json:"MemoryUsageCommitPeakBytes,omitempty"` + + MemoryUsagePrivateWorkingSetBytes int32 `json:"MemoryUsagePrivateWorkingSetBytes,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/modify_setting_request.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/modify_setting_request.go new file mode 100644 index 000000000000..d29455a3e434 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/modify_setting_request.go @@ -0,0 +1,20 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type ModifySettingRequest struct { + ResourcePath string `json:"ResourcePath,omitempty"` + + RequestType string `json:"RequestType,omitempty"` + + Settings interface{} `json:"Settings,omitempty"` // NOTE: Swagger generated as *interface{}. Locally updated + + GuestRequest interface{} `json:"GuestRequest,omitempty"` // NOTE: Swagger generated as *interface{}. Locally updated +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/mouse.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/mouse.go new file mode 100644 index 000000000000..ccf8b938f3ac --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/mouse.go @@ -0,0 +1,13 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type Mouse struct { +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/network_adapter.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/network_adapter.go new file mode 100644 index 000000000000..c586f66c251b --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/network_adapter.go @@ -0,0 +1,17 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type NetworkAdapter struct { + + EndpointId string `json:"EndpointId,omitempty"` + + MacAddress string `json:"MacAddress,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/networking.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/networking.go new file mode 100644 index 000000000000..12c47827c5db --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/networking.go @@ -0,0 +1,24 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type Networking struct { + + AllowUnqualifiedDnsQuery bool `json:"AllowUnqualifiedDnsQuery,omitempty"` + + DnsSearchList string `json:"DnsSearchList,omitempty"` + + NetworkSharedContainerName string `json:"NetworkSharedContainerName,omitempty"` + + // Guid in windows; string in linux + Namespace string `json:"Namespace,omitempty"` + + NetworkAdapters []string `json:"NetworkAdapters,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/pause_notification.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/pause_notification.go new file mode 100644 index 000000000000..1cd70d17902e --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/pause_notification.go @@ -0,0 +1,16 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +// Notification data that is indicated to components running in the Virtual Machine. +type PauseNotification struct { + + Reason string `json:"Reason,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/pause_options.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/pause_options.go new file mode 100644 index 000000000000..780a5cae2c1c --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/pause_options.go @@ -0,0 +1,18 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +// Options for HcsPauseComputeSystem +type PauseOptions struct { + + SuspensionLevel string `json:"SuspensionLevel,omitempty"` + + HostedNotification *PauseNotification `json:"HostedNotification,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/plan9.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/plan9.go new file mode 100644 index 000000000000..705c677e1f81 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/plan9.go @@ -0,0 +1,15 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type Plan9 struct { + + Shares []Plan9Share `json:"Shares,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/plan9_share.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/plan9_share.go new file mode 100644 index 000000000000..eb171817a693 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/plan9_share.go @@ -0,0 +1,33 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type Plan9Share struct { + + Name string `json:"Name,omitempty"` + + // The name by which the guest operation system can access this share, via the aname parameter in the Plan9 protocol. + AccessName string `json:"AccessName,omitempty"` + + Path string `json:"Path,omitempty"` + + Port int32 `json:"Port,omitempty"` + + // Flags are marked private. Until they are exported correctly + // + // ReadOnly 0x00000001 + // LinuxMetadata 0x00000004 + // CaseSensitive 0x00000008 + Flags int32 `json:"Flags,omitempty"` + + ReadOnly bool `json:"ReadOnly,omitempty"` + + UseShareRootIdentity bool `json:"UseShareRootIdentity,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/process_details.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/process_details.go new file mode 100644 index 000000000000..63e0b7f8fe5f --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/process_details.go @@ -0,0 +1,34 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +import ( + "time" +) + +// Information about a process running in a container +type ProcessDetails struct { + + ProcessId int32 `json:"ProcessId,omitempty"` + + ImageName string `json:"ImageName,omitempty"` + + CreateTimestamp time.Time `json:"CreateTimestamp,omitempty"` + + UserTime100ns int32 `json:"UserTime100ns,omitempty"` + + KernelTime100ns int32 `json:"KernelTime100ns,omitempty"` + + MemoryCommitBytes int32 `json:"MemoryCommitBytes,omitempty"` + + MemoryWorkingSetPrivateBytes int32 `json:"MemoryWorkingSetPrivateBytes,omitempty"` + + MemoryWorkingSetSharedBytes int32 `json:"MemoryWorkingSetSharedBytes,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/process_modify_request.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/process_modify_request.go new file mode 100644 index 000000000000..29bc2e3d00bb --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/process_modify_request.go @@ -0,0 +1,20 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +// Passed to HcsRpc_ModifyProcess +type ProcessModifyRequest struct { + + Operation string `json:"Operation,omitempty"` + + ConsoleSize *ConsoleSize `json:"ConsoleSize,omitempty"` + + CloseHandle *CloseHandle `json:"CloseHandle,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/process_parameters.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/process_parameters.go new file mode 100644 index 000000000000..470c55734ed3 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/process_parameters.go @@ -0,0 +1,47 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type ProcessParameters struct { + + ApplicationName string `json:"ApplicationName,omitempty"` + + CommandLine string `json:"CommandLine,omitempty"` + + // optional alternative to CommandLine, currently only supported by Linux GCS + CommandArgs []string `json:"CommandArgs,omitempty"` + + User string `json:"User,omitempty"` + + WorkingDirectory string `json:"WorkingDirectory,omitempty"` + + Environment map[string]string `json:"Environment,omitempty"` + + // if set, will run as low-privilege process + RestrictedToken bool `json:"RestrictedToken,omitempty"` + + // if set, ignore StdErrPipe + EmulateConsole bool `json:"EmulateConsole,omitempty"` + + CreateStdInPipe bool `json:"CreateStdInPipe,omitempty"` + + CreateStdOutPipe bool `json:"CreateStdOutPipe,omitempty"` + + CreateStdErrPipe bool `json:"CreateStdErrPipe,omitempty"` + + // height then width + ConsoleSize []int32 `json:"ConsoleSize,omitempty"` + + // if set, find an existing session for the user and create the process in it + UseExistingLogin bool `json:"UseExistingLogin,omitempty"` + + // if set, use the legacy console instead of conhost + UseLegacyConsole bool `json:"UseLegacyConsole,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/process_status.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/process_status.go new file mode 100644 index 000000000000..20793d1503bd --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/process_status.go @@ -0,0 +1,22 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +// Status of a process running in a container +type ProcessStatus struct { + + ProcessId int32 `json:"ProcessId,omitempty"` + + Exited bool `json:"Exited,omitempty"` + + ExitCode int32 `json:"ExitCode,omitempty"` + + LastWaitResult int32 `json:"LastWaitResult,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/processor.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/processor.go new file mode 100644 index 000000000000..7a60b0245aa9 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/processor.go @@ -0,0 +1,19 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type Processor struct { + + Count int32 `json:"Count,omitempty"` + + Maximum int32 `json:"Maximum,omitempty"` + + Weight int32 `json:"Weight,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/processor_2.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/processor_2.go new file mode 100644 index 000000000000..40d3e7356d5a --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/processor_2.go @@ -0,0 +1,21 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type Processor2 struct { + + Count int32 `json:"Count,omitempty"` + + Limit int32 `json:"Limit,omitempty"` + + Weight int32 `json:"Weight,omitempty"` + + ExposeVirtualizationExtensions bool `json:"ExposeVirtualizationExtensions,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/processor_stats.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/processor_stats.go new file mode 100644 index 000000000000..9d3b77e57286 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/processor_stats.go @@ -0,0 +1,20 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +// CPU runtime statistics +type ProcessorStats struct { + + TotalRuntime100ns int32 `json:"TotalRuntime100ns,omitempty"` + + RuntimeUser100ns int32 `json:"RuntimeUser100ns,omitempty"` + + RuntimeKernel100ns int32 `json:"RuntimeKernel100ns,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/properties.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/properties.go new file mode 100644 index 000000000000..6db2a48f66c9 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/properties.go @@ -0,0 +1,47 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type Properties struct { + + Id string `json:"Id,omitempty"` + + SystemType string `json:"SystemType,omitempty"` + + RuntimeOsType string `json:"RuntimeOsType,omitempty"` + + Name string `json:"Name,omitempty"` + + Owner string `json:"Owner,omitempty"` + + RuntimeId string `json:"RuntimeId,omitempty"` + + RuntimeTemplateId string `json:"RuntimeTemplateId,omitempty"` + + State string `json:"State,omitempty"` + + Stopped bool `json:"Stopped,omitempty"` + + ExitType string `json:"ExitType,omitempty"` + + Memory *MemoryInformationForVm `json:"Memory,omitempty"` + + Statistics *Statistics `json:"Statistics,omitempty"` + + ProcessList []ProcessDetails `json:"ProcessList,omitempty"` + + TerminateOnLastHandleClosed bool `json:"TerminateOnLastHandleClosed,omitempty"` + + HostingSystemId string `json:"HostingSystemId,omitempty"` + + SharedMemoryRegionInfo []SharedMemoryRegionInfo `json:"SharedMemoryRegionInfo,omitempty"` + + GuestConnectionInfo *GuestConnectionInfo `json:"GuestConnectionInfo,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/property_query.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/property_query.go new file mode 100644 index 000000000000..22b92ffdfd46 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/property_query.go @@ -0,0 +1,16 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +// By default the basic properties will be returned. This query provides a way to request specific properties. +type PropertyQuery struct { + + PropertyTypes []string `json:"PropertyTypes,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/rdp_connection_options.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/rdp_connection_options.go new file mode 100644 index 000000000000..97e453128342 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/rdp_connection_options.go @@ -0,0 +1,17 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type RdpConnectionOptions struct { + + AccessSids []string `json:"AccessSids,omitempty"` + + NamedPipe string `json:"NamedPipe,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/registry_changes.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/registry_changes.go new file mode 100644 index 000000000000..fa574ccc801b --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/registry_changes.go @@ -0,0 +1,17 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type RegistryChanges struct { + + AddValues []RegistryValue `json:"AddValues,omitempty"` + + DeleteKeys []RegistryKey `json:"DeleteKeys,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/registry_key.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/registry_key.go new file mode 100644 index 000000000000..fab03bc60bee --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/registry_key.go @@ -0,0 +1,19 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type RegistryKey struct { + + Hive string `json:"Hive,omitempty"` + + Name string `json:"Name,omitempty"` + + Volatile bool `json:"Volatile,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/registry_value.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/registry_value.go new file mode 100644 index 000000000000..1589f4841340 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/registry_value.go @@ -0,0 +1,31 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type RegistryValue struct { + + Key *RegistryKey `json:"Key,omitempty"` + + Name string `json:"Name,omitempty"` + + Type_ string `json:"Type,omitempty"` + + // One and only one value type must be set. + StringValue string `json:"StringValue,omitempty"` + + BinaryValue string `json:"BinaryValue,omitempty"` + + DWordValue int32 `json:"DWordValue,omitempty"` + + QWordValue int32 `json:"QWordValue,omitempty"` + + // Only used if RegistryValueType is CustomType The data is in BinaryValue + CustomType int32 `json:"CustomType,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/restore_state.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/restore_state.go new file mode 100644 index 000000000000..778ff58735aa --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/restore_state.go @@ -0,0 +1,19 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type RestoreState struct { + + // The path to the save state file to restore the system from. + SaveStateFilePath string `json:"SaveStateFilePath,omitempty"` + + // The ID of the template system to clone this new system off of. An empty string indicates the system should not be cloned from a template. + TemplateSystemId string `json:"TemplateSystemId,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/save_options.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/save_options.go new file mode 100644 index 000000000000..e55fa1d98a5b --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/save_options.go @@ -0,0 +1,19 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type SaveOptions struct { + + // The type of save operation to be performed. + SaveType string `json:"SaveType,omitempty"` + + // The path to the file that will container the saved state. + SaveStateFilePath string `json:"SaveStateFilePath,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/scsi.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/scsi.go new file mode 100644 index 000000000000..bf253a470b65 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/scsi.go @@ -0,0 +1,16 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type Scsi struct { + + // Map of attachments, where the key is the integer LUN number on the controller. + Attachments map[string]Attachment `json:"Attachments,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/shared_memory_configuration.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/shared_memory_configuration.go new file mode 100644 index 000000000000..bd573f6cd4e3 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/shared_memory_configuration.go @@ -0,0 +1,15 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type SharedMemoryConfiguration struct { + + Regions []SharedMemoryRegion `json:"Regions,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/shared_memory_region.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/shared_memory_region.go new file mode 100644 index 000000000000..a57b2cba73b8 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/shared_memory_region.go @@ -0,0 +1,23 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type SharedMemoryRegion struct { + + SectionName string `json:"SectionName,omitempty"` + + StartOffset int32 `json:"StartOffset,omitempty"` + + Length int32 `json:"Length,omitempty"` + + AllowGuestWrite bool `json:"AllowGuestWrite,omitempty"` + + HiddenFromGuest bool `json:"HiddenFromGuest,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/shared_memory_region_info.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/shared_memory_region_info.go new file mode 100644 index 000000000000..d9a50cc7da88 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/shared_memory_region_info.go @@ -0,0 +1,17 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type SharedMemoryRegionInfo struct { + + SectionName string `json:"SectionName,omitempty"` + + GuestPhysicalAddress int32 `json:"GuestPhysicalAddress,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/silo_properties.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/silo_properties.go new file mode 100644 index 000000000000..599c06e8aa13 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/silo_properties.go @@ -0,0 +1,18 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +// Silo job information +type SiloProperties struct { + + Enabled bool `json:"Enabled,omitempty"` + + JobName string `json:"JobName,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/statistics.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/statistics.go new file mode 100644 index 000000000000..5cb3ed93b598 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/statistics.go @@ -0,0 +1,30 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +import ( + "time" +) + +// Runtime statistics for a container +type Statistics struct { + + Timestamp time.Time `json:"Timestamp,omitempty"` + + ContainerStartTime time.Time `json:"ContainerStartTime,omitempty"` + + Uptime100ns int32 `json:"Uptime100ns,omitempty"` + + Processor *ProcessorStats `json:"Processor,omitempty"` + + Memory *MemoryStats `json:"Memory,omitempty"` + + Storage *StorageStats `json:"Storage,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/storage.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/storage.go new file mode 100644 index 000000000000..2627af91323e --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/storage.go @@ -0,0 +1,21 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type Storage struct { + + // List of layers that describe the parent hierarchy for a container's storage. These layers combined together, presented as a disposable and/or committable working storage, are used by the container to record all changes done to the parent layers. + Layers []Layer `json:"Layers,omitempty"` + + // Path that points to the scratch space of a container, where parent layers are combined together to present a new disposable and/or committable layer with the changes done during its runtime. + Path string `json:"Path,omitempty"` + + QoS *StorageQoS `json:"QoS,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/storage_qo_s.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/storage_qo_s.go new file mode 100644 index 000000000000..8c5255df1e39 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/storage_qo_s.go @@ -0,0 +1,17 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type StorageQoS struct { + + IopsMaximum int32 `json:"IopsMaximum,omitempty"` + + BandwidthMaximum int32 `json:"BandwidthMaximum,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/storage_stats.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/storage_stats.go new file mode 100644 index 000000000000..198ea57d7506 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/storage_stats.go @@ -0,0 +1,22 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +// Storage runtime statistics +type StorageStats struct { + + ReadCountNormalized int32 `json:"ReadCountNormalized,omitempty"` + + ReadSizeBytes int32 `json:"ReadSizeBytes,omitempty"` + + WriteCountNormalized int32 `json:"WriteCountNormalized,omitempty"` + + WriteSizeBytes int32 `json:"WriteSizeBytes,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/topology.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/topology.go new file mode 100644 index 000000000000..af2e3c823464 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/topology.go @@ -0,0 +1,17 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type Topology struct { + + Memory *Memory2 `json:"Memory,omitempty"` + + Processor *Processor2 `json:"Processor,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/uefi.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/uefi.go new file mode 100644 index 000000000000..ba91178f96cd --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/uefi.go @@ -0,0 +1,21 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type Uefi struct { + + EnableDebugger bool `json:"EnableDebugger,omitempty"` + + SecureBootTemplateId string `json:"SecureBootTemplateId,omitempty"` + + BootThis *UefiBootEntry `json:"BootThis,omitempty"` + + Console string `json:"Console,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/uefi_boot_entry.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/uefi_boot_entry.go new file mode 100644 index 000000000000..6620fb2bcf8d --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/uefi_boot_entry.go @@ -0,0 +1,23 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type UefiBootEntry struct { + + DeviceType string `json:"DeviceType,omitempty"` + + DevicePath string `json:"DevicePath,omitempty"` + + DiskNumber int32 `json:"DiskNumber,omitempty"` + + OptionalData string `json:"OptionalData,omitempty"` + + VmbFsRootPath string `json:"VmbFsRootPath,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/version.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/version.go new file mode 100644 index 000000000000..62c0e4d12abb --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/version.go @@ -0,0 +1,17 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type Version struct { + + Major int32 `json:"Major,omitempty"` + + Minor int32 `json:"Minor,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/video_monitor.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/video_monitor.go new file mode 100644 index 000000000000..0958e5606250 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/video_monitor.go @@ -0,0 +1,19 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type VideoMonitor struct { + + HorizontalResolution int32 `json:"HorizontalResolution,omitempty"` + + VerticalResolution int32 `json:"VerticalResolution,omitempty"` + + ConnectionOptions *RdpConnectionOptions `json:"ConnectionOptions,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/virtual_machine.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/virtual_machine.go new file mode 100644 index 000000000000..2d22b1bcb084 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/virtual_machine.go @@ -0,0 +1,32 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type VirtualMachine struct { + + // StopOnReset is private in the schema. If regenerated need to put back. + StopOnReset bool `json:"StopOnReset,omitempty"` + + Chipset *Chipset `json:"Chipset,omitempty"` + + ComputeTopology *Topology `json:"ComputeTopology,omitempty"` + + Devices *Devices `json:"Devices,omitempty"` + + GuestState *GuestState `json:"GuestState,omitempty"` + + RestoreState *RestoreState `json:"RestoreState,omitempty"` + + RegistryChanges *RegistryChanges `json:"RegistryChanges,omitempty"` + + StorageQoS *StorageQoS `json:"StorageQoS,omitempty"` + + GuestConnection *GuestConnection `json:"GuestConnection,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/virtual_node_info.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/virtual_node_info.go new file mode 100644 index 000000000000..48402d8ecb14 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/virtual_node_info.go @@ -0,0 +1,21 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type VirtualNodeInfo struct { + + VirtualNodeIndex int32 `json:"VirtualNodeIndex,omitempty"` + + PhysicalNodeNumber int32 `json:"PhysicalNodeNumber,omitempty"` + + VirtualProcessorCount int32 `json:"VirtualProcessorCount,omitempty"` + + MemoryUsageInPages int32 `json:"MemoryUsageInPages,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/virtual_p_mem_controller.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/virtual_p_mem_controller.go new file mode 100644 index 000000000000..f5b7f3e38c0f --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/virtual_p_mem_controller.go @@ -0,0 +1,20 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type VirtualPMemController struct { + Devices map[string]VirtualPMemDevice `json:"Devices,omitempty"` + + MaximumCount uint32 `json:"MaximumCount,omitempty"` + + MaximumSizeBytes uint64 `json:"MaximumSizeBytes,omitempty"` + + Backing string `json:"Backing,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/virtual_p_mem_device.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/virtual_p_mem_device.go new file mode 100644 index 000000000000..47714444aa09 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/virtual_p_mem_device.go @@ -0,0 +1,19 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type VirtualPMemDevice struct { + + HostPath string `json:"HostPath,omitempty"` + + ReadOnly bool `json:"ReadOnly,omitempty"` + + ImageFormat string `json:"ImageFormat,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/virtual_smb.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/virtual_smb.go new file mode 100644 index 000000000000..76131b3a71ac --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/virtual_smb.go @@ -0,0 +1,17 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type VirtualSmb struct { + + Shares []VirtualSmbShare `json:"Shares,omitempty"` + + DirectFileMappingInMB int64 `json:"DirectFileMappingInMB,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/virtual_smb_share.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/virtual_smb_share.go new file mode 100644 index 000000000000..b50098a4232f --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/virtual_smb_share.go @@ -0,0 +1,21 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type VirtualSmbShare struct { + + Name string `json:"Name,omitempty"` + + Path string `json:"Path,omitempty"` + + AllowedFiles []string `json:"AllowedFiles,omitempty"` + + Options *VirtualSmbShareOptions `json:"Options,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/virtual_smb_share_options.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/virtual_smb_share_options.go new file mode 100644 index 000000000000..c1894279dc85 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/virtual_smb_share_options.go @@ -0,0 +1,63 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type VirtualSmbShareOptions struct { + + ReadOnly bool `json:"ReadOnly,omitempty"` + + // convert exclusive access to shared read access + ShareRead bool `json:"ShareRead,omitempty"` + + // all opens will use cached I/O + CacheIo bool `json:"CacheIo,omitempty"` + + // disable oplock support + NoOplocks bool `json:"NoOplocks,omitempty"` + + // Acquire the backup privilege when attempting to open + TakeBackupPrivilege bool `json:"TakeBackupPrivilege,omitempty"` + + // Use the identity of the share root when opening + UseShareRootIdentity bool `json:"UseShareRootIdentity,omitempty"` + + // disable Direct Mapping + NoDirectmap bool `json:"NoDirectmap,omitempty"` + + // disable Byterange locks + NoLocks bool `json:"NoLocks,omitempty"` + + // disable Directory CHange Notifications + NoDirnotify bool `json:"NoDirnotify,omitempty"` + + // share is use for VM shared memory + VmSharedMemory bool `json:"VmSharedMemory,omitempty"` + + // allow access only to the files specified in AllowedFiles + RestrictFileAccess bool `json:"RestrictFileAccess,omitempty"` + + // disable all oplocks except Level II + ForceLevelIIOplocks bool `json:"ForceLevelIIOplocks,omitempty"` + + // Allow the host to reparse this base layer + ReparseBaseLayer bool `json:"ReparseBaseLayer,omitempty"` + + // Enable pseudo-oplocks + PseudoOplocks bool `json:"PseudoOplocks,omitempty"` + + // All opens will use non-cached IO + NonCacheIo bool `json:"NonCacheIo,omitempty"` + + // Enable pseudo directory change notifications + PseudoDirnotify bool `json:"PseudoDirnotify,omitempty"` + + // Block directory enumeration, renames, and deletes. + SingleFileMapping bool `json:"SingleFileMapping,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/vm_memory.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/vm_memory.go new file mode 100644 index 000000000000..39f628667cd0 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/vm_memory.go @@ -0,0 +1,27 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type VmMemory struct { + + AvailableMemory int32 `json:"AvailableMemory,omitempty"` + + AvailableMemoryBuffer int32 `json:"AvailableMemoryBuffer,omitempty"` + + ReservedMemory int32 `json:"ReservedMemory,omitempty"` + + AssignedMemory int32 `json:"AssignedMemory,omitempty"` + + SlpActive bool `json:"SlpActive,omitempty"` + + BalancingEnabled bool `json:"BalancingEnabled,omitempty"` + + DmOperationInProgress bool `json:"DmOperationInProgress,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/schema2/windows_crash_reporting.go b/vendor/github.com/Microsoft/hcsshim/internal/schema2/windows_crash_reporting.go new file mode 100644 index 000000000000..cf632bbc8343 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/schema2/windows_crash_reporting.go @@ -0,0 +1,17 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.1 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type WindowsCrashReporting struct { + + DumpFileName string `json:"DumpFileName,omitempty"` + + MaxDumpSize int64 `json:"MaxDumpSize,omitempty"` +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/timeout/timeout.go b/vendor/github.com/Microsoft/hcsshim/internal/timeout/timeout.go new file mode 100644 index 000000000000..ff3b6572e659 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/timeout/timeout.go @@ -0,0 +1,70 @@ +package timeout + +import ( + "os" + "strconv" + "time" +) + +var ( + // defaultTimeout is the timeout for most operations that is not overridden. + defaultTimeout = 4 * time.Minute + + // defaultTimeoutTestdRetry is the retry loop timeout for testd to respond + // for a disk to come online in LCOW. + defaultTimeoutTestdRetry = 5 * time.Second +) + +// External variables for HCSShim consumers to use. +var ( + // SystemCreate is the timeout for creating a compute system + SystemCreate time.Duration = defaultTimeout + + // SystemStart is the timeout for starting a compute system + SystemStart time.Duration = defaultTimeout + + // SystemPause is the timeout for pausing a compute system + SystemPause time.Duration = defaultTimeout + + // SystemResume is the timeout for resuming a compute system + SystemResume time.Duration = defaultTimeout + + // SyscallWatcher is the timeout before warning of a potential stuck platform syscall. + SyscallWatcher time.Duration = defaultTimeout + + // Tar2VHD is the timeout for the tar2vhd operation to complete + Tar2VHD time.Duration = defaultTimeout + + // ExternalCommandToStart is the timeout for external commands to start + ExternalCommandToStart = defaultTimeout + + // ExternalCommandToComplete is the timeout for external commands to complete. + // Generally this means copying data from their stdio pipes. + ExternalCommandToComplete = defaultTimeout + + // TestDRetryLoop is the timeout for testd retry loop when onlining a SCSI disk in LCOW + TestDRetryLoop = defaultTimeoutTestdRetry +) + +func init() { + SystemCreate = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSTEMCREATE", SystemCreate) + SystemStart = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSTEMSTART", SystemStart) + SystemPause = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSTEMPAUSE", SystemPause) + SystemResume = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSTEMRESUME", SystemResume) + SyscallWatcher = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSCALLWATCHER", SyscallWatcher) + Tar2VHD = durationFromEnvironment("HCSSHIM_TIMEOUT_TAR2VHD", Tar2VHD) + ExternalCommandToStart = durationFromEnvironment("HCSSHIM_TIMEOUT_EXTERNALCOMMANDSTART", ExternalCommandToStart) + ExternalCommandToComplete = durationFromEnvironment("HCSSHIM_TIMEOUT_EXTERNALCOMMANDCOMPLETE", ExternalCommandToComplete) + TestDRetryLoop = durationFromEnvironment("HCSSHIM_TIMEOUT_TESTDRETRYLOOP", TestDRetryLoop) +} + +func durationFromEnvironment(env string, defaultValue time.Duration) time.Duration { + envTimeout := os.Getenv(env) + if len(envTimeout) > 0 { + e, err := strconv.Atoi(envTimeout) + if err == nil && e > 0 { + return time.Second * time.Duration(e) + } + } + return defaultValue +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/activatelayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/activatelayer.go new file mode 100644 index 000000000000..dcb9192685a5 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/activatelayer.go @@ -0,0 +1,32 @@ +package wclayer + +import ( + "github.com/Microsoft/hcsshim/internal/hcserror" + "github.com/sirupsen/logrus" +) + +// ActivateLayer will find the layer with the given id and mount it's filesystem. +// For a read/write layer, the mounted filesystem will appear as a volume on the +// host, while a read-only layer is generally expected to be a no-op. +// An activated layer must later be deactivated via DeactivateLayer. +func ActivateLayer(path string) (err error) { + title := "hcsshim::ActivateLayer" + fields := logrus.Fields{ + "path": path, + } + logrus.WithFields(fields).Debug(title) + defer func() { + if err != nil { + fields[logrus.ErrorKey] = err + logrus.WithFields(fields).Error(err) + } else { + logrus.WithFields(fields).Debug(title + " - succeeded") + } + }() + + err = activateLayer(&stdDriverInfo, path) + if err != nil { + return hcserror.New(err, title+" - failed", "") + } + return nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/baselayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/baselayer.go new file mode 100644 index 000000000000..5784241dfa03 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/baselayer.go @@ -0,0 +1,173 @@ +package wclayer + +import ( + "errors" + "os" + "path/filepath" + "syscall" + + "github.com/Microsoft/go-winio" + "github.com/Microsoft/hcsshim/internal/hcserror" + "github.com/Microsoft/hcsshim/internal/safefile" +) + +type baseLayerWriter struct { + root *os.File + f *os.File + bw *winio.BackupFileWriter + err error + hasUtilityVM bool + dirInfo []dirInfo +} + +type dirInfo struct { + path string + fileInfo winio.FileBasicInfo +} + +// reapplyDirectoryTimes reapplies directory modification, creation, etc. times +// after processing of the directory tree has completed. The times are expected +// to be ordered such that parent directories come before child directories. +func reapplyDirectoryTimes(root *os.File, dis []dirInfo) error { + for i := range dis { + di := &dis[len(dis)-i-1] // reverse order: process child directories first + f, err := safefile.OpenRelative(di.path, root, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.FILE_SHARE_READ, safefile.FILE_OPEN, safefile.FILE_DIRECTORY_FILE) + if err != nil { + return err + } + + err = winio.SetFileBasicInfo(f, &di.fileInfo) + f.Close() + if err != nil { + return err + } + } + return nil +} + +func (w *baseLayerWriter) closeCurrentFile() error { + if w.f != nil { + err := w.bw.Close() + err2 := w.f.Close() + w.f = nil + w.bw = nil + if err != nil { + return err + } + if err2 != nil { + return err2 + } + } + return nil +} + +func (w *baseLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) (err error) { + defer func() { + if err != nil { + w.err = err + } + }() + + err = w.closeCurrentFile() + if err != nil { + return err + } + + if filepath.ToSlash(name) == `UtilityVM/Files` { + w.hasUtilityVM = true + } + + var f *os.File + defer func() { + if f != nil { + f.Close() + } + }() + + extraFlags := uint32(0) + if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 { + extraFlags |= safefile.FILE_DIRECTORY_FILE + if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 { + w.dirInfo = append(w.dirInfo, dirInfo{name, *fileInfo}) + } + } + + mode := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | winio.WRITE_DAC | winio.WRITE_OWNER | winio.ACCESS_SYSTEM_SECURITY) + f, err = safefile.OpenRelative(name, w.root, mode, syscall.FILE_SHARE_READ, safefile.FILE_CREATE, extraFlags) + if err != nil { + return hcserror.New(err, "Failed to safefile.OpenRelative", name) + } + + err = winio.SetFileBasicInfo(f, fileInfo) + if err != nil { + return hcserror.New(err, "Failed to SetFileBasicInfo", name) + } + + w.f = f + w.bw = winio.NewBackupFileWriter(f, true) + f = nil + return nil +} + +func (w *baseLayerWriter) AddLink(name string, target string) (err error) { + defer func() { + if err != nil { + w.err = err + } + }() + + err = w.closeCurrentFile() + if err != nil { + return err + } + + return safefile.LinkRelative(target, w.root, name, w.root) +} + +func (w *baseLayerWriter) Remove(name string) error { + return errors.New("base layer cannot have tombstones") +} + +func (w *baseLayerWriter) Write(b []byte) (int, error) { + n, err := w.bw.Write(b) + if err != nil { + w.err = err + } + return n, err +} + +func (w *baseLayerWriter) Close() error { + defer func() { + w.root.Close() + w.root = nil + }() + err := w.closeCurrentFile() + if err != nil { + return err + } + if w.err == nil { + // Restore the file times of all the directories, since they may have + // been modified by creating child directories. + err = reapplyDirectoryTimes(w.root, w.dirInfo) + if err != nil { + return err + } + + err = ProcessBaseLayer(w.root.Name()) + if err != nil { + return err + } + + if w.hasUtilityVM { + err := safefile.EnsureNotReparsePointRelative("UtilityVM", w.root) + if err != nil { + return err + } + err = ProcessUtilityVMImage(filepath.Join(w.root.Name(), "UtilityVM")) + if err != nil { + return err + } + } + } + return w.err +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/createlayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/createlayer.go new file mode 100644 index 000000000000..be2bc3fd650b --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/createlayer.go @@ -0,0 +1,31 @@ +package wclayer + +import ( + "github.com/Microsoft/hcsshim/internal/hcserror" + "github.com/sirupsen/logrus" +) + +// CreateLayer creates a new, empty, read-only layer on the filesystem based on +// the parent layer provided. +func CreateLayer(path, parent string) (err error) { + title := "hcsshim::CreateLayer" + fields := logrus.Fields{ + "parent": parent, + "path": path, + } + logrus.WithFields(fields).Debug(title) + defer func() { + if err != nil { + fields[logrus.ErrorKey] = err + logrus.WithFields(fields).Error(err) + } else { + logrus.WithFields(fields).Debug(title + " - succeeded") + } + }() + + err = createLayer(&stdDriverInfo, path, parent) + if err != nil { + return hcserror.New(err, title+" - failed", "") + } + return nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/createscratchlayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/createscratchlayer.go new file mode 100644 index 000000000000..7e3351289e67 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/createscratchlayer.go @@ -0,0 +1,38 @@ +package wclayer + +import ( + "github.com/Microsoft/hcsshim/internal/hcserror" + "github.com/sirupsen/logrus" +) + +// CreateScratchLayer creates and populates new read-write layer for use by a container. +// This requires both the id of the direct parent layer, as well as the full list +// of paths to all parent layers up to the base (and including the direct parent +// whose id was provided). +func CreateScratchLayer(path string, parentLayerPaths []string) (err error) { + title := "hcsshim::CreateScratchLayer" + fields := logrus.Fields{ + "path": path, + } + logrus.WithFields(fields).Debug(title) + defer func() { + if err != nil { + fields[logrus.ErrorKey] = err + logrus.WithFields(fields).Error(err) + } else { + logrus.WithFields(fields).Debug(title + " - succeeded") + } + }() + + // Generate layer descriptors + layers, err := layerPathsToDescriptors(parentLayerPaths) + if err != nil { + return err + } + + err = createSandboxLayer(&stdDriverInfo, path, 0, layers) + if err != nil { + return hcserror.New(err, title+" - failed", "") + } + return nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/deactivatelayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/deactivatelayer.go new file mode 100644 index 000000000000..2dd5d5715925 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/deactivatelayer.go @@ -0,0 +1,29 @@ +package wclayer + +import ( + "github.com/Microsoft/hcsshim/internal/hcserror" + "github.com/sirupsen/logrus" +) + +// DeactivateLayer will dismount a layer that was mounted via ActivateLayer. +func DeactivateLayer(path string) (err error) { + title := "hcsshim::DeactivateLayer" + fields := logrus.Fields{ + "path": path, + } + logrus.WithFields(fields).Debug(title) + defer func() { + if err != nil { + fields[logrus.ErrorKey] = err + logrus.WithFields(fields).Error(err) + } else { + logrus.WithFields(fields).Debug(title + " - succeeded") + } + }() + + err = deactivateLayer(&stdDriverInfo, path) + if err != nil { + return hcserror.New(err, title+"- failed", "") + } + return nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/destroylayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/destroylayer.go new file mode 100644 index 000000000000..4da690c20305 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/destroylayer.go @@ -0,0 +1,30 @@ +package wclayer + +import ( + "github.com/Microsoft/hcsshim/internal/hcserror" + "github.com/sirupsen/logrus" +) + +// DestroyLayer will remove the on-disk files representing the layer with the given +// path, including that layer's containing folder, if any. +func DestroyLayer(path string) (err error) { + title := "hcsshim::DestroyLayer" + fields := logrus.Fields{ + "path": path, + } + logrus.WithFields(fields).Debug(title) + defer func() { + if err != nil { + fields[logrus.ErrorKey] = err + logrus.WithFields(fields).Error(err) + } else { + logrus.WithFields(fields).Debug(title + " - succeeded") + } + }() + + err = destroyLayer(&stdDriverInfo, path) + if err != nil { + return hcserror.New(err, title+" - failed", "") + } + return nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/expandscratchsize.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/expandscratchsize.go new file mode 100644 index 000000000000..651676fb25eb --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/expandscratchsize.go @@ -0,0 +1,30 @@ +package wclayer + +import ( + "github.com/Microsoft/hcsshim/internal/hcserror" + "github.com/sirupsen/logrus" +) + +// ExpandScratchSize expands the size of a layer to at least size bytes. +func ExpandScratchSize(path string, size uint64) (err error) { + title := "hcsshim::ExpandScratchSize" + fields := logrus.Fields{ + "path": path, + "size": size, + } + logrus.WithFields(fields).Debug(title) + defer func() { + if err != nil { + fields[logrus.ErrorKey] = err + logrus.WithFields(fields).Error(err) + } else { + logrus.WithFields(fields).Debug(title + " - succeeded") + } + }() + + err = expandSandboxSize(&stdDriverInfo, path, size) + if err != nil { + return hcserror.New(err, title+" - failed", "") + } + return nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/exportlayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/exportlayer.go new file mode 100644 index 000000000000..0425b3395549 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/exportlayer.go @@ -0,0 +1,76 @@ +package wclayer + +import ( + "io/ioutil" + "os" + + "github.com/Microsoft/go-winio" + "github.com/Microsoft/hcsshim/internal/hcserror" + "github.com/sirupsen/logrus" +) + +// ExportLayer will create a folder at exportFolderPath and fill that folder with +// the transport format version of the layer identified by layerId. This transport +// format includes any metadata required for later importing the layer (using +// ImportLayer), and requires the full list of parent layer paths in order to +// perform the export. +func ExportLayer(path string, exportFolderPath string, parentLayerPaths []string) (err error) { + title := "hcsshim::ExportLayer" + fields := logrus.Fields{ + "path": path, + "exportFolderPath": exportFolderPath, + } + logrus.WithFields(fields).Debug(title) + defer func() { + if err != nil { + fields[logrus.ErrorKey] = err + logrus.WithFields(fields).Error(err) + } else { + logrus.WithFields(fields).Debug(title + " - succeeded") + } + }() + + // Generate layer descriptors + layers, err := layerPathsToDescriptors(parentLayerPaths) + if err != nil { + return err + } + + err = exportLayer(&stdDriverInfo, path, exportFolderPath, layers) + if err != nil { + return hcserror.New(err, title+" - failed", "") + } + return nil +} + +type LayerReader interface { + Next() (string, int64, *winio.FileBasicInfo, error) + Read(b []byte) (int, error) + Close() error +} + +// NewLayerReader returns a new layer reader for reading the contents of an on-disk layer. +// The caller must have taken the SeBackupPrivilege privilege +// to call this and any methods on the resulting LayerReader. +func NewLayerReader(path string, parentLayerPaths []string) (LayerReader, error) { + exportPath, err := ioutil.TempDir("", "hcs") + if err != nil { + return nil, err + } + err = ExportLayer(path, exportPath, parentLayerPaths) + if err != nil { + os.RemoveAll(exportPath) + return nil, err + } + return &legacyLayerReaderWrapper{newLegacyLayerReader(exportPath)}, nil +} + +type legacyLayerReaderWrapper struct { + *legacyLayerReader +} + +func (r *legacyLayerReaderWrapper) Close() error { + err := r.legacyLayerReader.Close() + os.RemoveAll(r.root) + return err +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/getlayermountpath.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/getlayermountpath.go new file mode 100644 index 000000000000..d60b6ed53154 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/getlayermountpath.go @@ -0,0 +1,56 @@ +package wclayer + +import ( + "syscall" + + "github.com/Microsoft/hcsshim/internal/hcserror" + "github.com/sirupsen/logrus" +) + +// GetLayerMountPath will look for a mounted layer with the given path and return +// the path at which that layer can be accessed. This path may be a volume path +// if the layer is a mounted read-write layer, otherwise it is expected to be the +// folder path at which the layer is stored. +func GetLayerMountPath(path string) (_ string, err error) { + title := "hcsshim::GetLayerMountPath" + fields := logrus.Fields{ + "path": path, + } + logrus.WithFields(fields).Debug(title) + defer func() { + if err != nil { + fields[logrus.ErrorKey] = err + logrus.WithFields(fields).Error(err) + } else { + logrus.WithFields(fields).Debug(title + " - succeeded") + } + }() + + var mountPathLength uintptr + mountPathLength = 0 + + // Call the procedure itself. + logrus.WithFields(fields).Debug("Calling proc (1)") + err = getLayerMountPath(&stdDriverInfo, path, &mountPathLength, nil) + if err != nil { + return "", hcserror.New(err, title+" - failed", "(first call)") + } + + // Allocate a mount path of the returned length. + if mountPathLength == 0 { + return "", nil + } + mountPathp := make([]uint16, mountPathLength) + mountPathp[0] = 0 + + // Call the procedure again + logrus.WithFields(fields).Debug("Calling proc (2)") + err = getLayerMountPath(&stdDriverInfo, path, &mountPathLength, &mountPathp[0]) + if err != nil { + return "", hcserror.New(err, title+" - failed", "(second call)") + } + + mountPath := syscall.UTF16ToString(mountPathp[0:]) + fields["mountPath"] = mountPath + return mountPath, nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/getsharedbaseimages.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/getsharedbaseimages.go new file mode 100644 index 000000000000..dbd83ef2bcc0 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/getsharedbaseimages.go @@ -0,0 +1,29 @@ +package wclayer + +import ( + "github.com/Microsoft/hcsshim/internal/hcserror" + "github.com/Microsoft/hcsshim/internal/interop" + "github.com/sirupsen/logrus" +) + +// GetSharedBaseImages will enumerate the images stored in the common central +// image store and return descriptive info about those images for the purpose +// of registering them with the graphdriver, graph, and tagstore. +func GetSharedBaseImages() (imageData string, err error) { + title := "hcsshim::GetSharedBaseImages" + logrus.Debug(title) + defer func() { + if err != nil { + logrus.WithError(err).Error(err) + } else { + logrus.WithField("imageData", imageData).Debug(title + " - succeeded") + } + }() + + var buffer *uint16 + err = getBaseImages(&buffer) + if err != nil { + return "", hcserror.New(err, title+" - failed", "") + } + return interop.ConvertAndFreeCoTaskMemString(buffer), nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/grantvmaccess.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/grantvmaccess.go new file mode 100644 index 000000000000..05735df6cdca --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/grantvmaccess.go @@ -0,0 +1,30 @@ +package wclayer + +import ( + "github.com/Microsoft/hcsshim/internal/hcserror" + "github.com/sirupsen/logrus" +) + +// GrantVmAccess adds access to a file for a given VM +func GrantVmAccess(vmid string, filepath string) (err error) { + title := "hcsshim::GrantVmAccess" + fields := logrus.Fields{ + "vm-id": vmid, + "path": filepath, + } + logrus.WithFields(fields).Debug(title) + defer func() { + if err != nil { + fields[logrus.ErrorKey] = err + logrus.WithFields(fields).Error(err) + } else { + logrus.WithFields(fields).Debug(title + " - succeeded") + } + }() + + err = grantVmAccess(vmid, filepath) + if err != nil { + return hcserror.New(err, title+" - failed", "") + } + return nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/importlayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/importlayer.go new file mode 100644 index 000000000000..76a804f2af2b --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/importlayer.go @@ -0,0 +1,135 @@ +package wclayer + +import ( + "io/ioutil" + "os" + "path/filepath" + + "github.com/Microsoft/go-winio" + "github.com/Microsoft/hcsshim/internal/hcserror" + "github.com/Microsoft/hcsshim/internal/safefile" + "github.com/sirupsen/logrus" +) + +// ImportLayer will take the contents of the folder at importFolderPath and import +// that into a layer with the id layerId. Note that in order to correctly populate +// the layer and interperet the transport format, all parent layers must already +// be present on the system at the paths provided in parentLayerPaths. +func ImportLayer(path string, importFolderPath string, parentLayerPaths []string) (err error) { + title := "hcsshim::ImportLayer" + fields := logrus.Fields{ + "path": path, + "importFolderPath": importFolderPath, + } + logrus.WithFields(fields).Debug(title) + defer func() { + if err != nil { + fields[logrus.ErrorKey] = err + logrus.WithFields(fields).Error(err) + } else { + logrus.WithFields(fields).Debug(title + " - succeeded") + } + }() + + // Generate layer descriptors + layers, err := layerPathsToDescriptors(parentLayerPaths) + if err != nil { + return err + } + + err = importLayer(&stdDriverInfo, path, importFolderPath, layers) + if err != nil { + return hcserror.New(err, title+" - failed", "") + } + return nil +} + +// LayerWriter is an interface that supports writing a new container image layer. +type LayerWriter interface { + // Add adds a file to the layer with given metadata. + Add(name string, fileInfo *winio.FileBasicInfo) error + // AddLink adds a hard link to the layer. The target must already have been added. + AddLink(name string, target string) error + // Remove removes a file that was present in a parent layer from the layer. + Remove(name string) error + // Write writes data to the current file. The data must be in the format of a Win32 + // backup stream. + Write(b []byte) (int, error) + // Close finishes the layer writing process and releases any resources. + Close() error +} + +type legacyLayerWriterWrapper struct { + *legacyLayerWriter + path string + parentLayerPaths []string +} + +func (r *legacyLayerWriterWrapper) Close() error { + defer os.RemoveAll(r.root.Name()) + defer r.legacyLayerWriter.CloseRoots() + err := r.legacyLayerWriter.Close() + if err != nil { + return err + } + + if err = ImportLayer(r.destRoot.Name(), r.path, r.parentLayerPaths); err != nil { + return err + } + for _, name := range r.Tombstones { + if err = safefile.RemoveRelative(name, r.destRoot); err != nil && !os.IsNotExist(err) { + return err + } + } + // Add any hard links that were collected. + for _, lnk := range r.PendingLinks { + if err = safefile.RemoveRelative(lnk.Path, r.destRoot); err != nil && !os.IsNotExist(err) { + return err + } + if err = safefile.LinkRelative(lnk.Target, lnk.TargetRoot, lnk.Path, r.destRoot); err != nil { + return err + } + } + // Prepare the utility VM for use if one is present in the layer. + if r.HasUtilityVM { + err := safefile.EnsureNotReparsePointRelative("UtilityVM", r.destRoot) + if err != nil { + return err + } + err = ProcessUtilityVMImage(filepath.Join(r.destRoot.Name(), "UtilityVM")) + if err != nil { + return err + } + } + return nil +} + +// NewLayerWriter returns a new layer writer for creating a layer on disk. +// The caller must have taken the SeBackupPrivilege and SeRestorePrivilege privileges +// to call this and any methods on the resulting LayerWriter. +func NewLayerWriter(path string, parentLayerPaths []string) (LayerWriter, error) { + if len(parentLayerPaths) == 0 { + // This is a base layer. It gets imported differently. + f, err := safefile.OpenRoot(path) + if err != nil { + return nil, err + } + return &baseLayerWriter{ + root: f, + }, nil + } + + importPath, err := ioutil.TempDir("", "hcs") + if err != nil { + return nil, err + } + w, err := newLegacyLayerWriter(importPath, parentLayerPaths, path) + if err != nil { + return nil, err + } + return &legacyLayerWriterWrapper{ + legacyLayerWriter: w, + path: importPath, + parentLayerPaths: parentLayerPaths, + }, nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerexists.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerexists.go new file mode 100644 index 000000000000..258167a57933 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerexists.go @@ -0,0 +1,33 @@ +package wclayer + +import ( + "github.com/Microsoft/hcsshim/internal/hcserror" + "github.com/sirupsen/logrus" +) + +// LayerExists will return true if a layer with the given id exists and is known +// to the system. +func LayerExists(path string) (_ bool, err error) { + title := "hcsshim::LayerExists" + fields := logrus.Fields{ + "path": path, + } + logrus.WithFields(fields).Debug(title) + defer func() { + if err != nil { + fields[logrus.ErrorKey] = err + logrus.WithFields(fields).Error(err) + } else { + logrus.WithFields(fields).Debug(title + " - succeeded") + } + }() + + // Call the procedure itself. + var exists uint32 + err = layerExists(&stdDriverInfo, path, &exists) + if err != nil { + return false, hcserror.New(err, title+" - failed", "") + } + fields["layer-exists"] = exists != 0 + return exists != 0, nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerid.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerid.go new file mode 100644 index 000000000000..90df3bedceb6 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerid.go @@ -0,0 +1,13 @@ +package wclayer + +import ( + "path/filepath" + + "github.com/Microsoft/hcsshim/internal/guid" +) + +// LayerID returns the layer ID of a layer on disk. +func LayerID(path string) (guid.GUID, error) { + _, file := filepath.Split(path) + return NameToGuid(file) +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerutils.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerutils.go new file mode 100644 index 000000000000..6d0ae8a074ef --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerutils.go @@ -0,0 +1,96 @@ +package wclayer + +// This file contains utility functions to support storage (graph) related +// functionality. + +import ( + "syscall" + + "github.com/Microsoft/hcsshim/internal/guid" + "github.com/sirupsen/logrus" +) + +/* To pass into syscall, we need a struct matching the following: +enum GraphDriverType +{ + DiffDriver, + FilterDriver +}; + +struct DriverInfo { + GraphDriverType Flavour; + LPCWSTR HomeDir; +}; +*/ + +type driverInfo struct { + Flavour int + HomeDirp *uint16 +} + +var ( + utf16EmptyString uint16 + stdDriverInfo = driverInfo{1, &utf16EmptyString} +) + +/* To pass into syscall, we need a struct matching the following: +typedef struct _WC_LAYER_DESCRIPTOR { + + // + // The ID of the layer + // + + GUID LayerId; + + // + // Additional flags + // + + union { + struct { + ULONG Reserved : 31; + ULONG Dirty : 1; // Created from sandbox as a result of snapshot + }; + ULONG Value; + } Flags; + + // + // Path to the layer root directory, null-terminated + // + + PCWSTR Path; + +} WC_LAYER_DESCRIPTOR, *PWC_LAYER_DESCRIPTOR; +*/ +type WC_LAYER_DESCRIPTOR struct { + LayerId guid.GUID + Flags uint32 + Pathp *uint16 +} + +func layerPathsToDescriptors(parentLayerPaths []string) ([]WC_LAYER_DESCRIPTOR, error) { + // Array of descriptors that gets constructed. + var layers []WC_LAYER_DESCRIPTOR + + for i := 0; i < len(parentLayerPaths); i++ { + g, err := LayerID(parentLayerPaths[i]) + if err != nil { + logrus.WithError(err).Debug("Failed to convert name to guid") + return nil, err + } + + p, err := syscall.UTF16PtrFromString(parentLayerPaths[i]) + if err != nil { + logrus.WithError(err).Debug("Failed conversion of parentLayerPath to pointer") + return nil, err + } + + layers = append(layers, WC_LAYER_DESCRIPTOR{ + LayerId: g, + Flags: 0, + Pathp: p, + }) + } + + return layers, nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/legacy.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/legacy.go new file mode 100644 index 000000000000..b8ea5d2632ea --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/legacy.go @@ -0,0 +1,815 @@ +package wclayer + +import ( + "bufio" + "encoding/binary" + "errors" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + "syscall" + + "github.com/Microsoft/go-winio" + "github.com/Microsoft/hcsshim/internal/longpath" + "github.com/Microsoft/hcsshim/internal/safefile" +) + +var errorIterationCanceled = errors.New("") + +var mutatedUtilityVMFiles = map[string]bool{ + `EFI\Microsoft\Boot\BCD`: true, + `EFI\Microsoft\Boot\BCD.LOG`: true, + `EFI\Microsoft\Boot\BCD.LOG1`: true, + `EFI\Microsoft\Boot\BCD.LOG2`: true, +} + +const ( + filesPath = `Files` + hivesPath = `Hives` + utilityVMPath = `UtilityVM` + utilityVMFilesPath = `UtilityVM\Files` +) + +func openFileOrDir(path string, mode uint32, createDisposition uint32) (file *os.File, err error) { + return winio.OpenForBackup(path, mode, syscall.FILE_SHARE_READ, createDisposition) +} + +func hasPathPrefix(p, prefix string) bool { + return strings.HasPrefix(p, prefix) && len(p) > len(prefix) && p[len(prefix)] == '\\' +} + +type fileEntry struct { + path string + fi os.FileInfo + err error +} + +type legacyLayerReader struct { + root string + result chan *fileEntry + proceed chan bool + currentFile *os.File + backupReader *winio.BackupFileReader +} + +// newLegacyLayerReader returns a new LayerReader that can read the Windows +// container layer transport format from disk. +func newLegacyLayerReader(root string) *legacyLayerReader { + r := &legacyLayerReader{ + root: root, + result: make(chan *fileEntry), + proceed: make(chan bool), + } + go r.walk() + return r +} + +func readTombstones(path string) (map[string]([]string), error) { + tf, err := os.Open(filepath.Join(path, "tombstones.txt")) + if err != nil { + return nil, err + } + defer tf.Close() + s := bufio.NewScanner(tf) + if !s.Scan() || s.Text() != "\xef\xbb\xbfVersion 1.0" { + return nil, errors.New("Invalid tombstones file") + } + + ts := make(map[string]([]string)) + for s.Scan() { + t := filepath.Join(filesPath, s.Text()[1:]) // skip leading `\` + dir := filepath.Dir(t) + ts[dir] = append(ts[dir], t) + } + if err = s.Err(); err != nil { + return nil, err + } + + return ts, nil +} + +func (r *legacyLayerReader) walkUntilCancelled() error { + root, err := longpath.LongAbs(r.root) + if err != nil { + return err + } + + r.root = root + ts, err := readTombstones(r.root) + if err != nil { + return err + } + + err = filepath.Walk(r.root, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + // Indirect fix for https://github.com/moby/moby/issues/32838#issuecomment-343610048. + // Handle failure from what may be a golang bug in the conversion of + // UTF16 to UTF8 in files which are left in the recycle bin. Os.Lstat + // which is called by filepath.Walk will fail when a filename contains + // unicode characters. Skip the recycle bin regardless which is goodness. + if strings.EqualFold(path, filepath.Join(r.root, `Files\$Recycle.Bin`)) && info.IsDir() { + return filepath.SkipDir + } + + if path == r.root || path == filepath.Join(r.root, "tombstones.txt") || strings.HasSuffix(path, ".$wcidirs$") { + return nil + } + + r.result <- &fileEntry{path, info, nil} + if !<-r.proceed { + return errorIterationCanceled + } + + // List all the tombstones. + if info.IsDir() { + relPath, err := filepath.Rel(r.root, path) + if err != nil { + return err + } + if dts, ok := ts[relPath]; ok { + for _, t := range dts { + r.result <- &fileEntry{filepath.Join(r.root, t), nil, nil} + if !<-r.proceed { + return errorIterationCanceled + } + } + } + } + return nil + }) + if err == errorIterationCanceled { + return nil + } + if err == nil { + return io.EOF + } + return err +} + +func (r *legacyLayerReader) walk() { + defer close(r.result) + if !<-r.proceed { + return + } + + err := r.walkUntilCancelled() + if err != nil { + for { + r.result <- &fileEntry{err: err} + if !<-r.proceed { + return + } + } + } +} + +func (r *legacyLayerReader) reset() { + if r.backupReader != nil { + r.backupReader.Close() + r.backupReader = nil + } + if r.currentFile != nil { + r.currentFile.Close() + r.currentFile = nil + } +} + +func findBackupStreamSize(r io.Reader) (int64, error) { + br := winio.NewBackupStreamReader(r) + for { + hdr, err := br.Next() + if err != nil { + if err == io.EOF { + err = nil + } + return 0, err + } + if hdr.Id == winio.BackupData { + return hdr.Size, nil + } + } +} + +func (r *legacyLayerReader) Next() (path string, size int64, fileInfo *winio.FileBasicInfo, err error) { + r.reset() + r.proceed <- true + fe := <-r.result + if fe == nil { + err = errors.New("LegacyLayerReader closed") + return + } + if fe.err != nil { + err = fe.err + return + } + + path, err = filepath.Rel(r.root, fe.path) + if err != nil { + return + } + + if fe.fi == nil { + // This is a tombstone. Return a nil fileInfo. + return + } + + if fe.fi.IsDir() && hasPathPrefix(path, filesPath) { + fe.path += ".$wcidirs$" + } + + f, err := openFileOrDir(fe.path, syscall.GENERIC_READ, syscall.OPEN_EXISTING) + if err != nil { + return + } + defer func() { + if f != nil { + f.Close() + } + }() + + fileInfo, err = winio.GetFileBasicInfo(f) + if err != nil { + return + } + + if !hasPathPrefix(path, filesPath) { + size = fe.fi.Size() + r.backupReader = winio.NewBackupFileReader(f, false) + if path == hivesPath || path == filesPath { + // The Hives directory has a non-deterministic file time because of the + // nature of the import process. Use the times from System_Delta. + var g *os.File + g, err = os.Open(filepath.Join(r.root, hivesPath, `System_Delta`)) + if err != nil { + return + } + attr := fileInfo.FileAttributes + fileInfo, err = winio.GetFileBasicInfo(g) + g.Close() + if err != nil { + return + } + fileInfo.FileAttributes = attr + } + + // The creation time and access time get reset for files outside of the Files path. + fileInfo.CreationTime = fileInfo.LastWriteTime + fileInfo.LastAccessTime = fileInfo.LastWriteTime + + } else { + // The file attributes are written before the backup stream. + var attr uint32 + err = binary.Read(f, binary.LittleEndian, &attr) + if err != nil { + return + } + fileInfo.FileAttributes = attr + beginning := int64(4) + + // Find the accurate file size. + if !fe.fi.IsDir() { + size, err = findBackupStreamSize(f) + if err != nil { + err = &os.PathError{Op: "findBackupStreamSize", Path: fe.path, Err: err} + return + } + } + + // Return back to the beginning of the backup stream. + _, err = f.Seek(beginning, 0) + if err != nil { + return + } + } + + r.currentFile = f + f = nil + return +} + +func (r *legacyLayerReader) Read(b []byte) (int, error) { + if r.backupReader == nil { + if r.currentFile == nil { + return 0, io.EOF + } + return r.currentFile.Read(b) + } + return r.backupReader.Read(b) +} + +func (r *legacyLayerReader) Seek(offset int64, whence int) (int64, error) { + if r.backupReader == nil { + if r.currentFile == nil { + return 0, errors.New("no current file") + } + return r.currentFile.Seek(offset, whence) + } + return 0, errors.New("seek not supported on this stream") +} + +func (r *legacyLayerReader) Close() error { + r.proceed <- false + <-r.result + r.reset() + return nil +} + +type pendingLink struct { + Path, Target string + TargetRoot *os.File +} + +type pendingDir struct { + Path string + Root *os.File +} + +type legacyLayerWriter struct { + root *os.File + destRoot *os.File + parentRoots []*os.File + currentFile *os.File + bufWriter *bufio.Writer + currentFileName string + currentFileRoot *os.File + backupWriter *winio.BackupFileWriter + Tombstones []string + HasUtilityVM bool + uvmDi []dirInfo + addedFiles map[string]bool + PendingLinks []pendingLink + pendingDirs []pendingDir + currentIsDir bool +} + +// newLegacyLayerWriter returns a LayerWriter that can write the contaler layer +// transport format to disk. +func newLegacyLayerWriter(root string, parentRoots []string, destRoot string) (w *legacyLayerWriter, err error) { + w = &legacyLayerWriter{ + addedFiles: make(map[string]bool), + } + defer func() { + if err != nil { + w.CloseRoots() + w = nil + } + }() + w.root, err = safefile.OpenRoot(root) + if err != nil { + return + } + w.destRoot, err = safefile.OpenRoot(destRoot) + if err != nil { + return + } + for _, r := range parentRoots { + f, err := safefile.OpenRoot(r) + if err != nil { + return w, err + } + w.parentRoots = append(w.parentRoots, f) + } + w.bufWriter = bufio.NewWriterSize(ioutil.Discard, 65536) + return +} + +func (w *legacyLayerWriter) CloseRoots() { + if w.root != nil { + w.root.Close() + w.root = nil + } + if w.destRoot != nil { + w.destRoot.Close() + w.destRoot = nil + } + for i := range w.parentRoots { + w.parentRoots[i].Close() + } + w.parentRoots = nil +} + +func (w *legacyLayerWriter) initUtilityVM() error { + if !w.HasUtilityVM { + err := safefile.MkdirRelative(utilityVMPath, w.destRoot) + if err != nil { + return err + } + // Server 2016 does not support multiple layers for the utility VM, so + // clone the utility VM from the parent layer into this layer. Use hard + // links to avoid unnecessary copying, since most of the files are + // immutable. + err = cloneTree(w.parentRoots[0], w.destRoot, utilityVMFilesPath, mutatedUtilityVMFiles) + if err != nil { + return fmt.Errorf("cloning the parent utility VM image failed: %s", err) + } + w.HasUtilityVM = true + } + return nil +} + +func (w *legacyLayerWriter) reset() error { + err := w.bufWriter.Flush() + if err != nil { + return err + } + w.bufWriter.Reset(ioutil.Discard) + if w.currentIsDir { + r := w.currentFile + br := winio.NewBackupStreamReader(r) + // Seek to the beginning of the backup stream, skipping the fileattrs + if _, err := r.Seek(4, io.SeekStart); err != nil { + return err + } + + for { + bhdr, err := br.Next() + if err == io.EOF { + // end of backupstream data + break + } + if err != nil { + return err + } + switch bhdr.Id { + case winio.BackupReparseData: + // The current file is a `.$wcidirs$` metadata file that + // describes a directory reparse point. Delete the placeholder + // directory to prevent future files being added into the + // destination of the reparse point during the ImportLayer call + if err := safefile.RemoveRelative(w.currentFileName, w.currentFileRoot); err != nil { + return err + } + w.pendingDirs = append(w.pendingDirs, pendingDir{Path: w.currentFileName, Root: w.currentFileRoot}) + default: + // ignore all other stream types, as we only care about directory reparse points + } + } + w.currentIsDir = false + } + if w.backupWriter != nil { + w.backupWriter.Close() + w.backupWriter = nil + } + if w.currentFile != nil { + w.currentFile.Close() + w.currentFile = nil + w.currentFileName = "" + w.currentFileRoot = nil + } + return nil +} + +// copyFileWithMetadata copies a file using the backup/restore APIs in order to preserve metadata +func copyFileWithMetadata(srcRoot, destRoot *os.File, subPath string, isDir bool) (fileInfo *winio.FileBasicInfo, err error) { + src, err := safefile.OpenRelative( + subPath, + srcRoot, + syscall.GENERIC_READ|winio.ACCESS_SYSTEM_SECURITY, + syscall.FILE_SHARE_READ, + safefile.FILE_OPEN, + safefile.FILE_OPEN_REPARSE_POINT) + if err != nil { + return nil, err + } + defer src.Close() + srcr := winio.NewBackupFileReader(src, true) + defer srcr.Close() + + fileInfo, err = winio.GetFileBasicInfo(src) + if err != nil { + return nil, err + } + + extraFlags := uint32(0) + if isDir { + extraFlags |= safefile.FILE_DIRECTORY_FILE + } + dest, err := safefile.OpenRelative( + subPath, + destRoot, + syscall.GENERIC_READ|syscall.GENERIC_WRITE|winio.WRITE_DAC|winio.WRITE_OWNER|winio.ACCESS_SYSTEM_SECURITY, + syscall.FILE_SHARE_READ, + safefile.FILE_CREATE, + extraFlags) + if err != nil { + return nil, err + } + defer dest.Close() + + err = winio.SetFileBasicInfo(dest, fileInfo) + if err != nil { + return nil, err + } + + destw := winio.NewBackupFileWriter(dest, true) + defer func() { + cerr := destw.Close() + if err == nil { + err = cerr + } + }() + + _, err = io.Copy(destw, srcr) + if err != nil { + return nil, err + } + + return fileInfo, nil +} + +// cloneTree clones a directory tree using hard links. It skips hard links for +// the file names in the provided map and just copies those files. +func cloneTree(srcRoot *os.File, destRoot *os.File, subPath string, mutatedFiles map[string]bool) error { + var di []dirInfo + err := safefile.EnsureNotReparsePointRelative(subPath, srcRoot) + if err != nil { + return err + } + err = filepath.Walk(filepath.Join(srcRoot.Name(), subPath), func(srcFilePath string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + relPath, err := filepath.Rel(srcRoot.Name(), srcFilePath) + if err != nil { + return err + } + + fileAttributes := info.Sys().(*syscall.Win32FileAttributeData).FileAttributes + // Directories, reparse points, and files that will be mutated during + // utility VM import must be copied. All other files can be hard linked. + isReparsePoint := fileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT != 0 + // In go1.9, FileInfo.IsDir() returns false if the directory is also a symlink. + // See: https://github.com/golang/go/commit/1989921aef60c83e6f9127a8448fb5ede10e9acc + // Fixes the problem by checking syscall.FILE_ATTRIBUTE_DIRECTORY directly + isDir := fileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 + + if isDir || isReparsePoint || mutatedFiles[relPath] { + fi, err := copyFileWithMetadata(srcRoot, destRoot, relPath, isDir) + if err != nil { + return err + } + if isDir && !isReparsePoint { + di = append(di, dirInfo{path: relPath, fileInfo: *fi}) + } + } else { + err = safefile.LinkRelative(relPath, srcRoot, relPath, destRoot) + if err != nil { + return err + } + } + + return nil + }) + if err != nil { + return err + } + + return reapplyDirectoryTimes(destRoot, di) +} + +func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) error { + if err := w.reset(); err != nil { + return err + } + + if name == utilityVMPath { + return w.initUtilityVM() + } + + name = filepath.Clean(name) + if hasPathPrefix(name, utilityVMPath) { + if !w.HasUtilityVM { + return errors.New("missing UtilityVM directory") + } + if !hasPathPrefix(name, utilityVMFilesPath) && name != utilityVMFilesPath { + return errors.New("invalid UtilityVM layer") + } + createDisposition := uint32(safefile.FILE_OPEN) + if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 { + st, err := safefile.LstatRelative(name, w.destRoot) + if err != nil && !os.IsNotExist(err) { + return err + } + if st != nil { + // Delete the existing file/directory if it is not the same type as this directory. + existingAttr := st.Sys().(*syscall.Win32FileAttributeData).FileAttributes + if (uint32(fileInfo.FileAttributes)^existingAttr)&(syscall.FILE_ATTRIBUTE_DIRECTORY|syscall.FILE_ATTRIBUTE_REPARSE_POINT) != 0 { + if err = safefile.RemoveAllRelative(name, w.destRoot); err != nil { + return err + } + st = nil + } + } + if st == nil { + if err = safefile.MkdirRelative(name, w.destRoot); err != nil { + return err + } + } + if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 { + w.uvmDi = append(w.uvmDi, dirInfo{path: name, fileInfo: *fileInfo}) + } + } else { + // Overwrite any existing hard link. + err := safefile.RemoveRelative(name, w.destRoot) + if err != nil && !os.IsNotExist(err) { + return err + } + createDisposition = safefile.FILE_CREATE + } + + f, err := safefile.OpenRelative( + name, + w.destRoot, + syscall.GENERIC_READ|syscall.GENERIC_WRITE|winio.WRITE_DAC|winio.WRITE_OWNER|winio.ACCESS_SYSTEM_SECURITY, + syscall.FILE_SHARE_READ, + createDisposition, + safefile.FILE_OPEN_REPARSE_POINT, + ) + if err != nil { + return err + } + defer func() { + if f != nil { + f.Close() + safefile.RemoveRelative(name, w.destRoot) + } + }() + + err = winio.SetFileBasicInfo(f, fileInfo) + if err != nil { + return err + } + + w.backupWriter = winio.NewBackupFileWriter(f, true) + w.bufWriter.Reset(w.backupWriter) + w.currentFile = f + w.currentFileName = name + w.currentFileRoot = w.destRoot + w.addedFiles[name] = true + f = nil + return nil + } + + fname := name + if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 { + err := safefile.MkdirRelative(name, w.root) + if err != nil { + return err + } + fname += ".$wcidirs$" + w.currentIsDir = true + } + + f, err := safefile.OpenRelative(fname, w.root, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.FILE_SHARE_READ, safefile.FILE_CREATE, 0) + if err != nil { + return err + } + defer func() { + if f != nil { + f.Close() + safefile.RemoveRelative(fname, w.root) + } + }() + + strippedFi := *fileInfo + strippedFi.FileAttributes = 0 + err = winio.SetFileBasicInfo(f, &strippedFi) + if err != nil { + return err + } + + if hasPathPrefix(name, hivesPath) { + w.backupWriter = winio.NewBackupFileWriter(f, false) + w.bufWriter.Reset(w.backupWriter) + } else { + w.bufWriter.Reset(f) + // The file attributes are written before the stream. + err = binary.Write(w.bufWriter, binary.LittleEndian, uint32(fileInfo.FileAttributes)) + if err != nil { + w.bufWriter.Reset(ioutil.Discard) + return err + } + } + + w.currentFile = f + w.currentFileName = name + w.currentFileRoot = w.root + w.addedFiles[name] = true + f = nil + return nil +} + +func (w *legacyLayerWriter) AddLink(name string, target string) error { + if err := w.reset(); err != nil { + return err + } + + target = filepath.Clean(target) + var roots []*os.File + if hasPathPrefix(target, filesPath) { + // Look for cross-layer hard link targets in the parent layers, since + // nothing is in the destination path yet. + roots = w.parentRoots + } else if hasPathPrefix(target, utilityVMFilesPath) { + // Since the utility VM is fully cloned into the destination path + // already, look for cross-layer hard link targets directly in the + // destination path. + roots = []*os.File{w.destRoot} + } + + if roots == nil || (!hasPathPrefix(name, filesPath) && !hasPathPrefix(name, utilityVMFilesPath)) { + return errors.New("invalid hard link in layer") + } + + // Find to try the target of the link in a previously added file. If that + // fails, search in parent layers. + var selectedRoot *os.File + if _, ok := w.addedFiles[target]; ok { + selectedRoot = w.destRoot + } else { + for _, r := range roots { + if _, err := safefile.LstatRelative(target, r); err != nil { + if !os.IsNotExist(err) { + return err + } + } else { + selectedRoot = r + break + } + } + if selectedRoot == nil { + return fmt.Errorf("failed to find link target for '%s' -> '%s'", name, target) + } + } + + // The link can't be written until after the ImportLayer call. + w.PendingLinks = append(w.PendingLinks, pendingLink{ + Path: name, + Target: target, + TargetRoot: selectedRoot, + }) + w.addedFiles[name] = true + return nil +} + +func (w *legacyLayerWriter) Remove(name string) error { + name = filepath.Clean(name) + if hasPathPrefix(name, filesPath) { + w.Tombstones = append(w.Tombstones, name) + } else if hasPathPrefix(name, utilityVMFilesPath) { + err := w.initUtilityVM() + if err != nil { + return err + } + // Make sure the path exists; os.RemoveAll will not fail if the file is + // already gone, and this needs to be a fatal error for diagnostics + // purposes. + if _, err := safefile.LstatRelative(name, w.destRoot); err != nil { + return err + } + err = safefile.RemoveAllRelative(name, w.destRoot) + if err != nil { + return err + } + } else { + return fmt.Errorf("invalid tombstone %s", name) + } + + return nil +} + +func (w *legacyLayerWriter) Write(b []byte) (int, error) { + if w.backupWriter == nil && w.currentFile == nil { + return 0, errors.New("closed") + } + return w.bufWriter.Write(b) +} + +func (w *legacyLayerWriter) Close() error { + if err := w.reset(); err != nil { + return err + } + if err := safefile.RemoveRelative("tombstones.txt", w.root); err != nil && !os.IsNotExist(err) { + return err + } + for _, pd := range w.pendingDirs { + err := safefile.MkdirRelative(pd.Path, pd.Root) + if err != nil { + return err + } + } + if w.HasUtilityVM { + err := reapplyDirectoryTimes(w.destRoot, w.uvmDi) + if err != nil { + return err + } + } + return nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/nametoguid.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/nametoguid.go new file mode 100644 index 000000000000..45a63cf65f2c --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/nametoguid.go @@ -0,0 +1,34 @@ +package wclayer + +import ( + "github.com/Microsoft/hcsshim/internal/guid" + "github.com/Microsoft/hcsshim/internal/hcserror" + "github.com/sirupsen/logrus" +) + +// NameToGuid converts the given string into a GUID using the algorithm in the +// Host Compute Service, ensuring GUIDs generated with the same string are common +// across all clients. +func NameToGuid(name string) (id guid.GUID, err error) { + title := "hcsshim::NameToGuid" + fields := logrus.Fields{ + "name": name, + } + logrus.WithFields(fields).Debug(title) + defer func() { + if err != nil { + fields[logrus.ErrorKey] = err + logrus.WithFields(fields).Error(err) + } else { + logrus.WithFields(fields).Debug(title + " - succeeded") + } + }() + + err = nameToGuid(name, &id) + if err != nil { + err = hcserror.New(err, title+" - failed", "") + return + } + fields["guid"] = id.String() + return +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/preparelayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/preparelayer.go new file mode 100644 index 000000000000..2b65b0186230 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/preparelayer.go @@ -0,0 +1,47 @@ +package wclayer + +import ( + "sync" + + "github.com/Microsoft/hcsshim/internal/hcserror" + "github.com/sirupsen/logrus" +) + +var prepareLayerLock sync.Mutex + +// PrepareLayer finds a mounted read-write layer matching path and enables the +// the filesystem filter for use on that layer. This requires the paths to all +// parent layers, and is necessary in order to view or interact with the layer +// as an actual filesystem (reading and writing files, creating directories, etc). +// Disabling the filter must be done via UnprepareLayer. +func PrepareLayer(path string, parentLayerPaths []string) (err error) { + title := "hcsshim::PrepareLayer" + fields := logrus.Fields{ + "path": path, + } + logrus.WithFields(fields).Debug(title) + defer func() { + if err != nil { + fields[logrus.ErrorKey] = err + logrus.WithFields(fields).Error(err) + } else { + logrus.WithFields(fields).Debug(title + " - succeeded") + } + }() + + // Generate layer descriptors + layers, err := layerPathsToDescriptors(parentLayerPaths) + if err != nil { + return err + } + + // This lock is a temporary workaround for a Windows bug. Only allowing one + // call to prepareLayer at a time vastly reduces the chance of a timeout. + prepareLayerLock.Lock() + defer prepareLayerLock.Unlock() + err = prepareLayer(&stdDriverInfo, path, layers) + if err != nil { + return hcserror.New(err, title+" - failed", "") + } + return nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/processimage.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/processimage.go new file mode 100644 index 000000000000..884207c3edb7 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/processimage.go @@ -0,0 +1,23 @@ +package wclayer + +import "os" + +// ProcessBaseLayer post-processes a base layer that has had its files extracted. +// The files should have been extracted to \Files. +func ProcessBaseLayer(path string) error { + err := processBaseImage(path) + if err != nil { + return &os.PathError{Op: "ProcessBaseLayer", Path: path, Err: err} + } + return nil +} + +// ProcessUtilityVMImage post-processes a utility VM image that has had its files extracted. +// The files should have been extracted to \Files. +func ProcessUtilityVMImage(path string) error { + err := processUtilityImage(path) + if err != nil { + return &os.PathError{Op: "ProcessUtilityVMImage", Path: path, Err: err} + } + return nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/unpreparelayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/unpreparelayer.go new file mode 100644 index 000000000000..bccd45969148 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/unpreparelayer.go @@ -0,0 +1,30 @@ +package wclayer + +import ( + "github.com/Microsoft/hcsshim/internal/hcserror" + "github.com/sirupsen/logrus" +) + +// UnprepareLayer disables the filesystem filter for the read-write layer with +// the given id. +func UnprepareLayer(path string) (err error) { + title := "hcsshim::UnprepareLayer" + fields := logrus.Fields{ + "path": path, + } + logrus.WithFields(fields).Debug(title) + defer func() { + if err != nil { + fields[logrus.ErrorKey] = err + logrus.WithFields(fields).Error(err) + } else { + logrus.WithFields(fields).Debug(title + " - succeeded") + } + }() + + err = unprepareLayer(&stdDriverInfo, path) + if err != nil { + return hcserror.New(err, title+" - failed", "") + } + return nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/wclayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/wclayer.go new file mode 100644 index 000000000000..78f2aacd8c69 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/wclayer.go @@ -0,0 +1,27 @@ +package wclayer + +import "github.com/Microsoft/hcsshim/internal/guid" + +//go:generate go run ../../mksyscall_windows.go -output zsyscall_windows.go wclayer.go + +//sys activateLayer(info *driverInfo, id string) (hr error) = vmcompute.ActivateLayer? +//sys copyLayer(info *driverInfo, srcId string, dstId string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.CopyLayer? +//sys createLayer(info *driverInfo, id string, parent string) (hr error) = vmcompute.CreateLayer? +//sys createSandboxLayer(info *driverInfo, id string, parent uintptr, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.CreateSandboxLayer? +//sys expandSandboxSize(info *driverInfo, id string, size uint64) (hr error) = vmcompute.ExpandSandboxSize? +//sys deactivateLayer(info *driverInfo, id string) (hr error) = vmcompute.DeactivateLayer? +//sys destroyLayer(info *driverInfo, id string) (hr error) = vmcompute.DestroyLayer? +//sys exportLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.ExportLayer? +//sys getLayerMountPath(info *driverInfo, id string, length *uintptr, buffer *uint16) (hr error) = vmcompute.GetLayerMountPath? +//sys getBaseImages(buffer **uint16) (hr error) = vmcompute.GetBaseImages? +//sys importLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.ImportLayer? +//sys layerExists(info *driverInfo, id string, exists *uint32) (hr error) = vmcompute.LayerExists? +//sys nameToGuid(name string, guid *_guid) (hr error) = vmcompute.NameToGuid? +//sys prepareLayer(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.PrepareLayer? +//sys unprepareLayer(info *driverInfo, id string) (hr error) = vmcompute.UnprepareLayer? +//sys processBaseImage(path string) (hr error) = vmcompute.ProcessBaseImage? +//sys processUtilityImage(path string) (hr error) = vmcompute.ProcessUtilityImage? + +//sys grantVmAccess(vmid string, filepath string) (hr error) = vmcompute.GrantVmAccess? + +type _guid = guid.GUID diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/zsyscall_windows.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/zsyscall_windows.go new file mode 100644 index 000000000000..d853ab259514 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/zsyscall_windows.go @@ -0,0 +1,510 @@ +// Code generated mksyscall_windows.exe DO NOT EDIT + +package wclayer + +import ( + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +var _ unsafe.Pointer + +// Do the interface allocations only once for common +// Errno values. +const ( + errnoERROR_IO_PENDING = 997 +) + +var ( + errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) +) + +// errnoErr returns common boxed Errno values, to prevent +// allocations at runtime. +func errnoErr(e syscall.Errno) error { + switch e { + case 0: + return nil + case errnoERROR_IO_PENDING: + return errERROR_IO_PENDING + } + // TODO: add more here, after collecting data on the common + // error values see on Windows. (perhaps when running + // all.bat?) + return e +} + +var ( + modvmcompute = windows.NewLazySystemDLL("vmcompute.dll") + + procActivateLayer = modvmcompute.NewProc("ActivateLayer") + procCopyLayer = modvmcompute.NewProc("CopyLayer") + procCreateLayer = modvmcompute.NewProc("CreateLayer") + procCreateSandboxLayer = modvmcompute.NewProc("CreateSandboxLayer") + procExpandSandboxSize = modvmcompute.NewProc("ExpandSandboxSize") + procDeactivateLayer = modvmcompute.NewProc("DeactivateLayer") + procDestroyLayer = modvmcompute.NewProc("DestroyLayer") + procExportLayer = modvmcompute.NewProc("ExportLayer") + procGetLayerMountPath = modvmcompute.NewProc("GetLayerMountPath") + procGetBaseImages = modvmcompute.NewProc("GetBaseImages") + procImportLayer = modvmcompute.NewProc("ImportLayer") + procLayerExists = modvmcompute.NewProc("LayerExists") + procNameToGuid = modvmcompute.NewProc("NameToGuid") + procPrepareLayer = modvmcompute.NewProc("PrepareLayer") + procUnprepareLayer = modvmcompute.NewProc("UnprepareLayer") + procProcessBaseImage = modvmcompute.NewProc("ProcessBaseImage") + procProcessUtilityImage = modvmcompute.NewProc("ProcessUtilityImage") + procGrantVmAccess = modvmcompute.NewProc("GrantVmAccess") +) + +func activateLayer(info *driverInfo, id string) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + return _activateLayer(info, _p0) +} + +func _activateLayer(info *driverInfo, id *uint16) (hr error) { + if hr = procActivateLayer.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procActivateLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func copyLayer(info *driverInfo, srcId string, dstId string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(srcId) + if hr != nil { + return + } + var _p1 *uint16 + _p1, hr = syscall.UTF16PtrFromString(dstId) + if hr != nil { + return + } + return _copyLayer(info, _p0, _p1, descriptors) +} + +func _copyLayer(info *driverInfo, srcId *uint16, dstId *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { + var _p2 *WC_LAYER_DESCRIPTOR + if len(descriptors) > 0 { + _p2 = &descriptors[0] + } + if hr = procCopyLayer.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall6(procCopyLayer.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(srcId)), uintptr(unsafe.Pointer(dstId)), uintptr(unsafe.Pointer(_p2)), uintptr(len(descriptors)), 0) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func createLayer(info *driverInfo, id string, parent string) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + var _p1 *uint16 + _p1, hr = syscall.UTF16PtrFromString(parent) + if hr != nil { + return + } + return _createLayer(info, _p0, _p1) +} + +func _createLayer(info *driverInfo, id *uint16, parent *uint16) (hr error) { + if hr = procCreateLayer.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procCreateLayer.Addr(), 3, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(parent))) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func createSandboxLayer(info *driverInfo, id string, parent uintptr, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + return _createSandboxLayer(info, _p0, parent, descriptors) +} + +func _createSandboxLayer(info *driverInfo, id *uint16, parent uintptr, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { + var _p1 *WC_LAYER_DESCRIPTOR + if len(descriptors) > 0 { + _p1 = &descriptors[0] + } + if hr = procCreateSandboxLayer.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall6(procCreateSandboxLayer.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(parent), uintptr(unsafe.Pointer(_p1)), uintptr(len(descriptors)), 0) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func expandSandboxSize(info *driverInfo, id string, size uint64) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + return _expandSandboxSize(info, _p0, size) +} + +func _expandSandboxSize(info *driverInfo, id *uint16, size uint64) (hr error) { + if hr = procExpandSandboxSize.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procExpandSandboxSize.Addr(), 3, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(size)) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func deactivateLayer(info *driverInfo, id string) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + return _deactivateLayer(info, _p0) +} + +func _deactivateLayer(info *driverInfo, id *uint16) (hr error) { + if hr = procDeactivateLayer.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procDeactivateLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func destroyLayer(info *driverInfo, id string) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + return _destroyLayer(info, _p0) +} + +func _destroyLayer(info *driverInfo, id *uint16) (hr error) { + if hr = procDestroyLayer.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procDestroyLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func exportLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + var _p1 *uint16 + _p1, hr = syscall.UTF16PtrFromString(path) + if hr != nil { + return + } + return _exportLayer(info, _p0, _p1, descriptors) +} + +func _exportLayer(info *driverInfo, id *uint16, path *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { + var _p2 *WC_LAYER_DESCRIPTOR + if len(descriptors) > 0 { + _p2 = &descriptors[0] + } + if hr = procExportLayer.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall6(procExportLayer.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(_p2)), uintptr(len(descriptors)), 0) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func getLayerMountPath(info *driverInfo, id string, length *uintptr, buffer *uint16) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + return _getLayerMountPath(info, _p0, length, buffer) +} + +func _getLayerMountPath(info *driverInfo, id *uint16, length *uintptr, buffer *uint16) (hr error) { + if hr = procGetLayerMountPath.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall6(procGetLayerMountPath.Addr(), 4, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(length)), uintptr(unsafe.Pointer(buffer)), 0, 0) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func getBaseImages(buffer **uint16) (hr error) { + if hr = procGetBaseImages.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procGetBaseImages.Addr(), 1, uintptr(unsafe.Pointer(buffer)), 0, 0) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func importLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + var _p1 *uint16 + _p1, hr = syscall.UTF16PtrFromString(path) + if hr != nil { + return + } + return _importLayer(info, _p0, _p1, descriptors) +} + +func _importLayer(info *driverInfo, id *uint16, path *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { + var _p2 *WC_LAYER_DESCRIPTOR + if len(descriptors) > 0 { + _p2 = &descriptors[0] + } + if hr = procImportLayer.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall6(procImportLayer.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(_p2)), uintptr(len(descriptors)), 0) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func layerExists(info *driverInfo, id string, exists *uint32) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + return _layerExists(info, _p0, exists) +} + +func _layerExists(info *driverInfo, id *uint16, exists *uint32) (hr error) { + if hr = procLayerExists.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procLayerExists.Addr(), 3, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(exists))) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func nameToGuid(name string, guid *_guid) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(name) + if hr != nil { + return + } + return _nameToGuid(_p0, guid) +} + +func _nameToGuid(name *uint16, guid *_guid) (hr error) { + if hr = procNameToGuid.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procNameToGuid.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(guid)), 0) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func prepareLayer(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + return _prepareLayer(info, _p0, descriptors) +} + +func _prepareLayer(info *driverInfo, id *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) { + var _p1 *WC_LAYER_DESCRIPTOR + if len(descriptors) > 0 { + _p1 = &descriptors[0] + } + if hr = procPrepareLayer.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall6(procPrepareLayer.Addr(), 4, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(_p1)), uintptr(len(descriptors)), 0, 0) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func unprepareLayer(info *driverInfo, id string) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(id) + if hr != nil { + return + } + return _unprepareLayer(info, _p0) +} + +func _unprepareLayer(info *driverInfo, id *uint16) (hr error) { + if hr = procUnprepareLayer.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procUnprepareLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func processBaseImage(path string) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(path) + if hr != nil { + return + } + return _processBaseImage(_p0) +} + +func _processBaseImage(path *uint16) (hr error) { + if hr = procProcessBaseImage.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procProcessBaseImage.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func processUtilityImage(path string) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(path) + if hr != nil { + return + } + return _processUtilityImage(_p0) +} + +func _processUtilityImage(path *uint16) (hr error) { + if hr = procProcessUtilityImage.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procProcessUtilityImage.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} + +func grantVmAccess(vmid string, filepath string) (hr error) { + var _p0 *uint16 + _p0, hr = syscall.UTF16PtrFromString(vmid) + if hr != nil { + return + } + var _p1 *uint16 + _p1, hr = syscall.UTF16PtrFromString(filepath) + if hr != nil { + return + } + return _grantVmAccess(_p0, _p1) +} + +func _grantVmAccess(vmid *uint16, filepath *uint16) (hr error) { + if hr = procGrantVmAccess.Find(); hr != nil { + return + } + r0, _, _ := syscall.Syscall(procGrantVmAccess.Addr(), 2, uintptr(unsafe.Pointer(vmid)), uintptr(unsafe.Pointer(filepath)), 0) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} diff --git a/vendor/github.com/Microsoft/hcsshim/layer.go b/vendor/github.com/Microsoft/hcsshim/layer.go new file mode 100644 index 000000000000..df0e63bbde5b --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/layer.go @@ -0,0 +1,106 @@ +package hcsshim + +import ( + "crypto/sha1" + "path/filepath" + + "github.com/Microsoft/hcsshim/internal/guid" + "github.com/Microsoft/hcsshim/internal/wclayer" +) + +func layerPath(info *DriverInfo, id string) string { + return filepath.Join(info.HomeDir, id) +} + +func ActivateLayer(info DriverInfo, id string) error { + return wclayer.ActivateLayer(layerPath(&info, id)) +} +func CreateLayer(info DriverInfo, id, parent string) error { + return wclayer.CreateLayer(layerPath(&info, id), parent) +} + +// New clients should use CreateScratchLayer instead. Kept in to preserve API compatibility. +func CreateSandboxLayer(info DriverInfo, layerId, parentId string, parentLayerPaths []string) error { + return wclayer.CreateScratchLayer(layerPath(&info, layerId), parentLayerPaths) +} +func CreateScratchLayer(info DriverInfo, layerId, parentId string, parentLayerPaths []string) error { + return wclayer.CreateScratchLayer(layerPath(&info, layerId), parentLayerPaths) +} +func DeactivateLayer(info DriverInfo, id string) error { + return wclayer.DeactivateLayer(layerPath(&info, id)) +} +func DestroyLayer(info DriverInfo, id string) error { + return wclayer.DestroyLayer(layerPath(&info, id)) +} + +// New clients should use ExpandScratchSize instead. Kept in to preserve API compatibility. +func ExpandSandboxSize(info DriverInfo, layerId string, size uint64) error { + return wclayer.ExpandScratchSize(layerPath(&info, layerId), size) +} +func ExpandScratchSize(info DriverInfo, layerId string, size uint64) error { + return wclayer.ExpandScratchSize(layerPath(&info, layerId), size) +} +func ExportLayer(info DriverInfo, layerId string, exportFolderPath string, parentLayerPaths []string) error { + return wclayer.ExportLayer(layerPath(&info, layerId), exportFolderPath, parentLayerPaths) +} +func GetLayerMountPath(info DriverInfo, id string) (string, error) { + return wclayer.GetLayerMountPath(layerPath(&info, id)) +} +func GetSharedBaseImages() (imageData string, err error) { + return wclayer.GetSharedBaseImages() +} +func ImportLayer(info DriverInfo, layerID string, importFolderPath string, parentLayerPaths []string) error { + return wclayer.ImportLayer(layerPath(&info, layerID), importFolderPath, parentLayerPaths) +} +func LayerExists(info DriverInfo, id string) (bool, error) { + return wclayer.LayerExists(layerPath(&info, id)) +} +func PrepareLayer(info DriverInfo, layerId string, parentLayerPaths []string) error { + return wclayer.PrepareLayer(layerPath(&info, layerId), parentLayerPaths) +} +func ProcessBaseLayer(path string) error { + return wclayer.ProcessBaseLayer(path) +} +func ProcessUtilityVMImage(path string) error { + return wclayer.ProcessUtilityVMImage(path) +} +func UnprepareLayer(info DriverInfo, layerId string) error { + return wclayer.UnprepareLayer(layerPath(&info, layerId)) +} + +type DriverInfo struct { + Flavour int + HomeDir string +} + +type GUID [16]byte + +func NameToGuid(name string) (id GUID, err error) { + g, err := wclayer.NameToGuid(name) + return GUID(g), err +} + +func NewGUID(source string) *GUID { + h := sha1.Sum([]byte(source)) + var g GUID + copy(g[0:], h[0:16]) + return &g +} + +func (g *GUID) ToString() string { + return (guid.GUID)(*g).String() +} + +type LayerReader = wclayer.LayerReader + +func NewLayerReader(info DriverInfo, layerID string, parentLayerPaths []string) (LayerReader, error) { + return wclayer.NewLayerReader(layerPath(&info, layerID), parentLayerPaths) +} + +type LayerWriter = wclayer.LayerWriter + +func NewLayerWriter(info DriverInfo, layerID string, parentLayerPaths []string) (LayerWriter, error) { + return wclayer.NewLayerWriter(layerPath(&info, layerID), parentLayerPaths) +} + +type WC_LAYER_DESCRIPTOR = wclayer.WC_LAYER_DESCRIPTOR diff --git a/vendor/github.com/Microsoft/hcsshim/process.go b/vendor/github.com/Microsoft/hcsshim/process.go new file mode 100644 index 000000000000..ca8acbb7c256 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/process.go @@ -0,0 +1,72 @@ +package hcsshim + +import ( + "io" + "time" + + "github.com/Microsoft/hcsshim/internal/hcs" +) + +// ContainerError is an error encountered in HCS +type process struct { + p *hcs.Process +} + +// Pid returns the process ID of the process within the container. +func (process *process) Pid() int { + return process.p.Pid() +} + +// Kill signals the process to terminate but does not wait for it to finish terminating. +func (process *process) Kill() error { + return convertProcessError(process.p.Kill(), process) +} + +// Wait waits for the process to exit. +func (process *process) Wait() error { + return convertProcessError(process.p.Wait(), process) +} + +// WaitTimeout waits for the process to exit or the duration to elapse. It returns +// false if timeout occurs. +func (process *process) WaitTimeout(timeout time.Duration) error { + return convertProcessError(process.p.WaitTimeout(timeout), process) +} + +// ExitCode returns the exit code of the process. The process must have +// already terminated. +func (process *process) ExitCode() (int, error) { + code, err := process.p.ExitCode() + if err != nil { + err = convertProcessError(err, process) + } + return code, err +} + +// ResizeConsole resizes the console of the process. +func (process *process) ResizeConsole(width, height uint16) error { + return convertProcessError(process.p.ResizeConsole(width, height), process) +} + +// Stdio returns the stdin, stdout, and stderr pipes, respectively. Closing +// these pipes does not close the underlying pipes; it should be possible to +// call this multiple times to get multiple interfaces. +func (process *process) Stdio() (io.WriteCloser, io.ReadCloser, io.ReadCloser, error) { + stdin, stdout, stderr, err := process.p.Stdio() + if err != nil { + err = convertProcessError(err, process) + } + return stdin, stdout, stderr, err +} + +// CloseStdin closes the write side of the stdin pipe so that the process is +// notified on the read side that there is no more data in stdin. +func (process *process) CloseStdin() error { + return convertProcessError(process.p.CloseStdin(), process) +} + +// Close cleans up any state associated with the process but does not kill +// or wait on it. +func (process *process) Close() error { + return convertProcessError(process.p.Close(), process) +} diff --git a/vendor/github.com/Microsoft/hcsshim/vendor.conf b/vendor/github.com/Microsoft/hcsshim/vendor.conf new file mode 100644 index 000000000000..6e0ed156621d --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/vendor.conf @@ -0,0 +1,21 @@ +github.com/blang/semver v3.1.0 +github.com/containerd/console c12b1e7919c14469339a5d38f2f8ed9b64a9de23 +github.com/containerd/go-runc 5a6d9f37cfa36b15efba46dc7ea349fa9b7143c3 +github.com/hashicorp/errwrap 7554cd9344cec97297fa6649b055a8c98c2a1e55 +github.com/hashicorp/go-multierror ed905158d87462226a13fe39ddf685ea65f1c11f +github.com/konsorten/go-windows-terminal-sequences v1.0.1 +github.com/linuxkit/virtsock 8e79449dea0735c1c056d814934dd035734cc97c +github.com/Microsoft/go-winio 16cfc975803886a5e47c4257a24c8d8c52e178b2 +github.com/Microsoft/opengcs v0.3.9 +github.com/opencontainers/runtime-spec eba862dc2470385a233c7507392675cbeadf7353 +github.com/opencontainers/runtime-tools 1d69bd0f9c39677d0630e50664fbc3154ae61b88 +github.com/pkg/errors v0.8.1 +github.com/sirupsen/logrus v1.3.0 +github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16 +github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c +github.com/xeipuuv/gojsonpointer 4e3ac2762d5f479393488629ee9370b50873b3a6 +github.com/xeipuuv/gojsonreference bd5ef7bd5415a7ac448318e64f11a24cd21e594b +github.com/xeipuuv/gojsonschema 1d523034197ff1f222f6429836dd36a2457a1874 +golang.org/x/crypto ff983b9c42bc9fbf91556e191cc8efb585c16908 +golang.org/x/sync 37e7f081c4d4c64e13b10787722085407fe5d15f +golang.org/x/sys e5ecc2a6747ce8d4af18ed98b3de5ae30eb3a5bb \ No newline at end of file diff --git a/vendor/github.com/Microsoft/hcsshim/zsyscall_windows.go b/vendor/github.com/Microsoft/hcsshim/zsyscall_windows.go new file mode 100644 index 000000000000..8bed84857383 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/zsyscall_windows.go @@ -0,0 +1,54 @@ +// Code generated mksyscall_windows.exe DO NOT EDIT + +package hcsshim + +import ( + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +var _ unsafe.Pointer + +// Do the interface allocations only once for common +// Errno values. +const ( + errnoERROR_IO_PENDING = 997 +) + +var ( + errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) +) + +// errnoErr returns common boxed Errno values, to prevent +// allocations at runtime. +func errnoErr(e syscall.Errno) error { + switch e { + case 0: + return nil + case errnoERROR_IO_PENDING: + return errERROR_IO_PENDING + } + // TODO: add more here, after collecting data on the common + // error values see on Windows. (perhaps when running + // all.bat?) + return e +} + +var ( + modiphlpapi = windows.NewLazySystemDLL("iphlpapi.dll") + + procSetCurrentThreadCompartmentId = modiphlpapi.NewProc("SetCurrentThreadCompartmentId") +) + +func SetCurrentThreadCompartmentId(compartmentId uint32) (hr error) { + r0, _, _ := syscall.Syscall(procSetCurrentThreadCompartmentId.Addr(), 1, uintptr(compartmentId), 0, 0) + if int32(r0) < 0 { + if r0&0x1fff0000 == 0x00070000 { + r0 &= 0xffff + } + hr = syscall.Errno(r0) + } + return +} diff --git a/vendor/github.com/StackExchange/wmi/LICENSE b/vendor/github.com/StackExchange/wmi/LICENSE new file mode 100644 index 000000000000..ae80b67209e2 --- /dev/null +++ b/vendor/github.com/StackExchange/wmi/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 Stack Exchange + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/StackExchange/wmi/README.md b/vendor/github.com/StackExchange/wmi/README.md new file mode 100644 index 000000000000..426d1a46b4aa --- /dev/null +++ b/vendor/github.com/StackExchange/wmi/README.md @@ -0,0 +1,6 @@ +wmi +=== + +Package wmi provides a WQL interface to Windows WMI. + +Note: It interfaces with WMI on the local machine, therefore it only runs on Windows. diff --git a/vendor/github.com/StackExchange/wmi/swbemservices.go b/vendor/github.com/StackExchange/wmi/swbemservices.go new file mode 100644 index 000000000000..3ff875630378 --- /dev/null +++ b/vendor/github.com/StackExchange/wmi/swbemservices.go @@ -0,0 +1,260 @@ +// +build windows + +package wmi + +import ( + "fmt" + "reflect" + "runtime" + "sync" + + "github.com/go-ole/go-ole" + "github.com/go-ole/go-ole/oleutil" +) + +// SWbemServices is used to access wmi. See https://msdn.microsoft.com/en-us/library/aa393719(v=vs.85).aspx +type SWbemServices struct { + //TODO: track namespace. Not sure if we can re connect to a different namespace using the same instance + cWMIClient *Client //This could also be an embedded struct, but then we would need to branch on Client vs SWbemServices in the Query method + sWbemLocatorIUnknown *ole.IUnknown + sWbemLocatorIDispatch *ole.IDispatch + queries chan *queryRequest + closeError chan error + lQueryorClose sync.Mutex +} + +type queryRequest struct { + query string + dst interface{} + args []interface{} + finished chan error +} + +// InitializeSWbemServices will return a new SWbemServices object that can be used to query WMI +func InitializeSWbemServices(c *Client, connectServerArgs ...interface{}) (*SWbemServices, error) { + //fmt.Println("InitializeSWbemServices: Starting") + //TODO: implement connectServerArgs as optional argument for init with connectServer call + s := new(SWbemServices) + s.cWMIClient = c + s.queries = make(chan *queryRequest) + initError := make(chan error) + go s.process(initError) + + err, ok := <-initError + if ok { + return nil, err //Send error to caller + } + //fmt.Println("InitializeSWbemServices: Finished") + return s, nil +} + +// Close will clear and release all of the SWbemServices resources +func (s *SWbemServices) Close() error { + s.lQueryorClose.Lock() + if s == nil || s.sWbemLocatorIDispatch == nil { + s.lQueryorClose.Unlock() + return fmt.Errorf("SWbemServices is not Initialized") + } + if s.queries == nil { + s.lQueryorClose.Unlock() + return fmt.Errorf("SWbemServices has been closed") + } + //fmt.Println("Close: sending close request") + var result error + ce := make(chan error) + s.closeError = ce //Race condition if multiple callers to close. May need to lock here + close(s.queries) //Tell background to shut things down + s.lQueryorClose.Unlock() + err, ok := <-ce + if ok { + result = err + } + //fmt.Println("Close: finished") + return result +} + +func (s *SWbemServices) process(initError chan error) { + //fmt.Println("process: starting background thread initialization") + //All OLE/WMI calls must happen on the same initialized thead, so lock this goroutine + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED) + if err != nil { + oleCode := err.(*ole.OleError).Code() + if oleCode != ole.S_OK && oleCode != S_FALSE { + initError <- fmt.Errorf("ole.CoInitializeEx error: %v", err) + return + } + } + defer ole.CoUninitialize() + + unknown, err := oleutil.CreateObject("WbemScripting.SWbemLocator") + if err != nil { + initError <- fmt.Errorf("CreateObject SWbemLocator error: %v", err) + return + } else if unknown == nil { + initError <- ErrNilCreateObject + return + } + defer unknown.Release() + s.sWbemLocatorIUnknown = unknown + + dispatch, err := s.sWbemLocatorIUnknown.QueryInterface(ole.IID_IDispatch) + if err != nil { + initError <- fmt.Errorf("SWbemLocator QueryInterface error: %v", err) + return + } + defer dispatch.Release() + s.sWbemLocatorIDispatch = dispatch + + // we can't do the ConnectServer call outside the loop unless we find a way to track and re-init the connectServerArgs + //fmt.Println("process: initialized. closing initError") + close(initError) + //fmt.Println("process: waiting for queries") + for q := range s.queries { + //fmt.Printf("process: new query: len(query)=%d\n", len(q.query)) + errQuery := s.queryBackground(q) + //fmt.Println("process: s.queryBackground finished") + if errQuery != nil { + q.finished <- errQuery + } + close(q.finished) + } + //fmt.Println("process: queries channel closed") + s.queries = nil //set channel to nil so we know it is closed + //TODO: I think the Release/Clear calls can panic if things are in a bad state. + //TODO: May need to recover from panics and send error to method caller instead. + close(s.closeError) +} + +// Query runs the WQL query using a SWbemServices instance and appends the values to dst. +// +// dst must have type *[]S or *[]*S, for some struct type S. Fields selected in +// the query must have the same name in dst. Supported types are all signed and +// unsigned integers, time.Time, string, bool, or a pointer to one of those. +// Array types are not supported. +// +// By default, the local machine and default namespace are used. These can be +// changed using connectServerArgs. See +// http://msdn.microsoft.com/en-us/library/aa393720.aspx for details. +func (s *SWbemServices) Query(query string, dst interface{}, connectServerArgs ...interface{}) error { + s.lQueryorClose.Lock() + if s == nil || s.sWbemLocatorIDispatch == nil { + s.lQueryorClose.Unlock() + return fmt.Errorf("SWbemServices is not Initialized") + } + if s.queries == nil { + s.lQueryorClose.Unlock() + return fmt.Errorf("SWbemServices has been closed") + } + + //fmt.Println("Query: Sending query request") + qr := queryRequest{ + query: query, + dst: dst, + args: connectServerArgs, + finished: make(chan error), + } + s.queries <- &qr + s.lQueryorClose.Unlock() + err, ok := <-qr.finished + if ok { + //fmt.Println("Query: Finished with error") + return err //Send error to caller + } + //fmt.Println("Query: Finished") + return nil +} + +func (s *SWbemServices) queryBackground(q *queryRequest) error { + if s == nil || s.sWbemLocatorIDispatch == nil { + return fmt.Errorf("SWbemServices is not Initialized") + } + wmi := s.sWbemLocatorIDispatch //Should just rename in the code, but this will help as we break things apart + //fmt.Println("queryBackground: Starting") + + dv := reflect.ValueOf(q.dst) + if dv.Kind() != reflect.Ptr || dv.IsNil() { + return ErrInvalidEntityType + } + dv = dv.Elem() + mat, elemType := checkMultiArg(dv) + if mat == multiArgTypeInvalid { + return ErrInvalidEntityType + } + + // service is a SWbemServices + serviceRaw, err := oleutil.CallMethod(wmi, "ConnectServer", q.args...) + if err != nil { + return err + } + service := serviceRaw.ToIDispatch() + defer serviceRaw.Clear() + + // result is a SWBemObjectSet + resultRaw, err := oleutil.CallMethod(service, "ExecQuery", q.query) + if err != nil { + return err + } + result := resultRaw.ToIDispatch() + defer resultRaw.Clear() + + count, err := oleInt64(result, "Count") + if err != nil { + return err + } + + enumProperty, err := result.GetProperty("_NewEnum") + if err != nil { + return err + } + defer enumProperty.Clear() + + enum, err := enumProperty.ToIUnknown().IEnumVARIANT(ole.IID_IEnumVariant) + if err != nil { + return err + } + if enum == nil { + return fmt.Errorf("can't get IEnumVARIANT, enum is nil") + } + defer enum.Release() + + // Initialize a slice with Count capacity + dv.Set(reflect.MakeSlice(dv.Type(), 0, int(count))) + + var errFieldMismatch error + for itemRaw, length, err := enum.Next(1); length > 0; itemRaw, length, err = enum.Next(1) { + if err != nil { + return err + } + + err := func() error { + // item is a SWbemObject, but really a Win32_Process + item := itemRaw.ToIDispatch() + defer item.Release() + + ev := reflect.New(elemType) + if err = s.cWMIClient.loadEntity(ev.Interface(), item); err != nil { + if _, ok := err.(*ErrFieldMismatch); ok { + // We continue loading entities even in the face of field mismatch errors. + // If we encounter any other error, that other error is returned. Otherwise, + // an ErrFieldMismatch is returned. + errFieldMismatch = err + } else { + return err + } + } + if mat != multiArgTypeStructPtr { + ev = ev.Elem() + } + dv.Set(reflect.Append(dv, ev)) + return nil + }() + if err != nil { + return err + } + } + //fmt.Println("queryBackground: Finished") + return errFieldMismatch +} diff --git a/vendor/github.com/StackExchange/wmi/wmi.go b/vendor/github.com/StackExchange/wmi/wmi.go new file mode 100644 index 000000000000..f32fb200b133 --- /dev/null +++ b/vendor/github.com/StackExchange/wmi/wmi.go @@ -0,0 +1,490 @@ +// +build windows + +/* +Package wmi provides a WQL interface for WMI on Windows. + +Example code to print names of running processes: + + type Win32_Process struct { + Name string + } + + func main() { + var dst []Win32_Process + q := wmi.CreateQuery(&dst, "") + err := wmi.Query(q, &dst) + if err != nil { + log.Fatal(err) + } + for i, v := range dst { + println(i, v.Name) + } + } + +*/ +package wmi + +import ( + "bytes" + "errors" + "fmt" + "log" + "os" + "reflect" + "runtime" + "strconv" + "strings" + "sync" + "time" + + "github.com/go-ole/go-ole" + "github.com/go-ole/go-ole/oleutil" +) + +var l = log.New(os.Stdout, "", log.LstdFlags) + +var ( + ErrInvalidEntityType = errors.New("wmi: invalid entity type") + // ErrNilCreateObject is the error returned if CreateObject returns nil even + // if the error was nil. + ErrNilCreateObject = errors.New("wmi: create object returned nil") + lock sync.Mutex +) + +// S_FALSE is returned by CoInitializeEx if it was already called on this thread. +const S_FALSE = 0x00000001 + +// QueryNamespace invokes Query with the given namespace on the local machine. +func QueryNamespace(query string, dst interface{}, namespace string) error { + return Query(query, dst, nil, namespace) +} + +// Query runs the WQL query and appends the values to dst. +// +// dst must have type *[]S or *[]*S, for some struct type S. Fields selected in +// the query must have the same name in dst. Supported types are all signed and +// unsigned integers, time.Time, string, bool, or a pointer to one of those. +// Array types are not supported. +// +// By default, the local machine and default namespace are used. These can be +// changed using connectServerArgs. See +// http://msdn.microsoft.com/en-us/library/aa393720.aspx for details. +// +// Query is a wrapper around DefaultClient.Query. +func Query(query string, dst interface{}, connectServerArgs ...interface{}) error { + if DefaultClient.SWbemServicesClient == nil { + return DefaultClient.Query(query, dst, connectServerArgs...) + } + return DefaultClient.SWbemServicesClient.Query(query, dst, connectServerArgs...) +} + +// A Client is an WMI query client. +// +// Its zero value (DefaultClient) is a usable client. +type Client struct { + // NonePtrZero specifies if nil values for fields which aren't pointers + // should be returned as the field types zero value. + // + // Setting this to true allows stucts without pointer fields to be used + // without the risk failure should a nil value returned from WMI. + NonePtrZero bool + + // PtrNil specifies if nil values for pointer fields should be returned + // as nil. + // + // Setting this to true will set pointer fields to nil where WMI + // returned nil, otherwise the types zero value will be returned. + PtrNil bool + + // AllowMissingFields specifies that struct fields not present in the + // query result should not result in an error. + // + // Setting this to true allows custom queries to be used with full + // struct definitions instead of having to define multiple structs. + AllowMissingFields bool + + // SWbemServiceClient is an optional SWbemServices object that can be + // initialized and then reused across multiple queries. If it is null + // then the method will initialize a new temporary client each time. + SWbemServicesClient *SWbemServices +} + +// DefaultClient is the default Client and is used by Query, QueryNamespace +var DefaultClient = &Client{} + +// Query runs the WQL query and appends the values to dst. +// +// dst must have type *[]S or *[]*S, for some struct type S. Fields selected in +// the query must have the same name in dst. Supported types are all signed and +// unsigned integers, time.Time, string, bool, or a pointer to one of those. +// Array types are not supported. +// +// By default, the local machine and default namespace are used. These can be +// changed using connectServerArgs. See +// http://msdn.microsoft.com/en-us/library/aa393720.aspx for details. +func (c *Client) Query(query string, dst interface{}, connectServerArgs ...interface{}) error { + dv := reflect.ValueOf(dst) + if dv.Kind() != reflect.Ptr || dv.IsNil() { + return ErrInvalidEntityType + } + dv = dv.Elem() + mat, elemType := checkMultiArg(dv) + if mat == multiArgTypeInvalid { + return ErrInvalidEntityType + } + + lock.Lock() + defer lock.Unlock() + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED) + if err != nil { + oleCode := err.(*ole.OleError).Code() + if oleCode != ole.S_OK && oleCode != S_FALSE { + return err + } + } + defer ole.CoUninitialize() + + unknown, err := oleutil.CreateObject("WbemScripting.SWbemLocator") + if err != nil { + return err + } else if unknown == nil { + return ErrNilCreateObject + } + defer unknown.Release() + + wmi, err := unknown.QueryInterface(ole.IID_IDispatch) + if err != nil { + return err + } + defer wmi.Release() + + // service is a SWbemServices + serviceRaw, err := oleutil.CallMethod(wmi, "ConnectServer", connectServerArgs...) + if err != nil { + return err + } + service := serviceRaw.ToIDispatch() + defer serviceRaw.Clear() + + // result is a SWBemObjectSet + resultRaw, err := oleutil.CallMethod(service, "ExecQuery", query) + if err != nil { + return err + } + result := resultRaw.ToIDispatch() + defer resultRaw.Clear() + + count, err := oleInt64(result, "Count") + if err != nil { + return err + } + + enumProperty, err := result.GetProperty("_NewEnum") + if err != nil { + return err + } + defer enumProperty.Clear() + + enum, err := enumProperty.ToIUnknown().IEnumVARIANT(ole.IID_IEnumVariant) + if err != nil { + return err + } + if enum == nil { + return fmt.Errorf("can't get IEnumVARIANT, enum is nil") + } + defer enum.Release() + + // Initialize a slice with Count capacity + dv.Set(reflect.MakeSlice(dv.Type(), 0, int(count))) + + var errFieldMismatch error + for itemRaw, length, err := enum.Next(1); length > 0; itemRaw, length, err = enum.Next(1) { + if err != nil { + return err + } + + err := func() error { + // item is a SWbemObject, but really a Win32_Process + item := itemRaw.ToIDispatch() + defer item.Release() + + ev := reflect.New(elemType) + if err = c.loadEntity(ev.Interface(), item); err != nil { + if _, ok := err.(*ErrFieldMismatch); ok { + // We continue loading entities even in the face of field mismatch errors. + // If we encounter any other error, that other error is returned. Otherwise, + // an ErrFieldMismatch is returned. + errFieldMismatch = err + } else { + return err + } + } + if mat != multiArgTypeStructPtr { + ev = ev.Elem() + } + dv.Set(reflect.Append(dv, ev)) + return nil + }() + if err != nil { + return err + } + } + return errFieldMismatch +} + +// ErrFieldMismatch is returned when a field is to be loaded into a different +// type than the one it was stored from, or when a field is missing or +// unexported in the destination struct. +// StructType is the type of the struct pointed to by the destination argument. +type ErrFieldMismatch struct { + StructType reflect.Type + FieldName string + Reason string +} + +func (e *ErrFieldMismatch) Error() string { + return fmt.Sprintf("wmi: cannot load field %q into a %q: %s", + e.FieldName, e.StructType, e.Reason) +} + +var timeType = reflect.TypeOf(time.Time{}) + +// loadEntity loads a SWbemObject into a struct pointer. +func (c *Client) loadEntity(dst interface{}, src *ole.IDispatch) (errFieldMismatch error) { + v := reflect.ValueOf(dst).Elem() + for i := 0; i < v.NumField(); i++ { + f := v.Field(i) + of := f + isPtr := f.Kind() == reflect.Ptr + if isPtr { + ptr := reflect.New(f.Type().Elem()) + f.Set(ptr) + f = f.Elem() + } + n := v.Type().Field(i).Name + if !f.CanSet() { + return &ErrFieldMismatch{ + StructType: of.Type(), + FieldName: n, + Reason: "CanSet() is false", + } + } + prop, err := oleutil.GetProperty(src, n) + if err != nil { + if !c.AllowMissingFields { + errFieldMismatch = &ErrFieldMismatch{ + StructType: of.Type(), + FieldName: n, + Reason: "no such struct field", + } + } + continue + } + defer prop.Clear() + + if prop.Value() == nil { + continue + } + + switch val := prop.Value().(type) { + case int8, int16, int32, int64, int: + v := reflect.ValueOf(val).Int() + switch f.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + f.SetInt(v) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + f.SetUint(uint64(v)) + default: + return &ErrFieldMismatch{ + StructType: of.Type(), + FieldName: n, + Reason: "not an integer class", + } + } + case uint8, uint16, uint32, uint64: + v := reflect.ValueOf(val).Uint() + switch f.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + f.SetInt(int64(v)) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + f.SetUint(v) + default: + return &ErrFieldMismatch{ + StructType: of.Type(), + FieldName: n, + Reason: "not an integer class", + } + } + case string: + switch f.Kind() { + case reflect.String: + f.SetString(val) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + iv, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return err + } + f.SetInt(iv) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + uv, err := strconv.ParseUint(val, 10, 64) + if err != nil { + return err + } + f.SetUint(uv) + case reflect.Struct: + switch f.Type() { + case timeType: + if len(val) == 25 { + mins, err := strconv.Atoi(val[22:]) + if err != nil { + return err + } + val = val[:22] + fmt.Sprintf("%02d%02d", mins/60, mins%60) + } + t, err := time.Parse("20060102150405.000000-0700", val) + if err != nil { + return err + } + f.Set(reflect.ValueOf(t)) + } + } + case bool: + switch f.Kind() { + case reflect.Bool: + f.SetBool(val) + default: + return &ErrFieldMismatch{ + StructType: of.Type(), + FieldName: n, + Reason: "not a bool", + } + } + case float32: + switch f.Kind() { + case reflect.Float32: + f.SetFloat(float64(val)) + default: + return &ErrFieldMismatch{ + StructType: of.Type(), + FieldName: n, + Reason: "not a Float32", + } + } + default: + if f.Kind() == reflect.Slice { + switch f.Type().Elem().Kind() { + case reflect.String: + safeArray := prop.ToArray() + if safeArray != nil { + arr := safeArray.ToValueArray() + fArr := reflect.MakeSlice(f.Type(), len(arr), len(arr)) + for i, v := range arr { + s := fArr.Index(i) + s.SetString(v.(string)) + } + f.Set(fArr) + } + case reflect.Uint8: + safeArray := prop.ToArray() + if safeArray != nil { + arr := safeArray.ToValueArray() + fArr := reflect.MakeSlice(f.Type(), len(arr), len(arr)) + for i, v := range arr { + s := fArr.Index(i) + s.SetUint(reflect.ValueOf(v).Uint()) + } + f.Set(fArr) + } + default: + return &ErrFieldMismatch{ + StructType: of.Type(), + FieldName: n, + Reason: fmt.Sprintf("unsupported slice type (%T)", val), + } + } + } else { + typeof := reflect.TypeOf(val) + if typeof == nil && (isPtr || c.NonePtrZero) { + if (isPtr && c.PtrNil) || (!isPtr && c.NonePtrZero) { + of.Set(reflect.Zero(of.Type())) + } + break + } + return &ErrFieldMismatch{ + StructType: of.Type(), + FieldName: n, + Reason: fmt.Sprintf("unsupported type (%T)", val), + } + } + } + } + return errFieldMismatch +} + +type multiArgType int + +const ( + multiArgTypeInvalid multiArgType = iota + multiArgTypeStruct + multiArgTypeStructPtr +) + +// checkMultiArg checks that v has type []S, []*S for some struct type S. +// +// It returns what category the slice's elements are, and the reflect.Type +// that represents S. +func checkMultiArg(v reflect.Value) (m multiArgType, elemType reflect.Type) { + if v.Kind() != reflect.Slice { + return multiArgTypeInvalid, nil + } + elemType = v.Type().Elem() + switch elemType.Kind() { + case reflect.Struct: + return multiArgTypeStruct, elemType + case reflect.Ptr: + elemType = elemType.Elem() + if elemType.Kind() == reflect.Struct { + return multiArgTypeStructPtr, elemType + } + } + return multiArgTypeInvalid, nil +} + +func oleInt64(item *ole.IDispatch, prop string) (int64, error) { + v, err := oleutil.GetProperty(item, prop) + if err != nil { + return 0, err + } + defer v.Clear() + + i := int64(v.Val) + return i, nil +} + +// CreateQuery returns a WQL query string that queries all columns of src. where +// is an optional string that is appended to the query, to be used with WHERE +// clauses. In such a case, the "WHERE" string should appear at the beginning. +func CreateQuery(src interface{}, where string) string { + var b bytes.Buffer + b.WriteString("SELECT ") + s := reflect.Indirect(reflect.ValueOf(src)) + t := s.Type() + if s.Kind() == reflect.Slice { + t = t.Elem() + } + if t.Kind() != reflect.Struct { + return "" + } + var fields []string + for i := 0; i < t.NumField(); i++ { + fields = append(fields, t.Field(i).Name) + } + b.WriteString(strings.Join(fields, ", ")) + b.WriteString(" FROM ") + b.WriteString(t.Name()) + b.WriteString(" " + where) + return b.String() +} diff --git a/vendor/github.com/dimchansky/utfbom/.gitignore b/vendor/github.com/dimchansky/utfbom/.gitignore new file mode 100644 index 000000000000..d7ec5cebb98d --- /dev/null +++ b/vendor/github.com/dimchansky/utfbom/.gitignore @@ -0,0 +1,37 @@ +# Binaries for programs and plugins +*.exe +*.dll +*.so +*.dylib +*.o +*.a + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.prof + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 +.glide/ + +# Gogland +.idea/ \ No newline at end of file diff --git a/vendor/github.com/dimchansky/utfbom/.travis.yml b/vendor/github.com/dimchansky/utfbom/.travis.yml new file mode 100644 index 000000000000..3512c85190d7 --- /dev/null +++ b/vendor/github.com/dimchansky/utfbom/.travis.yml @@ -0,0 +1,18 @@ +language: go + +go: + - '1.10' + - '1.11' + +# sudo=false makes the build run using a container +sudo: false + +before_install: + - go get github.com/mattn/goveralls + - go get golang.org/x/tools/cmd/cover + - go get golang.org/x/tools/cmd/goimports + - go get github.com/golang/lint/golint +script: + - gofiles=$(find ./ -name '*.go') && [ -z "$gofiles" ] || unformatted=$(goimports -l $gofiles) && [ -z "$unformatted" ] || (echo >&2 "Go files must be formatted with gofmt. Following files has problem:\n $unformatted" && false) + - golint ./... # This won't break the build, just show warnings + - $HOME/gopath/bin/goveralls -service=travis-ci diff --git a/vendor/github.com/dimchansky/utfbom/LICENSE b/vendor/github.com/dimchansky/utfbom/LICENSE new file mode 100644 index 000000000000..8dada3edaf50 --- /dev/null +++ b/vendor/github.com/dimchansky/utfbom/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/dimchansky/utfbom/README.md b/vendor/github.com/dimchansky/utfbom/README.md new file mode 100644 index 000000000000..8ece280089a5 --- /dev/null +++ b/vendor/github.com/dimchansky/utfbom/README.md @@ -0,0 +1,66 @@ +# utfbom [![Godoc](https://godoc.org/github.com/dimchansky/utfbom?status.png)](https://godoc.org/github.com/dimchansky/utfbom) [![License](https://img.shields.io/:license-apache-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![Build Status](https://travis-ci.org/dimchansky/utfbom.svg?branch=master)](https://travis-ci.org/dimchansky/utfbom) [![Go Report Card](https://goreportcard.com/badge/github.com/dimchansky/utfbom)](https://goreportcard.com/report/github.com/dimchansky/utfbom) [![Coverage Status](https://coveralls.io/repos/github/dimchansky/utfbom/badge.svg?branch=master)](https://coveralls.io/github/dimchansky/utfbom?branch=master) + +The package utfbom implements the detection of the BOM (Unicode Byte Order Mark) and removing as necessary. It can also return the encoding detected by the BOM. + +## Installation + + go get -u github.com/dimchansky/utfbom + +## Example + +```go +package main + +import ( + "bytes" + "fmt" + "io/ioutil" + + "github.com/dimchansky/utfbom" +) + +func main() { + trySkip([]byte("\xEF\xBB\xBFhello")) + trySkip([]byte("hello")) +} + +func trySkip(byteData []byte) { + fmt.Println("Input:", byteData) + + // just skip BOM + output, err := ioutil.ReadAll(utfbom.SkipOnly(bytes.NewReader(byteData))) + if err != nil { + fmt.Println(err) + return + } + fmt.Println("ReadAll with BOM skipping", output) + + // skip BOM and detect encoding + sr, enc := utfbom.Skip(bytes.NewReader(byteData)) + fmt.Printf("Detected encoding: %s\n", enc) + output, err = ioutil.ReadAll(sr) + if err != nil { + fmt.Println(err) + return + } + fmt.Println("ReadAll with BOM detection and skipping", output) + fmt.Println() +} +``` + +Output: + +``` +$ go run main.go +Input: [239 187 191 104 101 108 108 111] +ReadAll with BOM skipping [104 101 108 108 111] +Detected encoding: UTF8 +ReadAll with BOM detection and skipping [104 101 108 108 111] + +Input: [104 101 108 108 111] +ReadAll with BOM skipping [104 101 108 108 111] +Detected encoding: Unknown +ReadAll with BOM detection and skipping [104 101 108 108 111] +``` + + diff --git a/vendor/github.com/dimchansky/utfbom/go.mod b/vendor/github.com/dimchansky/utfbom/go.mod new file mode 100644 index 000000000000..4b9ecc6f545e --- /dev/null +++ b/vendor/github.com/dimchansky/utfbom/go.mod @@ -0,0 +1 @@ +module github.com/dimchansky/utfbom \ No newline at end of file diff --git a/vendor/github.com/dimchansky/utfbom/utfbom.go b/vendor/github.com/dimchansky/utfbom/utfbom.go new file mode 100644 index 000000000000..77a303e564b1 --- /dev/null +++ b/vendor/github.com/dimchansky/utfbom/utfbom.go @@ -0,0 +1,192 @@ +// Package utfbom implements the detection of the BOM (Unicode Byte Order Mark) and removing as necessary. +// It wraps an io.Reader object, creating another object (Reader) that also implements the io.Reader +// interface but provides automatic BOM checking and removing as necessary. +package utfbom + +import ( + "errors" + "io" +) + +// Encoding is type alias for detected UTF encoding. +type Encoding int + +// Constants to identify detected UTF encodings. +const ( + // Unknown encoding, returned when no BOM was detected + Unknown Encoding = iota + + // UTF8, BOM bytes: EF BB BF + UTF8 + + // UTF-16, big-endian, BOM bytes: FE FF + UTF16BigEndian + + // UTF-16, little-endian, BOM bytes: FF FE + UTF16LittleEndian + + // UTF-32, big-endian, BOM bytes: 00 00 FE FF + UTF32BigEndian + + // UTF-32, little-endian, BOM bytes: FF FE 00 00 + UTF32LittleEndian +) + +// String returns a user-friendly string representation of the encoding. Satisfies fmt.Stringer interface. +func (e Encoding) String() string { + switch e { + case UTF8: + return "UTF8" + case UTF16BigEndian: + return "UTF16BigEndian" + case UTF16LittleEndian: + return "UTF16LittleEndian" + case UTF32BigEndian: + return "UTF32BigEndian" + case UTF32LittleEndian: + return "UTF32LittleEndian" + default: + return "Unknown" + } +} + +const maxConsecutiveEmptyReads = 100 + +// Skip creates Reader which automatically detects BOM (Unicode Byte Order Mark) and removes it as necessary. +// It also returns the encoding detected by the BOM. +// If the detected encoding is not needed, you can call the SkipOnly function. +func Skip(rd io.Reader) (*Reader, Encoding) { + // Is it already a Reader? + b, ok := rd.(*Reader) + if ok { + return b, Unknown + } + + enc, left, err := detectUtf(rd) + return &Reader{ + rd: rd, + buf: left, + err: err, + }, enc +} + +// SkipOnly creates Reader which automatically detects BOM (Unicode Byte Order Mark) and removes it as necessary. +func SkipOnly(rd io.Reader) *Reader { + r, _ := Skip(rd) + return r +} + +// Reader implements automatic BOM (Unicode Byte Order Mark) checking and +// removing as necessary for an io.Reader object. +type Reader struct { + rd io.Reader // reader provided by the client + buf []byte // buffered data + err error // last error +} + +// Read is an implementation of io.Reader interface. +// The bytes are taken from the underlying Reader, but it checks for BOMs, removing them as necessary. +func (r *Reader) Read(p []byte) (n int, err error) { + if len(p) == 0 { + return 0, nil + } + + if r.buf == nil { + if r.err != nil { + return 0, r.readErr() + } + + return r.rd.Read(p) + } + + // copy as much as we can + n = copy(p, r.buf) + r.buf = nilIfEmpty(r.buf[n:]) + return n, nil +} + +func (r *Reader) readErr() error { + err := r.err + r.err = nil + return err +} + +var errNegativeRead = errors.New("utfbom: reader returned negative count from Read") + +func detectUtf(rd io.Reader) (enc Encoding, buf []byte, err error) { + buf, err = readBOM(rd) + + if len(buf) >= 4 { + if isUTF32BigEndianBOM4(buf) { + return UTF32BigEndian, nilIfEmpty(buf[4:]), err + } + if isUTF32LittleEndianBOM4(buf) { + return UTF32LittleEndian, nilIfEmpty(buf[4:]), err + } + } + + if len(buf) > 2 && isUTF8BOM3(buf) { + return UTF8, nilIfEmpty(buf[3:]), err + } + + if (err != nil && err != io.EOF) || (len(buf) < 2) { + return Unknown, nilIfEmpty(buf), err + } + + if isUTF16BigEndianBOM2(buf) { + return UTF16BigEndian, nilIfEmpty(buf[2:]), err + } + if isUTF16LittleEndianBOM2(buf) { + return UTF16LittleEndian, nilIfEmpty(buf[2:]), err + } + + return Unknown, nilIfEmpty(buf), err +} + +func readBOM(rd io.Reader) (buf []byte, err error) { + const maxBOMSize = 4 + var bom [maxBOMSize]byte // used to read BOM + + // read as many bytes as possible + for nEmpty, n := 0, 0; err == nil && len(buf) < maxBOMSize; buf = bom[:len(buf)+n] { + if n, err = rd.Read(bom[len(buf):]); n < 0 { + panic(errNegativeRead) + } + if n > 0 { + nEmpty = 0 + } else { + nEmpty++ + if nEmpty >= maxConsecutiveEmptyReads { + err = io.ErrNoProgress + } + } + } + return +} + +func isUTF32BigEndianBOM4(buf []byte) bool { + return buf[0] == 0x00 && buf[1] == 0x00 && buf[2] == 0xFE && buf[3] == 0xFF +} + +func isUTF32LittleEndianBOM4(buf []byte) bool { + return buf[0] == 0xFF && buf[1] == 0xFE && buf[2] == 0x00 && buf[3] == 0x00 +} + +func isUTF8BOM3(buf []byte) bool { + return buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF +} + +func isUTF16BigEndianBOM2(buf []byte) bool { + return buf[0] == 0xFE && buf[1] == 0xFF +} + +func isUTF16LittleEndianBOM2(buf []byte) bool { + return buf[0] == 0xFF && buf[1] == 0xFE +} + +func nilIfEmpty(buf []byte) (res []byte) { + if len(buf) > 0 { + res = buf + } + return +} diff --git a/vendor/github.com/go-ole/go-ole/.travis.yml b/vendor/github.com/go-ole/go-ole/.travis.yml new file mode 100644 index 000000000000..28f740cd5d0a --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/.travis.yml @@ -0,0 +1,8 @@ +language: go +sudo: false + +go: + - 1.9.x + - 1.10.x + - 1.11.x + - tip diff --git a/vendor/github.com/go-ole/go-ole/ChangeLog.md b/vendor/github.com/go-ole/go-ole/ChangeLog.md new file mode 100644 index 000000000000..4ba6a8c64d00 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/ChangeLog.md @@ -0,0 +1,49 @@ +# Version 1.x.x + +* **Add more test cases and reference new test COM server project.** (Placeholder for future additions) + +# Version 1.2.0-alphaX + +**Minimum supported version is now Go 1.4. Go 1.1 support is deprecated, but should still build.** + + * Added CI configuration for Travis-CI and AppVeyor. + * Added test InterfaceID and ClassID for the COM Test Server project. + * Added more inline documentation (#83). + * Added IEnumVARIANT implementation (#88). + * Added IEnumVARIANT test cases (#99, #100, #101). + * Added support for retrieving `time.Time` from VARIANT (#92). + * Added test case for IUnknown (#64). + * Added test case for IDispatch (#64). + * Added test cases for scalar variants (#64, #76). + +# Version 1.1.1 + + * Fixes for Linux build. + * Fixes for Windows build. + +# Version 1.1.0 + +The change to provide building on all platforms is a new feature. The increase in minor version reflects that and allows those who wish to stay on 1.0.x to continue to do so. Support for 1.0.x will be limited to bug fixes. + + * Move GUID out of variables.go into its own file to make new documentation available. + * Move OleError out of ole.go into its own file to make new documentation available. + * Add documentation to utility functions. + * Add documentation to variant receiver functions. + * Add documentation to ole structures. + * Make variant available to other systems outside of Windows. + * Make OLE structures available to other systems outside of Windows. + +## New Features + + * Library should now be built on all platforms supported by Go. Library will NOOP on any platform that is not Windows. + * More functions are now documented and available on godoc.org. + +# Version 1.0.1 + + 1. Fix package references from repository location change. + +# Version 1.0.0 + +This version is stable enough for use. The COM API is still incomplete, but provides enough functionality for accessing COM servers using IDispatch interface. + +There is no changelog for this version. Check commits for history. diff --git a/vendor/github.com/go-ole/go-ole/LICENSE b/vendor/github.com/go-ole/go-ole/LICENSE new file mode 100644 index 000000000000..623ec06f91ca --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright © 2013-2017 Yasuhiro Matsumoto, + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the “Software”), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/go-ole/go-ole/README.md b/vendor/github.com/go-ole/go-ole/README.md new file mode 100644 index 000000000000..7b577558d1cd --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/README.md @@ -0,0 +1,46 @@ +# Go OLE + +[![Build status](https://ci.appveyor.com/api/projects/status/qr0u2sf7q43us9fj?svg=true)](https://ci.appveyor.com/project/jacobsantos/go-ole-jgs28) +[![Build Status](https://travis-ci.org/go-ole/go-ole.svg?branch=master)](https://travis-ci.org/go-ole/go-ole) +[![GoDoc](https://godoc.org/github.com/go-ole/go-ole?status.svg)](https://godoc.org/github.com/go-ole/go-ole) + +Go bindings for Windows COM using shared libraries instead of cgo. + +By Yasuhiro Matsumoto. + +## Install + +To experiment with go-ole, you can just compile and run the example program: + +``` +go get github.com/go-ole/go-ole +cd /path/to/go-ole/ +go test + +cd /path/to/go-ole/example/excel +go run excel.go +``` + +## Continuous Integration + +Continuous integration configuration has been added for both Travis-CI and AppVeyor. You will have to add these to your own account for your fork in order for it to run. + +**Travis-CI** + +Travis-CI was added to check builds on Linux to ensure that `go get` works when cross building. Currently, Travis-CI is not used to test cross-building, but this may be changed in the future. It is also not currently possible to test the library on Linux, since COM API is specific to Windows and it is not currently possible to run a COM server on Linux or even connect to a remote COM server. + +**AppVeyor** + +AppVeyor is used to build on Windows using the (in-development) test COM server. It is currently only used to test the build and ensure that the code works on Windows. It will be used to register a COM server and then run the test cases based on the test COM server. + +The tests currently do run and do pass and this should be maintained with commits. + +## Versioning + +Go OLE uses [semantic versioning](http://semver.org) for version numbers, which is similar to the version contract of the Go language. Which means that the major version will always maintain backwards compatibility with minor versions. Minor versions will only add new additions and changes. Fixes will always be in patch. + +This contract should allow you to upgrade to new minor and patch versions without breakage or modifications to your existing code. Leave a ticket, if there is breakage, so that it could be fixed. + +## LICENSE + +Under the MIT License: http://mattn.mit-license.org/2013 diff --git a/vendor/github.com/go-ole/go-ole/appveyor.yml b/vendor/github.com/go-ole/go-ole/appveyor.yml new file mode 100644 index 000000000000..0d557ac2ff55 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/appveyor.yml @@ -0,0 +1,54 @@ +# Notes: +# - Minimal appveyor.yml file is an empty file. All sections are optional. +# - Indent each level of configuration with 2 spaces. Do not use tabs! +# - All section names are case-sensitive. +# - Section names should be unique on each level. + +version: "1.3.0.{build}-alpha-{branch}" + +os: Windows Server 2012 R2 + +branches: + only: + - master + - v1.2 + - v1.1 + - v1.0 + +skip_tags: true + +clone_folder: c:\gopath\src\github.com\go-ole\go-ole + +environment: + GOPATH: c:\gopath + matrix: + - GOARCH: amd64 + GOVERSION: 1.5 + GOROOT: c:\go + DOWNLOADPLATFORM: "x64" + +install: + - choco install mingw + - SET PATH=c:\tools\mingw64\bin;%PATH% + # - Download COM Server + - ps: Start-FileDownload "https://github.com/go-ole/test-com-server/releases/download/v1.0.2/test-com-server-${env:DOWNLOADPLATFORM}.zip" + - 7z e test-com-server-%DOWNLOADPLATFORM%.zip -oc:\gopath\src\github.com\go-ole\go-ole > NUL + - c:\gopath\src\github.com\go-ole\go-ole\build\register-assembly.bat + # - set + - go version + - go env + - go get -u golang.org/x/tools/cmd/cover + - go get -u golang.org/x/tools/cmd/godoc + - go get -u golang.org/x/tools/cmd/stringer + +build_script: + - cd c:\gopath\src\github.com\go-ole\go-ole + - go get -v -t ./... + - go build + - go test -v -cover ./... + +# disable automatic tests +test: off + +# disable deployment +deploy: off diff --git a/vendor/github.com/go-ole/go-ole/com.go b/vendor/github.com/go-ole/go-ole/com.go new file mode 100644 index 000000000000..6f986b1894ee --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/com.go @@ -0,0 +1,344 @@ +// +build windows + +package ole + +import ( + "syscall" + "unicode/utf16" + "unsafe" +) + +var ( + procCoInitialize, _ = modole32.FindProc("CoInitialize") + procCoInitializeEx, _ = modole32.FindProc("CoInitializeEx") + procCoUninitialize, _ = modole32.FindProc("CoUninitialize") + procCoCreateInstance, _ = modole32.FindProc("CoCreateInstance") + procCoTaskMemFree, _ = modole32.FindProc("CoTaskMemFree") + procCLSIDFromProgID, _ = modole32.FindProc("CLSIDFromProgID") + procCLSIDFromString, _ = modole32.FindProc("CLSIDFromString") + procStringFromCLSID, _ = modole32.FindProc("StringFromCLSID") + procStringFromIID, _ = modole32.FindProc("StringFromIID") + procIIDFromString, _ = modole32.FindProc("IIDFromString") + procCoGetObject, _ = modole32.FindProc("CoGetObject") + procGetUserDefaultLCID, _ = modkernel32.FindProc("GetUserDefaultLCID") + procCopyMemory, _ = modkernel32.FindProc("RtlMoveMemory") + procVariantInit, _ = modoleaut32.FindProc("VariantInit") + procVariantClear, _ = modoleaut32.FindProc("VariantClear") + procVariantTimeToSystemTime, _ = modoleaut32.FindProc("VariantTimeToSystemTime") + procSysAllocString, _ = modoleaut32.FindProc("SysAllocString") + procSysAllocStringLen, _ = modoleaut32.FindProc("SysAllocStringLen") + procSysFreeString, _ = modoleaut32.FindProc("SysFreeString") + procSysStringLen, _ = modoleaut32.FindProc("SysStringLen") + procCreateDispTypeInfo, _ = modoleaut32.FindProc("CreateDispTypeInfo") + procCreateStdDispatch, _ = modoleaut32.FindProc("CreateStdDispatch") + procGetActiveObject, _ = modoleaut32.FindProc("GetActiveObject") + + procGetMessageW, _ = moduser32.FindProc("GetMessageW") + procDispatchMessageW, _ = moduser32.FindProc("DispatchMessageW") +) + +// coInitialize initializes COM library on current thread. +// +// MSDN documentation suggests that this function should not be called. Call +// CoInitializeEx() instead. The reason has to do with threading and this +// function is only for single-threaded apartments. +// +// That said, most users of the library have gotten away with just this +// function. If you are experiencing threading issues, then use +// CoInitializeEx(). +func coInitialize() (err error) { + // http://msdn.microsoft.com/en-us/library/windows/desktop/ms678543(v=vs.85).aspx + // Suggests that no value should be passed to CoInitialized. + // Could just be Call() since the parameter is optional. <-- Needs testing to be sure. + hr, _, _ := procCoInitialize.Call(uintptr(0)) + if hr != 0 { + err = NewError(hr) + } + return +} + +// coInitializeEx initializes COM library with concurrency model. +func coInitializeEx(coinit uint32) (err error) { + // http://msdn.microsoft.com/en-us/library/windows/desktop/ms695279(v=vs.85).aspx + // Suggests that the first parameter is not only optional but should always be NULL. + hr, _, _ := procCoInitializeEx.Call(uintptr(0), uintptr(coinit)) + if hr != 0 { + err = NewError(hr) + } + return +} + +// CoInitialize initializes COM library on current thread. +// +// MSDN documentation suggests that this function should not be called. Call +// CoInitializeEx() instead. The reason has to do with threading and this +// function is only for single-threaded apartments. +// +// That said, most users of the library have gotten away with just this +// function. If you are experiencing threading issues, then use +// CoInitializeEx(). +func CoInitialize(p uintptr) (err error) { + // p is ignored and won't be used. + // Avoid any variable not used errors. + p = uintptr(0) + return coInitialize() +} + +// CoInitializeEx initializes COM library with concurrency model. +func CoInitializeEx(p uintptr, coinit uint32) (err error) { + // Avoid any variable not used errors. + p = uintptr(0) + return coInitializeEx(coinit) +} + +// CoUninitialize uninitializes COM Library. +func CoUninitialize() { + procCoUninitialize.Call() +} + +// CoTaskMemFree frees memory pointer. +func CoTaskMemFree(memptr uintptr) { + procCoTaskMemFree.Call(memptr) +} + +// CLSIDFromProgID retrieves Class Identifier with the given Program Identifier. +// +// The Programmatic Identifier must be registered, because it will be looked up +// in the Windows Registry. The registry entry has the following keys: CLSID, +// Insertable, Protocol and Shell +// (https://msdn.microsoft.com/en-us/library/dd542719(v=vs.85).aspx). +// +// programID identifies the class id with less precision and is not guaranteed +// to be unique. These are usually found in the registry under +// HKEY_LOCAL_MACHINE\SOFTWARE\Classes, usually with the format of +// "Program.Component.Version" with version being optional. +// +// CLSIDFromProgID in Windows API. +func CLSIDFromProgID(progId string) (clsid *GUID, err error) { + var guid GUID + lpszProgID := uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(progId))) + hr, _, _ := procCLSIDFromProgID.Call(lpszProgID, uintptr(unsafe.Pointer(&guid))) + if hr != 0 { + err = NewError(hr) + } + clsid = &guid + return +} + +// CLSIDFromString retrieves Class ID from string representation. +// +// This is technically the string version of the GUID and will convert the +// string to object. +// +// CLSIDFromString in Windows API. +func CLSIDFromString(str string) (clsid *GUID, err error) { + var guid GUID + lpsz := uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(str))) + hr, _, _ := procCLSIDFromString.Call(lpsz, uintptr(unsafe.Pointer(&guid))) + if hr != 0 { + err = NewError(hr) + } + clsid = &guid + return +} + +// StringFromCLSID returns GUID formated string from GUID object. +func StringFromCLSID(clsid *GUID) (str string, err error) { + var p *uint16 + hr, _, _ := procStringFromCLSID.Call(uintptr(unsafe.Pointer(clsid)), uintptr(unsafe.Pointer(&p))) + if hr != 0 { + err = NewError(hr) + } + str = LpOleStrToString(p) + return +} + +// IIDFromString returns GUID from program ID. +func IIDFromString(progId string) (clsid *GUID, err error) { + var guid GUID + lpsz := uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(progId))) + hr, _, _ := procIIDFromString.Call(lpsz, uintptr(unsafe.Pointer(&guid))) + if hr != 0 { + err = NewError(hr) + } + clsid = &guid + return +} + +// StringFromIID returns GUID formatted string from GUID object. +func StringFromIID(iid *GUID) (str string, err error) { + var p *uint16 + hr, _, _ := procStringFromIID.Call(uintptr(unsafe.Pointer(iid)), uintptr(unsafe.Pointer(&p))) + if hr != 0 { + err = NewError(hr) + } + str = LpOleStrToString(p) + return +} + +// CreateInstance of single uninitialized object with GUID. +func CreateInstance(clsid *GUID, iid *GUID) (unk *IUnknown, err error) { + if iid == nil { + iid = IID_IUnknown + } + hr, _, _ := procCoCreateInstance.Call( + uintptr(unsafe.Pointer(clsid)), + 0, + CLSCTX_SERVER, + uintptr(unsafe.Pointer(iid)), + uintptr(unsafe.Pointer(&unk))) + if hr != 0 { + err = NewError(hr) + } + return +} + +// GetActiveObject retrieves pointer to active object. +func GetActiveObject(clsid *GUID, iid *GUID) (unk *IUnknown, err error) { + if iid == nil { + iid = IID_IUnknown + } + hr, _, _ := procGetActiveObject.Call( + uintptr(unsafe.Pointer(clsid)), + uintptr(unsafe.Pointer(iid)), + uintptr(unsafe.Pointer(&unk))) + if hr != 0 { + err = NewError(hr) + } + return +} + +type BindOpts struct { + CbStruct uint32 + GrfFlags uint32 + GrfMode uint32 + TickCountDeadline uint32 +} + +// GetObject retrieves pointer to active object. +func GetObject(programID string, bindOpts *BindOpts, iid *GUID) (unk *IUnknown, err error) { + if bindOpts != nil { + bindOpts.CbStruct = uint32(unsafe.Sizeof(BindOpts{})) + } + if iid == nil { + iid = IID_IUnknown + } + hr, _, _ := procCoGetObject.Call( + uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(programID))), + uintptr(unsafe.Pointer(bindOpts)), + uintptr(unsafe.Pointer(iid)), + uintptr(unsafe.Pointer(&unk))) + if hr != 0 { + err = NewError(hr) + } + return +} + +// VariantInit initializes variant. +func VariantInit(v *VARIANT) (err error) { + hr, _, _ := procVariantInit.Call(uintptr(unsafe.Pointer(v))) + if hr != 0 { + err = NewError(hr) + } + return +} + +// VariantClear clears value in Variant settings to VT_EMPTY. +func VariantClear(v *VARIANT) (err error) { + hr, _, _ := procVariantClear.Call(uintptr(unsafe.Pointer(v))) + if hr != 0 { + err = NewError(hr) + } + return +} + +// SysAllocString allocates memory for string and copies string into memory. +func SysAllocString(v string) (ss *int16) { + pss, _, _ := procSysAllocString.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(v)))) + ss = (*int16)(unsafe.Pointer(pss)) + return +} + +// SysAllocStringLen copies up to length of given string returning pointer. +func SysAllocStringLen(v string) (ss *int16) { + utf16 := utf16.Encode([]rune(v + "\x00")) + ptr := &utf16[0] + + pss, _, _ := procSysAllocStringLen.Call(uintptr(unsafe.Pointer(ptr)), uintptr(len(utf16)-1)) + ss = (*int16)(unsafe.Pointer(pss)) + return +} + +// SysFreeString frees string system memory. This must be called with SysAllocString. +func SysFreeString(v *int16) (err error) { + hr, _, _ := procSysFreeString.Call(uintptr(unsafe.Pointer(v))) + if hr != 0 { + err = NewError(hr) + } + return +} + +// SysStringLen is the length of the system allocated string. +func SysStringLen(v *int16) uint32 { + l, _, _ := procSysStringLen.Call(uintptr(unsafe.Pointer(v))) + return uint32(l) +} + +// CreateStdDispatch provides default IDispatch implementation for IUnknown. +// +// This handles default IDispatch implementation for objects. It haves a few +// limitations with only supporting one language. It will also only return +// default exception codes. +func CreateStdDispatch(unk *IUnknown, v uintptr, ptinfo *IUnknown) (disp *IDispatch, err error) { + hr, _, _ := procCreateStdDispatch.Call( + uintptr(unsafe.Pointer(unk)), + v, + uintptr(unsafe.Pointer(ptinfo)), + uintptr(unsafe.Pointer(&disp))) + if hr != 0 { + err = NewError(hr) + } + return +} + +// CreateDispTypeInfo provides default ITypeInfo implementation for IDispatch. +// +// This will not handle the full implementation of the interface. +func CreateDispTypeInfo(idata *INTERFACEDATA) (pptinfo *IUnknown, err error) { + hr, _, _ := procCreateDispTypeInfo.Call( + uintptr(unsafe.Pointer(idata)), + uintptr(GetUserDefaultLCID()), + uintptr(unsafe.Pointer(&pptinfo))) + if hr != 0 { + err = NewError(hr) + } + return +} + +// copyMemory moves location of a block of memory. +func copyMemory(dest unsafe.Pointer, src unsafe.Pointer, length uint32) { + procCopyMemory.Call(uintptr(dest), uintptr(src), uintptr(length)) +} + +// GetUserDefaultLCID retrieves current user default locale. +func GetUserDefaultLCID() (lcid uint32) { + ret, _, _ := procGetUserDefaultLCID.Call() + lcid = uint32(ret) + return +} + +// GetMessage in message queue from runtime. +// +// This function appears to block. PeekMessage does not block. +func GetMessage(msg *Msg, hwnd uint32, MsgFilterMin uint32, MsgFilterMax uint32) (ret int32, err error) { + r0, _, err := procGetMessageW.Call(uintptr(unsafe.Pointer(msg)), uintptr(hwnd), uintptr(MsgFilterMin), uintptr(MsgFilterMax)) + ret = int32(r0) + return +} + +// DispatchMessage to window procedure. +func DispatchMessage(msg *Msg) (ret int32) { + r0, _, _ := procDispatchMessageW.Call(uintptr(unsafe.Pointer(msg))) + ret = int32(r0) + return +} diff --git a/vendor/github.com/go-ole/go-ole/com_func.go b/vendor/github.com/go-ole/go-ole/com_func.go new file mode 100644 index 000000000000..cef539d9ddd6 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/com_func.go @@ -0,0 +1,174 @@ +// +build !windows + +package ole + +import ( + "time" + "unsafe" +) + +// coInitialize initializes COM library on current thread. +// +// MSDN documentation suggests that this function should not be called. Call +// CoInitializeEx() instead. The reason has to do with threading and this +// function is only for single-threaded apartments. +// +// That said, most users of the library have gotten away with just this +// function. If you are experiencing threading issues, then use +// CoInitializeEx(). +func coInitialize() error { + return NewError(E_NOTIMPL) +} + +// coInitializeEx initializes COM library with concurrency model. +func coInitializeEx(coinit uint32) error { + return NewError(E_NOTIMPL) +} + +// CoInitialize initializes COM library on current thread. +// +// MSDN documentation suggests that this function should not be called. Call +// CoInitializeEx() instead. The reason has to do with threading and this +// function is only for single-threaded apartments. +// +// That said, most users of the library have gotten away with just this +// function. If you are experiencing threading issues, then use +// CoInitializeEx(). +func CoInitialize(p uintptr) error { + return NewError(E_NOTIMPL) +} + +// CoInitializeEx initializes COM library with concurrency model. +func CoInitializeEx(p uintptr, coinit uint32) error { + return NewError(E_NOTIMPL) +} + +// CoUninitialize uninitializes COM Library. +func CoUninitialize() {} + +// CoTaskMemFree frees memory pointer. +func CoTaskMemFree(memptr uintptr) {} + +// CLSIDFromProgID retrieves Class Identifier with the given Program Identifier. +// +// The Programmatic Identifier must be registered, because it will be looked up +// in the Windows Registry. The registry entry has the following keys: CLSID, +// Insertable, Protocol and Shell +// (https://msdn.microsoft.com/en-us/library/dd542719(v=vs.85).aspx). +// +// programID identifies the class id with less precision and is not guaranteed +// to be unique. These are usually found in the registry under +// HKEY_LOCAL_MACHINE\SOFTWARE\Classes, usually with the format of +// "Program.Component.Version" with version being optional. +// +// CLSIDFromProgID in Windows API. +func CLSIDFromProgID(progId string) (*GUID, error) { + return nil, NewError(E_NOTIMPL) +} + +// CLSIDFromString retrieves Class ID from string representation. +// +// This is technically the string version of the GUID and will convert the +// string to object. +// +// CLSIDFromString in Windows API. +func CLSIDFromString(str string) (*GUID, error) { + return nil, NewError(E_NOTIMPL) +} + +// StringFromCLSID returns GUID formated string from GUID object. +func StringFromCLSID(clsid *GUID) (string, error) { + return "", NewError(E_NOTIMPL) +} + +// IIDFromString returns GUID from program ID. +func IIDFromString(progId string) (*GUID, error) { + return nil, NewError(E_NOTIMPL) +} + +// StringFromIID returns GUID formatted string from GUID object. +func StringFromIID(iid *GUID) (string, error) { + return "", NewError(E_NOTIMPL) +} + +// CreateInstance of single uninitialized object with GUID. +func CreateInstance(clsid *GUID, iid *GUID) (*IUnknown, error) { + return nil, NewError(E_NOTIMPL) +} + +// GetActiveObject retrieves pointer to active object. +func GetActiveObject(clsid *GUID, iid *GUID) (*IUnknown, error) { + return nil, NewError(E_NOTIMPL) +} + +// VariantInit initializes variant. +func VariantInit(v *VARIANT) error { + return NewError(E_NOTIMPL) +} + +// VariantClear clears value in Variant settings to VT_EMPTY. +func VariantClear(v *VARIANT) error { + return NewError(E_NOTIMPL) +} + +// SysAllocString allocates memory for string and copies string into memory. +func SysAllocString(v string) *int16 { + u := int16(0) + return &u +} + +// SysAllocStringLen copies up to length of given string returning pointer. +func SysAllocStringLen(v string) *int16 { + u := int16(0) + return &u +} + +// SysFreeString frees string system memory. This must be called with SysAllocString. +func SysFreeString(v *int16) error { + return NewError(E_NOTIMPL) +} + +// SysStringLen is the length of the system allocated string. +func SysStringLen(v *int16) uint32 { + return uint32(0) +} + +// CreateStdDispatch provides default IDispatch implementation for IUnknown. +// +// This handles default IDispatch implementation for objects. It haves a few +// limitations with only supporting one language. It will also only return +// default exception codes. +func CreateStdDispatch(unk *IUnknown, v uintptr, ptinfo *IUnknown) (*IDispatch, error) { + return nil, NewError(E_NOTIMPL) +} + +// CreateDispTypeInfo provides default ITypeInfo implementation for IDispatch. +// +// This will not handle the full implementation of the interface. +func CreateDispTypeInfo(idata *INTERFACEDATA) (*IUnknown, error) { + return nil, NewError(E_NOTIMPL) +} + +// copyMemory moves location of a block of memory. +func copyMemory(dest unsafe.Pointer, src unsafe.Pointer, length uint32) {} + +// GetUserDefaultLCID retrieves current user default locale. +func GetUserDefaultLCID() uint32 { + return uint32(0) +} + +// GetMessage in message queue from runtime. +// +// This function appears to block. PeekMessage does not block. +func GetMessage(msg *Msg, hwnd uint32, MsgFilterMin uint32, MsgFilterMax uint32) (int32, error) { + return int32(0), NewError(E_NOTIMPL) +} + +// DispatchMessage to window procedure. +func DispatchMessage(msg *Msg) int32 { + return int32(0) +} + +func GetVariantDate(value uint64) (time.Time, error) { + return time.Now(), NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/connect.go b/vendor/github.com/go-ole/go-ole/connect.go new file mode 100644 index 000000000000..b2ac2ec67ac9 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/connect.go @@ -0,0 +1,192 @@ +package ole + +// Connection contains IUnknown for fluent interface interaction. +// +// Deprecated. Use oleutil package instead. +type Connection struct { + Object *IUnknown // Access COM +} + +// Initialize COM. +func (*Connection) Initialize() (err error) { + return coInitialize() +} + +// Uninitialize COM. +func (*Connection) Uninitialize() { + CoUninitialize() +} + +// Create IUnknown object based first on ProgId and then from String. +func (c *Connection) Create(progId string) (err error) { + var clsid *GUID + clsid, err = CLSIDFromProgID(progId) + if err != nil { + clsid, err = CLSIDFromString(progId) + if err != nil { + return + } + } + + unknown, err := CreateInstance(clsid, IID_IUnknown) + if err != nil { + return + } + c.Object = unknown + + return +} + +// Release IUnknown object. +func (c *Connection) Release() { + c.Object.Release() +} + +// Load COM object from list of programIDs or strings. +func (c *Connection) Load(names ...string) (errors []error) { + var tempErrors []error = make([]error, len(names)) + var numErrors int = 0 + for _, name := range names { + err := c.Create(name) + if err != nil { + tempErrors = append(tempErrors, err) + numErrors += 1 + continue + } + break + } + + copy(errors, tempErrors[0:numErrors]) + return +} + +// Dispatch returns Dispatch object. +func (c *Connection) Dispatch() (object *Dispatch, err error) { + dispatch, err := c.Object.QueryInterface(IID_IDispatch) + if err != nil { + return + } + object = &Dispatch{dispatch} + return +} + +// Dispatch stores IDispatch object. +type Dispatch struct { + Object *IDispatch // Dispatch object. +} + +// Call method on IDispatch with parameters. +func (d *Dispatch) Call(method string, params ...interface{}) (result *VARIANT, err error) { + id, err := d.GetId(method) + if err != nil { + return + } + + result, err = d.Invoke(id, DISPATCH_METHOD, params) + return +} + +// MustCall method on IDispatch with parameters. +func (d *Dispatch) MustCall(method string, params ...interface{}) (result *VARIANT) { + id, err := d.GetId(method) + if err != nil { + panic(err) + } + + result, err = d.Invoke(id, DISPATCH_METHOD, params) + if err != nil { + panic(err) + } + + return +} + +// Get property on IDispatch with parameters. +func (d *Dispatch) Get(name string, params ...interface{}) (result *VARIANT, err error) { + id, err := d.GetId(name) + if err != nil { + return + } + result, err = d.Invoke(id, DISPATCH_PROPERTYGET, params) + return +} + +// MustGet property on IDispatch with parameters. +func (d *Dispatch) MustGet(name string, params ...interface{}) (result *VARIANT) { + id, err := d.GetId(name) + if err != nil { + panic(err) + } + + result, err = d.Invoke(id, DISPATCH_PROPERTYGET, params) + if err != nil { + panic(err) + } + return +} + +// Set property on IDispatch with parameters. +func (d *Dispatch) Set(name string, params ...interface{}) (result *VARIANT, err error) { + id, err := d.GetId(name) + if err != nil { + return + } + result, err = d.Invoke(id, DISPATCH_PROPERTYPUT, params) + return +} + +// MustSet property on IDispatch with parameters. +func (d *Dispatch) MustSet(name string, params ...interface{}) (result *VARIANT) { + id, err := d.GetId(name) + if err != nil { + panic(err) + } + + result, err = d.Invoke(id, DISPATCH_PROPERTYPUT, params) + if err != nil { + panic(err) + } + return +} + +// GetId retrieves ID of name on IDispatch. +func (d *Dispatch) GetId(name string) (id int32, err error) { + var dispid []int32 + dispid, err = d.Object.GetIDsOfName([]string{name}) + if err != nil { + return + } + id = dispid[0] + return +} + +// GetIds retrieves all IDs of names on IDispatch. +func (d *Dispatch) GetIds(names ...string) (dispid []int32, err error) { + dispid, err = d.Object.GetIDsOfName(names) + return +} + +// Invoke IDispatch on DisplayID of dispatch type with parameters. +// +// There have been problems where if send cascading params..., it would error +// out because the parameters would be empty. +func (d *Dispatch) Invoke(id int32, dispatch int16, params []interface{}) (result *VARIANT, err error) { + if len(params) < 1 { + result, err = d.Object.Invoke(id, dispatch) + } else { + result, err = d.Object.Invoke(id, dispatch, params...) + } + return +} + +// Release IDispatch object. +func (d *Dispatch) Release() { + d.Object.Release() +} + +// Connect initializes COM and attempts to load IUnknown based on given names. +func Connect(names ...string) (connection *Connection) { + connection.Initialize() + connection.Load(names...) + return +} diff --git a/vendor/github.com/go-ole/go-ole/constants.go b/vendor/github.com/go-ole/go-ole/constants.go new file mode 100644 index 000000000000..fd0c6d74b0e9 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/constants.go @@ -0,0 +1,153 @@ +package ole + +const ( + CLSCTX_INPROC_SERVER = 1 + CLSCTX_INPROC_HANDLER = 2 + CLSCTX_LOCAL_SERVER = 4 + CLSCTX_INPROC_SERVER16 = 8 + CLSCTX_REMOTE_SERVER = 16 + CLSCTX_ALL = CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER + CLSCTX_INPROC = CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER + CLSCTX_SERVER = CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER +) + +const ( + COINIT_APARTMENTTHREADED = 0x2 + COINIT_MULTITHREADED = 0x0 + COINIT_DISABLE_OLE1DDE = 0x4 + COINIT_SPEED_OVER_MEMORY = 0x8 +) + +const ( + DISPATCH_METHOD = 1 + DISPATCH_PROPERTYGET = 2 + DISPATCH_PROPERTYPUT = 4 + DISPATCH_PROPERTYPUTREF = 8 +) + +const ( + S_OK = 0x00000000 + E_UNEXPECTED = 0x8000FFFF + E_NOTIMPL = 0x80004001 + E_OUTOFMEMORY = 0x8007000E + E_INVALIDARG = 0x80070057 + E_NOINTERFACE = 0x80004002 + E_POINTER = 0x80004003 + E_HANDLE = 0x80070006 + E_ABORT = 0x80004004 + E_FAIL = 0x80004005 + E_ACCESSDENIED = 0x80070005 + E_PENDING = 0x8000000A + + CO_E_CLASSSTRING = 0x800401F3 +) + +const ( + CC_FASTCALL = iota + CC_CDECL + CC_MSCPASCAL + CC_PASCAL = CC_MSCPASCAL + CC_MACPASCAL + CC_STDCALL + CC_FPFASTCALL + CC_SYSCALL + CC_MPWCDECL + CC_MPWPASCAL + CC_MAX = CC_MPWPASCAL +) + +type VT uint16 + +const ( + VT_EMPTY VT = 0x0 + VT_NULL VT = 0x1 + VT_I2 VT = 0x2 + VT_I4 VT = 0x3 + VT_R4 VT = 0x4 + VT_R8 VT = 0x5 + VT_CY VT = 0x6 + VT_DATE VT = 0x7 + VT_BSTR VT = 0x8 + VT_DISPATCH VT = 0x9 + VT_ERROR VT = 0xa + VT_BOOL VT = 0xb + VT_VARIANT VT = 0xc + VT_UNKNOWN VT = 0xd + VT_DECIMAL VT = 0xe + VT_I1 VT = 0x10 + VT_UI1 VT = 0x11 + VT_UI2 VT = 0x12 + VT_UI4 VT = 0x13 + VT_I8 VT = 0x14 + VT_UI8 VT = 0x15 + VT_INT VT = 0x16 + VT_UINT VT = 0x17 + VT_VOID VT = 0x18 + VT_HRESULT VT = 0x19 + VT_PTR VT = 0x1a + VT_SAFEARRAY VT = 0x1b + VT_CARRAY VT = 0x1c + VT_USERDEFINED VT = 0x1d + VT_LPSTR VT = 0x1e + VT_LPWSTR VT = 0x1f + VT_RECORD VT = 0x24 + VT_INT_PTR VT = 0x25 + VT_UINT_PTR VT = 0x26 + VT_FILETIME VT = 0x40 + VT_BLOB VT = 0x41 + VT_STREAM VT = 0x42 + VT_STORAGE VT = 0x43 + VT_STREAMED_OBJECT VT = 0x44 + VT_STORED_OBJECT VT = 0x45 + VT_BLOB_OBJECT VT = 0x46 + VT_CF VT = 0x47 + VT_CLSID VT = 0x48 + VT_BSTR_BLOB VT = 0xfff + VT_VECTOR VT = 0x1000 + VT_ARRAY VT = 0x2000 + VT_BYREF VT = 0x4000 + VT_RESERVED VT = 0x8000 + VT_ILLEGAL VT = 0xffff + VT_ILLEGALMASKED VT = 0xfff + VT_TYPEMASK VT = 0xfff +) + +const ( + DISPID_UNKNOWN = -1 + DISPID_VALUE = 0 + DISPID_PROPERTYPUT = -3 + DISPID_NEWENUM = -4 + DISPID_EVALUATE = -5 + DISPID_CONSTRUCTOR = -6 + DISPID_DESTRUCTOR = -7 + DISPID_COLLECT = -8 +) + +const ( + TKIND_ENUM = 1 + TKIND_RECORD = 2 + TKIND_MODULE = 3 + TKIND_INTERFACE = 4 + TKIND_DISPATCH = 5 + TKIND_COCLASS = 6 + TKIND_ALIAS = 7 + TKIND_UNION = 8 + TKIND_MAX = 9 +) + +// Safe Array Feature Flags + +const ( + FADF_AUTO = 0x0001 + FADF_STATIC = 0x0002 + FADF_EMBEDDED = 0x0004 + FADF_FIXEDSIZE = 0x0010 + FADF_RECORD = 0x0020 + FADF_HAVEIID = 0x0040 + FADF_HAVEVARTYPE = 0x0080 + FADF_BSTR = 0x0100 + FADF_UNKNOWN = 0x0200 + FADF_DISPATCH = 0x0400 + FADF_VARIANT = 0x0800 + FADF_RESERVED = 0xF008 +) diff --git a/vendor/github.com/go-ole/go-ole/error.go b/vendor/github.com/go-ole/go-ole/error.go new file mode 100644 index 000000000000..096b456d3a1f --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/error.go @@ -0,0 +1,51 @@ +package ole + +// OleError stores COM errors. +type OleError struct { + hr uintptr + description string + subError error +} + +// NewError creates new error with HResult. +func NewError(hr uintptr) *OleError { + return &OleError{hr: hr} +} + +// NewErrorWithDescription creates new COM error with HResult and description. +func NewErrorWithDescription(hr uintptr, description string) *OleError { + return &OleError{hr: hr, description: description} +} + +// NewErrorWithSubError creates new COM error with parent error. +func NewErrorWithSubError(hr uintptr, description string, err error) *OleError { + return &OleError{hr: hr, description: description, subError: err} +} + +// Code is the HResult. +func (v *OleError) Code() uintptr { + return uintptr(v.hr) +} + +// String description, either manually set or format message with error code. +func (v *OleError) String() string { + if v.description != "" { + return errstr(int(v.hr)) + " (" + v.description + ")" + } + return errstr(int(v.hr)) +} + +// Error implements error interface. +func (v *OleError) Error() string { + return v.String() +} + +// Description retrieves error summary, if there is one. +func (v *OleError) Description() string { + return v.description +} + +// SubError returns parent error, if there is one. +func (v *OleError) SubError() error { + return v.subError +} diff --git a/vendor/github.com/go-ole/go-ole/error_func.go b/vendor/github.com/go-ole/go-ole/error_func.go new file mode 100644 index 000000000000..8a2ffaa2724f --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/error_func.go @@ -0,0 +1,8 @@ +// +build !windows + +package ole + +// errstr converts error code to string. +func errstr(errno int) string { + return "" +} diff --git a/vendor/github.com/go-ole/go-ole/error_windows.go b/vendor/github.com/go-ole/go-ole/error_windows.go new file mode 100644 index 000000000000..d0e8e68595c4 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/error_windows.go @@ -0,0 +1,24 @@ +// +build windows + +package ole + +import ( + "fmt" + "syscall" + "unicode/utf16" +) + +// errstr converts error code to string. +func errstr(errno int) string { + // ask windows for the remaining errors + var flags uint32 = syscall.FORMAT_MESSAGE_FROM_SYSTEM | syscall.FORMAT_MESSAGE_ARGUMENT_ARRAY | syscall.FORMAT_MESSAGE_IGNORE_INSERTS + b := make([]uint16, 300) + n, err := syscall.FormatMessage(flags, 0, uint32(errno), 0, b, nil) + if err != nil { + return fmt.Sprintf("error %d (FormatMessage failed with: %v)", errno, err) + } + // trim terminating \r and \n + for ; n > 0 && (b[n-1] == '\n' || b[n-1] == '\r'); n-- { + } + return string(utf16.Decode(b[:n])) +} diff --git a/vendor/github.com/go-ole/go-ole/go.mod b/vendor/github.com/go-ole/go-ole/go.mod new file mode 100644 index 000000000000..df98533ea904 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/go.mod @@ -0,0 +1,3 @@ +module github.com/go-ole/go-ole + +go 1.12 diff --git a/vendor/github.com/go-ole/go-ole/guid.go b/vendor/github.com/go-ole/go-ole/guid.go new file mode 100644 index 000000000000..8d20f68fbf4a --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/guid.go @@ -0,0 +1,284 @@ +package ole + +var ( + // IID_NULL is null Interface ID, used when no other Interface ID is known. + IID_NULL = NewGUID("{00000000-0000-0000-0000-000000000000}") + + // IID_IUnknown is for IUnknown interfaces. + IID_IUnknown = NewGUID("{00000000-0000-0000-C000-000000000046}") + + // IID_IDispatch is for IDispatch interfaces. + IID_IDispatch = NewGUID("{00020400-0000-0000-C000-000000000046}") + + // IID_IEnumVariant is for IEnumVariant interfaces + IID_IEnumVariant = NewGUID("{00020404-0000-0000-C000-000000000046}") + + // IID_IConnectionPointContainer is for IConnectionPointContainer interfaces. + IID_IConnectionPointContainer = NewGUID("{B196B284-BAB4-101A-B69C-00AA00341D07}") + + // IID_IConnectionPoint is for IConnectionPoint interfaces. + IID_IConnectionPoint = NewGUID("{B196B286-BAB4-101A-B69C-00AA00341D07}") + + // IID_IInspectable is for IInspectable interfaces. + IID_IInspectable = NewGUID("{AF86E2E0-B12D-4C6A-9C5A-D7AA65101E90}") + + // IID_IProvideClassInfo is for IProvideClassInfo interfaces. + IID_IProvideClassInfo = NewGUID("{B196B283-BAB4-101A-B69C-00AA00341D07}") +) + +// These are for testing and not part of any library. +var ( + // IID_ICOMTestString is for ICOMTestString interfaces. + // + // {E0133EB4-C36F-469A-9D3D-C66B84BE19ED} + IID_ICOMTestString = NewGUID("{E0133EB4-C36F-469A-9D3D-C66B84BE19ED}") + + // IID_ICOMTestInt8 is for ICOMTestInt8 interfaces. + // + // {BEB06610-EB84-4155-AF58-E2BFF53680B4} + IID_ICOMTestInt8 = NewGUID("{BEB06610-EB84-4155-AF58-E2BFF53680B4}") + + // IID_ICOMTestInt16 is for ICOMTestInt16 interfaces. + // + // {DAA3F9FA-761E-4976-A860-8364CE55F6FC} + IID_ICOMTestInt16 = NewGUID("{DAA3F9FA-761E-4976-A860-8364CE55F6FC}") + + // IID_ICOMTestInt32 is for ICOMTestInt32 interfaces. + // + // {E3DEDEE7-38A2-4540-91D1-2EEF1D8891B0} + IID_ICOMTestInt32 = NewGUID("{E3DEDEE7-38A2-4540-91D1-2EEF1D8891B0}") + + // IID_ICOMTestInt64 is for ICOMTestInt64 interfaces. + // + // {8D437CBC-B3ED-485C-BC32-C336432A1623} + IID_ICOMTestInt64 = NewGUID("{8D437CBC-B3ED-485C-BC32-C336432A1623}") + + // IID_ICOMTestFloat is for ICOMTestFloat interfaces. + // + // {BF1ED004-EA02-456A-AA55-2AC8AC6B054C} + IID_ICOMTestFloat = NewGUID("{BF1ED004-EA02-456A-AA55-2AC8AC6B054C}") + + // IID_ICOMTestDouble is for ICOMTestDouble interfaces. + // + // {BF908A81-8687-4E93-999F-D86FAB284BA0} + IID_ICOMTestDouble = NewGUID("{BF908A81-8687-4E93-999F-D86FAB284BA0}") + + // IID_ICOMTestBoolean is for ICOMTestBoolean interfaces. + // + // {D530E7A6-4EE8-40D1-8931-3D63B8605010} + IID_ICOMTestBoolean = NewGUID("{D530E7A6-4EE8-40D1-8931-3D63B8605010}") + + // IID_ICOMEchoTestObject is for ICOMEchoTestObject interfaces. + // + // {6485B1EF-D780-4834-A4FE-1EBB51746CA3} + IID_ICOMEchoTestObject = NewGUID("{6485B1EF-D780-4834-A4FE-1EBB51746CA3}") + + // IID_ICOMTestTypes is for ICOMTestTypes interfaces. + // + // {CCA8D7AE-91C0-4277-A8B3-FF4EDF28D3C0} + IID_ICOMTestTypes = NewGUID("{CCA8D7AE-91C0-4277-A8B3-FF4EDF28D3C0}") + + // CLSID_COMEchoTestObject is for COMEchoTestObject class. + // + // {3C24506A-AE9E-4D50-9157-EF317281F1B0} + CLSID_COMEchoTestObject = NewGUID("{3C24506A-AE9E-4D50-9157-EF317281F1B0}") + + // CLSID_COMTestScalarClass is for COMTestScalarClass class. + // + // {865B85C5-0334-4AC6-9EF6-AACEC8FC5E86} + CLSID_COMTestScalarClass = NewGUID("{865B85C5-0334-4AC6-9EF6-AACEC8FC5E86}") +) + +const hextable = "0123456789ABCDEF" +const emptyGUID = "{00000000-0000-0000-0000-000000000000}" + +// GUID is Windows API specific GUID type. +// +// This exists to match Windows GUID type for direct passing for COM. +// Format is in xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx. +type GUID struct { + Data1 uint32 + Data2 uint16 + Data3 uint16 + Data4 [8]byte +} + +// NewGUID converts the given string into a globally unique identifier that is +// compliant with the Windows API. +// +// The supplied string may be in any of these formats: +// +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +// XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX +// {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} +// +// The conversion of the supplied string is not case-sensitive. +func NewGUID(guid string) *GUID { + d := []byte(guid) + var d1, d2, d3, d4a, d4b []byte + + switch len(d) { + case 38: + if d[0] != '{' || d[37] != '}' { + return nil + } + d = d[1:37] + fallthrough + case 36: + if d[8] != '-' || d[13] != '-' || d[18] != '-' || d[23] != '-' { + return nil + } + d1 = d[0:8] + d2 = d[9:13] + d3 = d[14:18] + d4a = d[19:23] + d4b = d[24:36] + case 32: + d1 = d[0:8] + d2 = d[8:12] + d3 = d[12:16] + d4a = d[16:20] + d4b = d[20:32] + default: + return nil + } + + var g GUID + var ok1, ok2, ok3, ok4 bool + g.Data1, ok1 = decodeHexUint32(d1) + g.Data2, ok2 = decodeHexUint16(d2) + g.Data3, ok3 = decodeHexUint16(d3) + g.Data4, ok4 = decodeHexByte64(d4a, d4b) + if ok1 && ok2 && ok3 && ok4 { + return &g + } + return nil +} + +func decodeHexUint32(src []byte) (value uint32, ok bool) { + var b1, b2, b3, b4 byte + var ok1, ok2, ok3, ok4 bool + b1, ok1 = decodeHexByte(src[0], src[1]) + b2, ok2 = decodeHexByte(src[2], src[3]) + b3, ok3 = decodeHexByte(src[4], src[5]) + b4, ok4 = decodeHexByte(src[6], src[7]) + value = (uint32(b1) << 24) | (uint32(b2) << 16) | (uint32(b3) << 8) | uint32(b4) + ok = ok1 && ok2 && ok3 && ok4 + return +} + +func decodeHexUint16(src []byte) (value uint16, ok bool) { + var b1, b2 byte + var ok1, ok2 bool + b1, ok1 = decodeHexByte(src[0], src[1]) + b2, ok2 = decodeHexByte(src[2], src[3]) + value = (uint16(b1) << 8) | uint16(b2) + ok = ok1 && ok2 + return +} + +func decodeHexByte64(s1 []byte, s2 []byte) (value [8]byte, ok bool) { + var ok1, ok2, ok3, ok4, ok5, ok6, ok7, ok8 bool + value[0], ok1 = decodeHexByte(s1[0], s1[1]) + value[1], ok2 = decodeHexByte(s1[2], s1[3]) + value[2], ok3 = decodeHexByte(s2[0], s2[1]) + value[3], ok4 = decodeHexByte(s2[2], s2[3]) + value[4], ok5 = decodeHexByte(s2[4], s2[5]) + value[5], ok6 = decodeHexByte(s2[6], s2[7]) + value[6], ok7 = decodeHexByte(s2[8], s2[9]) + value[7], ok8 = decodeHexByte(s2[10], s2[11]) + ok = ok1 && ok2 && ok3 && ok4 && ok5 && ok6 && ok7 && ok8 + return +} + +func decodeHexByte(c1, c2 byte) (value byte, ok bool) { + var n1, n2 byte + var ok1, ok2 bool + n1, ok1 = decodeHexChar(c1) + n2, ok2 = decodeHexChar(c2) + value = (n1 << 4) | n2 + ok = ok1 && ok2 + return +} + +func decodeHexChar(c byte) (byte, bool) { + switch { + case '0' <= c && c <= '9': + return c - '0', true + case 'a' <= c && c <= 'f': + return c - 'a' + 10, true + case 'A' <= c && c <= 'F': + return c - 'A' + 10, true + } + + return 0, false +} + +// String converts the GUID to string form. It will adhere to this pattern: +// +// {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} +// +// If the GUID is nil, the string representation of an empty GUID is returned: +// +// {00000000-0000-0000-0000-000000000000} +func (guid *GUID) String() string { + if guid == nil { + return emptyGUID + } + + var c [38]byte + c[0] = '{' + putUint32Hex(c[1:9], guid.Data1) + c[9] = '-' + putUint16Hex(c[10:14], guid.Data2) + c[14] = '-' + putUint16Hex(c[15:19], guid.Data3) + c[19] = '-' + putByteHex(c[20:24], guid.Data4[0:2]) + c[24] = '-' + putByteHex(c[25:37], guid.Data4[2:8]) + c[37] = '}' + return string(c[:]) +} + +func putUint32Hex(b []byte, v uint32) { + b[0] = hextable[byte(v>>24)>>4] + b[1] = hextable[byte(v>>24)&0x0f] + b[2] = hextable[byte(v>>16)>>4] + b[3] = hextable[byte(v>>16)&0x0f] + b[4] = hextable[byte(v>>8)>>4] + b[5] = hextable[byte(v>>8)&0x0f] + b[6] = hextable[byte(v)>>4] + b[7] = hextable[byte(v)&0x0f] +} + +func putUint16Hex(b []byte, v uint16) { + b[0] = hextable[byte(v>>8)>>4] + b[1] = hextable[byte(v>>8)&0x0f] + b[2] = hextable[byte(v)>>4] + b[3] = hextable[byte(v)&0x0f] +} + +func putByteHex(dst, src []byte) { + for i := 0; i < len(src); i++ { + dst[i*2] = hextable[src[i]>>4] + dst[i*2+1] = hextable[src[i]&0x0f] + } +} + +// IsEqualGUID compares two GUID. +// +// Not constant time comparison. +func IsEqualGUID(guid1 *GUID, guid2 *GUID) bool { + return guid1.Data1 == guid2.Data1 && + guid1.Data2 == guid2.Data2 && + guid1.Data3 == guid2.Data3 && + guid1.Data4[0] == guid2.Data4[0] && + guid1.Data4[1] == guid2.Data4[1] && + guid1.Data4[2] == guid2.Data4[2] && + guid1.Data4[3] == guid2.Data4[3] && + guid1.Data4[4] == guid2.Data4[4] && + guid1.Data4[5] == guid2.Data4[5] && + guid1.Data4[6] == guid2.Data4[6] && + guid1.Data4[7] == guid2.Data4[7] +} diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpoint.go b/vendor/github.com/go-ole/go-ole/iconnectionpoint.go new file mode 100644 index 000000000000..9e6c49f41f0a --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iconnectionpoint.go @@ -0,0 +1,20 @@ +package ole + +import "unsafe" + +type IConnectionPoint struct { + IUnknown +} + +type IConnectionPointVtbl struct { + IUnknownVtbl + GetConnectionInterface uintptr + GetConnectionPointContainer uintptr + Advise uintptr + Unadvise uintptr + EnumConnections uintptr +} + +func (v *IConnectionPoint) VTable() *IConnectionPointVtbl { + return (*IConnectionPointVtbl)(unsafe.Pointer(v.RawVTable)) +} diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpoint_func.go b/vendor/github.com/go-ole/go-ole/iconnectionpoint_func.go new file mode 100644 index 000000000000..5414dc3cd3bc --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iconnectionpoint_func.go @@ -0,0 +1,21 @@ +// +build !windows + +package ole + +import "unsafe" + +func (v *IConnectionPoint) GetConnectionInterface(piid **GUID) int32 { + return int32(0) +} + +func (v *IConnectionPoint) Advise(unknown *IUnknown) (uint32, error) { + return uint32(0), NewError(E_NOTIMPL) +} + +func (v *IConnectionPoint) Unadvise(cookie uint32) error { + return NewError(E_NOTIMPL) +} + +func (v *IConnectionPoint) EnumConnections(p *unsafe.Pointer) (err error) { + return NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpoint_windows.go b/vendor/github.com/go-ole/go-ole/iconnectionpoint_windows.go new file mode 100644 index 000000000000..32bc183248d9 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iconnectionpoint_windows.go @@ -0,0 +1,43 @@ +// +build windows + +package ole + +import ( + "syscall" + "unsafe" +) + +func (v *IConnectionPoint) GetConnectionInterface(piid **GUID) int32 { + // XXX: This doesn't look like it does what it's supposed to + return release((*IUnknown)(unsafe.Pointer(v))) +} + +func (v *IConnectionPoint) Advise(unknown *IUnknown) (cookie uint32, err error) { + hr, _, _ := syscall.Syscall( + v.VTable().Advise, + 3, + uintptr(unsafe.Pointer(v)), + uintptr(unsafe.Pointer(unknown)), + uintptr(unsafe.Pointer(&cookie))) + if hr != 0 { + err = NewError(hr) + } + return +} + +func (v *IConnectionPoint) Unadvise(cookie uint32) (err error) { + hr, _, _ := syscall.Syscall( + v.VTable().Unadvise, + 2, + uintptr(unsafe.Pointer(v)), + uintptr(cookie), + 0) + if hr != 0 { + err = NewError(hr) + } + return +} + +func (v *IConnectionPoint) EnumConnections(p *unsafe.Pointer) error { + return NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer.go b/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer.go new file mode 100644 index 000000000000..165860d199e8 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer.go @@ -0,0 +1,17 @@ +package ole + +import "unsafe" + +type IConnectionPointContainer struct { + IUnknown +} + +type IConnectionPointContainerVtbl struct { + IUnknownVtbl + EnumConnectionPoints uintptr + FindConnectionPoint uintptr +} + +func (v *IConnectionPointContainer) VTable() *IConnectionPointContainerVtbl { + return (*IConnectionPointContainerVtbl)(unsafe.Pointer(v.RawVTable)) +} diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_func.go b/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_func.go new file mode 100644 index 000000000000..5dfa42aaebb7 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_func.go @@ -0,0 +1,11 @@ +// +build !windows + +package ole + +func (v *IConnectionPointContainer) EnumConnectionPoints(points interface{}) error { + return NewError(E_NOTIMPL) +} + +func (v *IConnectionPointContainer) FindConnectionPoint(iid *GUID, point **IConnectionPoint) error { + return NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_windows.go b/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_windows.go new file mode 100644 index 000000000000..ad30d79efc4e --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_windows.go @@ -0,0 +1,25 @@ +// +build windows + +package ole + +import ( + "syscall" + "unsafe" +) + +func (v *IConnectionPointContainer) EnumConnectionPoints(points interface{}) error { + return NewError(E_NOTIMPL) +} + +func (v *IConnectionPointContainer) FindConnectionPoint(iid *GUID, point **IConnectionPoint) (err error) { + hr, _, _ := syscall.Syscall( + v.VTable().FindConnectionPoint, + 3, + uintptr(unsafe.Pointer(v)), + uintptr(unsafe.Pointer(iid)), + uintptr(unsafe.Pointer(point))) + if hr != 0 { + err = NewError(hr) + } + return +} diff --git a/vendor/github.com/go-ole/go-ole/idispatch.go b/vendor/github.com/go-ole/go-ole/idispatch.go new file mode 100644 index 000000000000..d4af1240925d --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/idispatch.go @@ -0,0 +1,94 @@ +package ole + +import "unsafe" + +type IDispatch struct { + IUnknown +} + +type IDispatchVtbl struct { + IUnknownVtbl + GetTypeInfoCount uintptr + GetTypeInfo uintptr + GetIDsOfNames uintptr + Invoke uintptr +} + +func (v *IDispatch) VTable() *IDispatchVtbl { + return (*IDispatchVtbl)(unsafe.Pointer(v.RawVTable)) +} + +func (v *IDispatch) GetIDsOfName(names []string) (dispid []int32, err error) { + dispid, err = getIDsOfName(v, names) + return +} + +func (v *IDispatch) Invoke(dispid int32, dispatch int16, params ...interface{}) (result *VARIANT, err error) { + result, err = invoke(v, dispid, dispatch, params...) + return +} + +func (v *IDispatch) GetTypeInfoCount() (c uint32, err error) { + c, err = getTypeInfoCount(v) + return +} + +func (v *IDispatch) GetTypeInfo() (tinfo *ITypeInfo, err error) { + tinfo, err = getTypeInfo(v) + return +} + +// GetSingleIDOfName is a helper that returns single display ID for IDispatch name. +// +// This replaces the common pattern of attempting to get a single name from the list of available +// IDs. It gives the first ID, if it is available. +func (v *IDispatch) GetSingleIDOfName(name string) (displayID int32, err error) { + var displayIDs []int32 + displayIDs, err = v.GetIDsOfName([]string{name}) + if err != nil { + return + } + displayID = displayIDs[0] + return +} + +// InvokeWithOptionalArgs accepts arguments as an array, works like Invoke. +// +// Accepts name and will attempt to retrieve Display ID to pass to Invoke. +// +// Passing params as an array is a workaround that could be fixed in later versions of Go that +// prevent passing empty params. During testing it was discovered that this is an acceptable way of +// getting around not being able to pass params normally. +func (v *IDispatch) InvokeWithOptionalArgs(name string, dispatch int16, params []interface{}) (result *VARIANT, err error) { + displayID, err := v.GetSingleIDOfName(name) + if err != nil { + return + } + + if len(params) < 1 { + result, err = v.Invoke(displayID, dispatch) + } else { + result, err = v.Invoke(displayID, dispatch, params...) + } + + return +} + +// CallMethod invokes named function with arguments on object. +func (v *IDispatch) CallMethod(name string, params ...interface{}) (*VARIANT, error) { + return v.InvokeWithOptionalArgs(name, DISPATCH_METHOD, params) +} + +// GetProperty retrieves the property with the name with the ability to pass arguments. +// +// Most of the time you will not need to pass arguments as most objects do not allow for this +// feature. Or at least, should not allow for this feature. Some servers don't follow best practices +// and this is provided for those edge cases. +func (v *IDispatch) GetProperty(name string, params ...interface{}) (*VARIANT, error) { + return v.InvokeWithOptionalArgs(name, DISPATCH_PROPERTYGET, params) +} + +// PutProperty attempts to mutate a property in the object. +func (v *IDispatch) PutProperty(name string, params ...interface{}) (*VARIANT, error) { + return v.InvokeWithOptionalArgs(name, DISPATCH_PROPERTYPUT, params) +} diff --git a/vendor/github.com/go-ole/go-ole/idispatch_func.go b/vendor/github.com/go-ole/go-ole/idispatch_func.go new file mode 100644 index 000000000000..b8fbbe319f1a --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/idispatch_func.go @@ -0,0 +1,19 @@ +// +build !windows + +package ole + +func getIDsOfName(disp *IDispatch, names []string) ([]int32, error) { + return []int32{}, NewError(E_NOTIMPL) +} + +func getTypeInfoCount(disp *IDispatch) (uint32, error) { + return uint32(0), NewError(E_NOTIMPL) +} + +func getTypeInfo(disp *IDispatch) (*ITypeInfo, error) { + return nil, NewError(E_NOTIMPL) +} + +func invoke(disp *IDispatch, dispid int32, dispatch int16, params ...interface{}) (*VARIANT, error) { + return nil, NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/idispatch_windows.go b/vendor/github.com/go-ole/go-ole/idispatch_windows.go new file mode 100644 index 000000000000..6ec180b55fd5 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/idispatch_windows.go @@ -0,0 +1,200 @@ +// +build windows + +package ole + +import ( + "math/big" + "syscall" + "time" + "unsafe" +) + +func getIDsOfName(disp *IDispatch, names []string) (dispid []int32, err error) { + wnames := make([]*uint16, len(names)) + for i := 0; i < len(names); i++ { + wnames[i] = syscall.StringToUTF16Ptr(names[i]) + } + dispid = make([]int32, len(names)) + namelen := uint32(len(names)) + hr, _, _ := syscall.Syscall6( + disp.VTable().GetIDsOfNames, + 6, + uintptr(unsafe.Pointer(disp)), + uintptr(unsafe.Pointer(IID_NULL)), + uintptr(unsafe.Pointer(&wnames[0])), + uintptr(namelen), + uintptr(GetUserDefaultLCID()), + uintptr(unsafe.Pointer(&dispid[0]))) + if hr != 0 { + err = NewError(hr) + } + return +} + +func getTypeInfoCount(disp *IDispatch) (c uint32, err error) { + hr, _, _ := syscall.Syscall( + disp.VTable().GetTypeInfoCount, + 2, + uintptr(unsafe.Pointer(disp)), + uintptr(unsafe.Pointer(&c)), + 0) + if hr != 0 { + err = NewError(hr) + } + return +} + +func getTypeInfo(disp *IDispatch) (tinfo *ITypeInfo, err error) { + hr, _, _ := syscall.Syscall( + disp.VTable().GetTypeInfo, + 3, + uintptr(unsafe.Pointer(disp)), + uintptr(GetUserDefaultLCID()), + uintptr(unsafe.Pointer(&tinfo))) + if hr != 0 { + err = NewError(hr) + } + return +} + +func invoke(disp *IDispatch, dispid int32, dispatch int16, params ...interface{}) (result *VARIANT, err error) { + var dispparams DISPPARAMS + + if dispatch&DISPATCH_PROPERTYPUT != 0 { + dispnames := [1]int32{DISPID_PROPERTYPUT} + dispparams.rgdispidNamedArgs = uintptr(unsafe.Pointer(&dispnames[0])) + dispparams.cNamedArgs = 1 + } else if dispatch&DISPATCH_PROPERTYPUTREF != 0 { + dispnames := [1]int32{DISPID_PROPERTYPUT} + dispparams.rgdispidNamedArgs = uintptr(unsafe.Pointer(&dispnames[0])) + dispparams.cNamedArgs = 1 + } + var vargs []VARIANT + if len(params) > 0 { + vargs = make([]VARIANT, len(params)) + for i, v := range params { + //n := len(params)-i-1 + n := len(params) - i - 1 + VariantInit(&vargs[n]) + switch vv := v.(type) { + case bool: + if vv { + vargs[n] = NewVariant(VT_BOOL, 0xffff) + } else { + vargs[n] = NewVariant(VT_BOOL, 0) + } + case *bool: + vargs[n] = NewVariant(VT_BOOL|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*bool))))) + case uint8: + vargs[n] = NewVariant(VT_I1, int64(v.(uint8))) + case *uint8: + vargs[n] = NewVariant(VT_I1|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint8))))) + case int8: + vargs[n] = NewVariant(VT_I1, int64(v.(int8))) + case *int8: + vargs[n] = NewVariant(VT_I1|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint8))))) + case int16: + vargs[n] = NewVariant(VT_I2, int64(v.(int16))) + case *int16: + vargs[n] = NewVariant(VT_I2|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int16))))) + case uint16: + vargs[n] = NewVariant(VT_UI2, int64(v.(uint16))) + case *uint16: + vargs[n] = NewVariant(VT_UI2|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint16))))) + case int32: + vargs[n] = NewVariant(VT_I4, int64(v.(int32))) + case *int32: + vargs[n] = NewVariant(VT_I4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int32))))) + case uint32: + vargs[n] = NewVariant(VT_UI4, int64(v.(uint32))) + case *uint32: + vargs[n] = NewVariant(VT_UI4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint32))))) + case int64: + vargs[n] = NewVariant(VT_I8, int64(v.(int64))) + case *int64: + vargs[n] = NewVariant(VT_I8|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int64))))) + case uint64: + vargs[n] = NewVariant(VT_UI8, int64(uintptr(v.(uint64)))) + case *uint64: + vargs[n] = NewVariant(VT_UI8|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint64))))) + case int: + vargs[n] = NewVariant(VT_I4, int64(v.(int))) + case *int: + vargs[n] = NewVariant(VT_I4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int))))) + case uint: + vargs[n] = NewVariant(VT_UI4, int64(v.(uint))) + case *uint: + vargs[n] = NewVariant(VT_UI4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint))))) + case float32: + vargs[n] = NewVariant(VT_R4, *(*int64)(unsafe.Pointer(&vv))) + case *float32: + vargs[n] = NewVariant(VT_R4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*float32))))) + case float64: + vargs[n] = NewVariant(VT_R8, *(*int64)(unsafe.Pointer(&vv))) + case *float64: + vargs[n] = NewVariant(VT_R8|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*float64))))) + case *big.Int: + vargs[n] = NewVariant(VT_DECIMAL, v.(*big.Int).Int64()) + case string: + vargs[n] = NewVariant(VT_BSTR, int64(uintptr(unsafe.Pointer(SysAllocStringLen(v.(string)))))) + case *string: + vargs[n] = NewVariant(VT_BSTR|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*string))))) + case time.Time: + s := vv.Format("2006-01-02 15:04:05") + vargs[n] = NewVariant(VT_BSTR, int64(uintptr(unsafe.Pointer(SysAllocStringLen(s))))) + case *time.Time: + s := vv.Format("2006-01-02 15:04:05") + vargs[n] = NewVariant(VT_BSTR|VT_BYREF, int64(uintptr(unsafe.Pointer(&s)))) + case *IDispatch: + vargs[n] = NewVariant(VT_DISPATCH, int64(uintptr(unsafe.Pointer(v.(*IDispatch))))) + case **IDispatch: + vargs[n] = NewVariant(VT_DISPATCH|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(**IDispatch))))) + case nil: + vargs[n] = NewVariant(VT_NULL, 0) + case *VARIANT: + vargs[n] = NewVariant(VT_VARIANT|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*VARIANT))))) + case []byte: + safeByteArray := safeArrayFromByteSlice(v.([]byte)) + vargs[n] = NewVariant(VT_ARRAY|VT_UI1, int64(uintptr(unsafe.Pointer(safeByteArray)))) + defer VariantClear(&vargs[n]) + case []string: + safeByteArray := safeArrayFromStringSlice(v.([]string)) + vargs[n] = NewVariant(VT_ARRAY|VT_BSTR, int64(uintptr(unsafe.Pointer(safeByteArray)))) + defer VariantClear(&vargs[n]) + default: + panic("unknown type") + } + } + dispparams.rgvarg = uintptr(unsafe.Pointer(&vargs[0])) + dispparams.cArgs = uint32(len(params)) + } + + result = new(VARIANT) + var excepInfo EXCEPINFO + VariantInit(result) + hr, _, _ := syscall.Syscall9( + disp.VTable().Invoke, + 9, + uintptr(unsafe.Pointer(disp)), + uintptr(dispid), + uintptr(unsafe.Pointer(IID_NULL)), + uintptr(GetUserDefaultLCID()), + uintptr(dispatch), + uintptr(unsafe.Pointer(&dispparams)), + uintptr(unsafe.Pointer(result)), + uintptr(unsafe.Pointer(&excepInfo)), + 0) + if hr != 0 { + err = NewErrorWithSubError(hr, BstrToString(excepInfo.bstrDescription), excepInfo) + } + for i, varg := range vargs { + n := len(params) - i - 1 + if varg.VT == VT_BSTR && varg.Val != 0 { + SysFreeString(((*int16)(unsafe.Pointer(uintptr(varg.Val))))) + } + if varg.VT == (VT_BSTR|VT_BYREF) && varg.Val != 0 { + *(params[n].(*string)) = LpOleStrToString(*(**uint16)(unsafe.Pointer(uintptr(varg.Val)))) + } + } + return +} diff --git a/vendor/github.com/go-ole/go-ole/ienumvariant.go b/vendor/github.com/go-ole/go-ole/ienumvariant.go new file mode 100644 index 000000000000..243389754430 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/ienumvariant.go @@ -0,0 +1,19 @@ +package ole + +import "unsafe" + +type IEnumVARIANT struct { + IUnknown +} + +type IEnumVARIANTVtbl struct { + IUnknownVtbl + Next uintptr + Skip uintptr + Reset uintptr + Clone uintptr +} + +func (v *IEnumVARIANT) VTable() *IEnumVARIANTVtbl { + return (*IEnumVARIANTVtbl)(unsafe.Pointer(v.RawVTable)) +} diff --git a/vendor/github.com/go-ole/go-ole/ienumvariant_func.go b/vendor/github.com/go-ole/go-ole/ienumvariant_func.go new file mode 100644 index 000000000000..c14848199cb8 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/ienumvariant_func.go @@ -0,0 +1,19 @@ +// +build !windows + +package ole + +func (enum *IEnumVARIANT) Clone() (*IEnumVARIANT, error) { + return nil, NewError(E_NOTIMPL) +} + +func (enum *IEnumVARIANT) Reset() error { + return NewError(E_NOTIMPL) +} + +func (enum *IEnumVARIANT) Skip(celt uint) error { + return NewError(E_NOTIMPL) +} + +func (enum *IEnumVARIANT) Next(celt uint) (VARIANT, uint, error) { + return NewVariant(VT_NULL, int64(0)), 0, NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/ienumvariant_windows.go b/vendor/github.com/go-ole/go-ole/ienumvariant_windows.go new file mode 100644 index 000000000000..4781f3b8b007 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/ienumvariant_windows.go @@ -0,0 +1,63 @@ +// +build windows + +package ole + +import ( + "syscall" + "unsafe" +) + +func (enum *IEnumVARIANT) Clone() (cloned *IEnumVARIANT, err error) { + hr, _, _ := syscall.Syscall( + enum.VTable().Clone, + 2, + uintptr(unsafe.Pointer(enum)), + uintptr(unsafe.Pointer(&cloned)), + 0) + if hr != 0 { + err = NewError(hr) + } + return +} + +func (enum *IEnumVARIANT) Reset() (err error) { + hr, _, _ := syscall.Syscall( + enum.VTable().Reset, + 1, + uintptr(unsafe.Pointer(enum)), + 0, + 0) + if hr != 0 { + err = NewError(hr) + } + return +} + +func (enum *IEnumVARIANT) Skip(celt uint) (err error) { + hr, _, _ := syscall.Syscall( + enum.VTable().Skip, + 2, + uintptr(unsafe.Pointer(enum)), + uintptr(celt), + 0) + if hr != 0 { + err = NewError(hr) + } + return +} + +func (enum *IEnumVARIANT) Next(celt uint) (array VARIANT, length uint, err error) { + hr, _, _ := syscall.Syscall6( + enum.VTable().Next, + 4, + uintptr(unsafe.Pointer(enum)), + uintptr(celt), + uintptr(unsafe.Pointer(&array)), + uintptr(unsafe.Pointer(&length)), + 0, + 0) + if hr != 0 { + err = NewError(hr) + } + return +} diff --git a/vendor/github.com/go-ole/go-ole/iinspectable.go b/vendor/github.com/go-ole/go-ole/iinspectable.go new file mode 100644 index 000000000000..f4a19e253af7 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iinspectable.go @@ -0,0 +1,18 @@ +package ole + +import "unsafe" + +type IInspectable struct { + IUnknown +} + +type IInspectableVtbl struct { + IUnknownVtbl + GetIIds uintptr + GetRuntimeClassName uintptr + GetTrustLevel uintptr +} + +func (v *IInspectable) VTable() *IInspectableVtbl { + return (*IInspectableVtbl)(unsafe.Pointer(v.RawVTable)) +} diff --git a/vendor/github.com/go-ole/go-ole/iinspectable_func.go b/vendor/github.com/go-ole/go-ole/iinspectable_func.go new file mode 100644 index 000000000000..348829bf062f --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iinspectable_func.go @@ -0,0 +1,15 @@ +// +build !windows + +package ole + +func (v *IInspectable) GetIids() ([]*GUID, error) { + return []*GUID{}, NewError(E_NOTIMPL) +} + +func (v *IInspectable) GetRuntimeClassName() (string, error) { + return "", NewError(E_NOTIMPL) +} + +func (v *IInspectable) GetTrustLevel() (uint32, error) { + return uint32(0), NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/iinspectable_windows.go b/vendor/github.com/go-ole/go-ole/iinspectable_windows.go new file mode 100644 index 000000000000..4519a4aa4495 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iinspectable_windows.go @@ -0,0 +1,72 @@ +// +build windows + +package ole + +import ( + "bytes" + "encoding/binary" + "reflect" + "syscall" + "unsafe" +) + +func (v *IInspectable) GetIids() (iids []*GUID, err error) { + var count uint32 + var array uintptr + hr, _, _ := syscall.Syscall( + v.VTable().GetIIds, + 3, + uintptr(unsafe.Pointer(v)), + uintptr(unsafe.Pointer(&count)), + uintptr(unsafe.Pointer(&array))) + if hr != 0 { + err = NewError(hr) + return + } + defer CoTaskMemFree(array) + + iids = make([]*GUID, count) + byteCount := count * uint32(unsafe.Sizeof(GUID{})) + slicehdr := reflect.SliceHeader{Data: array, Len: int(byteCount), Cap: int(byteCount)} + byteSlice := *(*[]byte)(unsafe.Pointer(&slicehdr)) + reader := bytes.NewReader(byteSlice) + for i := range iids { + guid := GUID{} + err = binary.Read(reader, binary.LittleEndian, &guid) + if err != nil { + return + } + iids[i] = &guid + } + return +} + +func (v *IInspectable) GetRuntimeClassName() (s string, err error) { + var hstring HString + hr, _, _ := syscall.Syscall( + v.VTable().GetRuntimeClassName, + 2, + uintptr(unsafe.Pointer(v)), + uintptr(unsafe.Pointer(&hstring)), + 0) + if hr != 0 { + err = NewError(hr) + return + } + s = hstring.String() + DeleteHString(hstring) + return +} + +func (v *IInspectable) GetTrustLevel() (level uint32, err error) { + hr, _, _ := syscall.Syscall( + v.VTable().GetTrustLevel, + 2, + uintptr(unsafe.Pointer(v)), + uintptr(unsafe.Pointer(&level)), + 0) + if hr != 0 { + err = NewError(hr) + } + return +} diff --git a/vendor/github.com/go-ole/go-ole/iprovideclassinfo.go b/vendor/github.com/go-ole/go-ole/iprovideclassinfo.go new file mode 100644 index 000000000000..25f3a6f24a91 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iprovideclassinfo.go @@ -0,0 +1,21 @@ +package ole + +import "unsafe" + +type IProvideClassInfo struct { + IUnknown +} + +type IProvideClassInfoVtbl struct { + IUnknownVtbl + GetClassInfo uintptr +} + +func (v *IProvideClassInfo) VTable() *IProvideClassInfoVtbl { + return (*IProvideClassInfoVtbl)(unsafe.Pointer(v.RawVTable)) +} + +func (v *IProvideClassInfo) GetClassInfo() (cinfo *ITypeInfo, err error) { + cinfo, err = getClassInfo(v) + return +} diff --git a/vendor/github.com/go-ole/go-ole/iprovideclassinfo_func.go b/vendor/github.com/go-ole/go-ole/iprovideclassinfo_func.go new file mode 100644 index 000000000000..7e3cb63ea739 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iprovideclassinfo_func.go @@ -0,0 +1,7 @@ +// +build !windows + +package ole + +func getClassInfo(disp *IProvideClassInfo) (tinfo *ITypeInfo, err error) { + return nil, NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/iprovideclassinfo_windows.go b/vendor/github.com/go-ole/go-ole/iprovideclassinfo_windows.go new file mode 100644 index 000000000000..2ad016394974 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iprovideclassinfo_windows.go @@ -0,0 +1,21 @@ +// +build windows + +package ole + +import ( + "syscall" + "unsafe" +) + +func getClassInfo(disp *IProvideClassInfo) (tinfo *ITypeInfo, err error) { + hr, _, _ := syscall.Syscall( + disp.VTable().GetClassInfo, + 2, + uintptr(unsafe.Pointer(disp)), + uintptr(unsafe.Pointer(&tinfo)), + 0) + if hr != 0 { + err = NewError(hr) + } + return +} diff --git a/vendor/github.com/go-ole/go-ole/itypeinfo.go b/vendor/github.com/go-ole/go-ole/itypeinfo.go new file mode 100644 index 000000000000..dd3c5e21bbf3 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/itypeinfo.go @@ -0,0 +1,34 @@ +package ole + +import "unsafe" + +type ITypeInfo struct { + IUnknown +} + +type ITypeInfoVtbl struct { + IUnknownVtbl + GetTypeAttr uintptr + GetTypeComp uintptr + GetFuncDesc uintptr + GetVarDesc uintptr + GetNames uintptr + GetRefTypeOfImplType uintptr + GetImplTypeFlags uintptr + GetIDsOfNames uintptr + Invoke uintptr + GetDocumentation uintptr + GetDllEntry uintptr + GetRefTypeInfo uintptr + AddressOfMember uintptr + CreateInstance uintptr + GetMops uintptr + GetContainingTypeLib uintptr + ReleaseTypeAttr uintptr + ReleaseFuncDesc uintptr + ReleaseVarDesc uintptr +} + +func (v *ITypeInfo) VTable() *ITypeInfoVtbl { + return (*ITypeInfoVtbl)(unsafe.Pointer(v.RawVTable)) +} diff --git a/vendor/github.com/go-ole/go-ole/itypeinfo_func.go b/vendor/github.com/go-ole/go-ole/itypeinfo_func.go new file mode 100644 index 000000000000..8364a659bae1 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/itypeinfo_func.go @@ -0,0 +1,7 @@ +// +build !windows + +package ole + +func (v *ITypeInfo) GetTypeAttr() (*TYPEATTR, error) { + return nil, NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/itypeinfo_windows.go b/vendor/github.com/go-ole/go-ole/itypeinfo_windows.go new file mode 100644 index 000000000000..54782b3da5dd --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/itypeinfo_windows.go @@ -0,0 +1,21 @@ +// +build windows + +package ole + +import ( + "syscall" + "unsafe" +) + +func (v *ITypeInfo) GetTypeAttr() (tattr *TYPEATTR, err error) { + hr, _, _ := syscall.Syscall( + uintptr(v.VTable().GetTypeAttr), + 2, + uintptr(unsafe.Pointer(v)), + uintptr(unsafe.Pointer(&tattr)), + 0) + if hr != 0 { + err = NewError(hr) + } + return +} diff --git a/vendor/github.com/go-ole/go-ole/iunknown.go b/vendor/github.com/go-ole/go-ole/iunknown.go new file mode 100644 index 000000000000..108f28ea6108 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iunknown.go @@ -0,0 +1,57 @@ +package ole + +import "unsafe" + +type IUnknown struct { + RawVTable *interface{} +} + +type IUnknownVtbl struct { + QueryInterface uintptr + AddRef uintptr + Release uintptr +} + +type UnknownLike interface { + QueryInterface(iid *GUID) (disp *IDispatch, err error) + AddRef() int32 + Release() int32 +} + +func (v *IUnknown) VTable() *IUnknownVtbl { + return (*IUnknownVtbl)(unsafe.Pointer(v.RawVTable)) +} + +func (v *IUnknown) PutQueryInterface(interfaceID *GUID, obj interface{}) error { + return reflectQueryInterface(v, v.VTable().QueryInterface, interfaceID, obj) +} + +func (v *IUnknown) IDispatch(interfaceID *GUID) (dispatch *IDispatch, err error) { + err = v.PutQueryInterface(interfaceID, &dispatch) + return +} + +func (v *IUnknown) IEnumVARIANT(interfaceID *GUID) (enum *IEnumVARIANT, err error) { + err = v.PutQueryInterface(interfaceID, &enum) + return +} + +func (v *IUnknown) QueryInterface(iid *GUID) (*IDispatch, error) { + return queryInterface(v, iid) +} + +func (v *IUnknown) MustQueryInterface(iid *GUID) (disp *IDispatch) { + unk, err := queryInterface(v, iid) + if err != nil { + panic(err) + } + return unk +} + +func (v *IUnknown) AddRef() int32 { + return addRef(v) +} + +func (v *IUnknown) Release() int32 { + return release(v) +} diff --git a/vendor/github.com/go-ole/go-ole/iunknown_func.go b/vendor/github.com/go-ole/go-ole/iunknown_func.go new file mode 100644 index 000000000000..d0a62cfd7302 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iunknown_func.go @@ -0,0 +1,19 @@ +// +build !windows + +package ole + +func reflectQueryInterface(self interface{}, method uintptr, interfaceID *GUID, obj interface{}) (err error) { + return NewError(E_NOTIMPL) +} + +func queryInterface(unk *IUnknown, iid *GUID) (disp *IDispatch, err error) { + return nil, NewError(E_NOTIMPL) +} + +func addRef(unk *IUnknown) int32 { + return 0 +} + +func release(unk *IUnknown) int32 { + return 0 +} diff --git a/vendor/github.com/go-ole/go-ole/iunknown_windows.go b/vendor/github.com/go-ole/go-ole/iunknown_windows.go new file mode 100644 index 000000000000..ede5bb8c1732 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iunknown_windows.go @@ -0,0 +1,58 @@ +// +build windows + +package ole + +import ( + "reflect" + "syscall" + "unsafe" +) + +func reflectQueryInterface(self interface{}, method uintptr, interfaceID *GUID, obj interface{}) (err error) { + selfValue := reflect.ValueOf(self).Elem() + objValue := reflect.ValueOf(obj).Elem() + + hr, _, _ := syscall.Syscall( + method, + 3, + selfValue.UnsafeAddr(), + uintptr(unsafe.Pointer(interfaceID)), + objValue.Addr().Pointer()) + if hr != 0 { + err = NewError(hr) + } + return +} + +func queryInterface(unk *IUnknown, iid *GUID) (disp *IDispatch, err error) { + hr, _, _ := syscall.Syscall( + unk.VTable().QueryInterface, + 3, + uintptr(unsafe.Pointer(unk)), + uintptr(unsafe.Pointer(iid)), + uintptr(unsafe.Pointer(&disp))) + if hr != 0 { + err = NewError(hr) + } + return +} + +func addRef(unk *IUnknown) int32 { + ret, _, _ := syscall.Syscall( + unk.VTable().AddRef, + 1, + uintptr(unsafe.Pointer(unk)), + 0, + 0) + return int32(ret) +} + +func release(unk *IUnknown) int32 { + ret, _, _ := syscall.Syscall( + unk.VTable().Release, + 1, + uintptr(unsafe.Pointer(unk)), + 0, + 0) + return int32(ret) +} diff --git a/vendor/github.com/go-ole/go-ole/ole.go b/vendor/github.com/go-ole/go-ole/ole.go new file mode 100644 index 000000000000..e2ae4f4bbfeb --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/ole.go @@ -0,0 +1,157 @@ +package ole + +import ( + "fmt" + "strings" +) + +// DISPPARAMS are the arguments that passed to methods or property. +type DISPPARAMS struct { + rgvarg uintptr + rgdispidNamedArgs uintptr + cArgs uint32 + cNamedArgs uint32 +} + +// EXCEPINFO defines exception info. +type EXCEPINFO struct { + wCode uint16 + wReserved uint16 + bstrSource *uint16 + bstrDescription *uint16 + bstrHelpFile *uint16 + dwHelpContext uint32 + pvReserved uintptr + pfnDeferredFillIn uintptr + scode uint32 +} + +// WCode return wCode in EXCEPINFO. +func (e EXCEPINFO) WCode() uint16 { + return e.wCode +} + +// SCODE return scode in EXCEPINFO. +func (e EXCEPINFO) SCODE() uint32 { + return e.scode +} + +// String convert EXCEPINFO to string. +func (e EXCEPINFO) String() string { + var src, desc, hlp string + if e.bstrSource == nil { + src = "" + } else { + src = BstrToString(e.bstrSource) + } + + if e.bstrDescription == nil { + desc = "" + } else { + desc = BstrToString(e.bstrDescription) + } + + if e.bstrHelpFile == nil { + hlp = "" + } else { + hlp = BstrToString(e.bstrHelpFile) + } + + return fmt.Sprintf( + "wCode: %#x, bstrSource: %v, bstrDescription: %v, bstrHelpFile: %v, dwHelpContext: %#x, scode: %#x", + e.wCode, src, desc, hlp, e.dwHelpContext, e.scode, + ) +} + +// Error implements error interface and returns error string. +func (e EXCEPINFO) Error() string { + if e.bstrDescription != nil { + return strings.TrimSpace(BstrToString(e.bstrDescription)) + } + + src := "Unknown" + if e.bstrSource != nil { + src = BstrToString(e.bstrSource) + } + + code := e.scode + if e.wCode != 0 { + code = uint32(e.wCode) + } + + return fmt.Sprintf("%v: %#x", src, code) +} + +// PARAMDATA defines parameter data type. +type PARAMDATA struct { + Name *int16 + Vt uint16 +} + +// METHODDATA defines method info. +type METHODDATA struct { + Name *uint16 + Data *PARAMDATA + Dispid int32 + Meth uint32 + CC int32 + CArgs uint32 + Flags uint16 + VtReturn uint32 +} + +// INTERFACEDATA defines interface info. +type INTERFACEDATA struct { + MethodData *METHODDATA + CMembers uint32 +} + +// Point is 2D vector type. +type Point struct { + X int32 + Y int32 +} + +// Msg is message between processes. +type Msg struct { + Hwnd uint32 + Message uint32 + Wparam int32 + Lparam int32 + Time uint32 + Pt Point +} + +// TYPEDESC defines data type. +type TYPEDESC struct { + Hreftype uint32 + VT uint16 +} + +// IDLDESC defines IDL info. +type IDLDESC struct { + DwReserved uint32 + WIDLFlags uint16 +} + +// TYPEATTR defines type info. +type TYPEATTR struct { + Guid GUID + Lcid uint32 + dwReserved uint32 + MemidConstructor int32 + MemidDestructor int32 + LpstrSchema *uint16 + CbSizeInstance uint32 + Typekind int32 + CFuncs uint16 + CVars uint16 + CImplTypes uint16 + CbSizeVft uint16 + CbAlignment uint16 + WTypeFlags uint16 + WMajorVerNum uint16 + WMinorVerNum uint16 + TdescAlias TYPEDESC + IdldescType IDLDESC +} diff --git a/vendor/github.com/go-ole/go-ole/oleutil/connection.go b/vendor/github.com/go-ole/go-ole/oleutil/connection.go new file mode 100644 index 000000000000..60df73cda001 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/oleutil/connection.go @@ -0,0 +1,100 @@ +// +build windows + +package oleutil + +import ( + "reflect" + "unsafe" + + ole "github.com/go-ole/go-ole" +) + +type stdDispatch struct { + lpVtbl *stdDispatchVtbl + ref int32 + iid *ole.GUID + iface interface{} + funcMap map[string]int32 +} + +type stdDispatchVtbl struct { + pQueryInterface uintptr + pAddRef uintptr + pRelease uintptr + pGetTypeInfoCount uintptr + pGetTypeInfo uintptr + pGetIDsOfNames uintptr + pInvoke uintptr +} + +func dispQueryInterface(this *ole.IUnknown, iid *ole.GUID, punk **ole.IUnknown) uint32 { + pthis := (*stdDispatch)(unsafe.Pointer(this)) + *punk = nil + if ole.IsEqualGUID(iid, ole.IID_IUnknown) || + ole.IsEqualGUID(iid, ole.IID_IDispatch) { + dispAddRef(this) + *punk = this + return ole.S_OK + } + if ole.IsEqualGUID(iid, pthis.iid) { + dispAddRef(this) + *punk = this + return ole.S_OK + } + return ole.E_NOINTERFACE +} + +func dispAddRef(this *ole.IUnknown) int32 { + pthis := (*stdDispatch)(unsafe.Pointer(this)) + pthis.ref++ + return pthis.ref +} + +func dispRelease(this *ole.IUnknown) int32 { + pthis := (*stdDispatch)(unsafe.Pointer(this)) + pthis.ref-- + return pthis.ref +} + +func dispGetIDsOfNames(this *ole.IUnknown, iid *ole.GUID, wnames []*uint16, namelen int, lcid int, pdisp []int32) uintptr { + pthis := (*stdDispatch)(unsafe.Pointer(this)) + names := make([]string, len(wnames)) + for i := 0; i < len(names); i++ { + names[i] = ole.LpOleStrToString(wnames[i]) + } + for n := 0; n < namelen; n++ { + if id, ok := pthis.funcMap[names[n]]; ok { + pdisp[n] = id + } + } + return ole.S_OK +} + +func dispGetTypeInfoCount(pcount *int) uintptr { + if pcount != nil { + *pcount = 0 + } + return ole.S_OK +} + +func dispGetTypeInfo(ptypeif *uintptr) uintptr { + return ole.E_NOTIMPL +} + +func dispInvoke(this *ole.IDispatch, dispid int32, riid *ole.GUID, lcid int, flags int16, dispparams *ole.DISPPARAMS, result *ole.VARIANT, pexcepinfo *ole.EXCEPINFO, nerr *uint) uintptr { + pthis := (*stdDispatch)(unsafe.Pointer(this)) + found := "" + for name, id := range pthis.funcMap { + if id == dispid { + found = name + } + } + if found != "" { + rv := reflect.ValueOf(pthis.iface).Elem() + rm := rv.MethodByName(found) + rr := rm.Call([]reflect.Value{}) + println(len(rr)) + return ole.S_OK + } + return ole.E_NOTIMPL +} diff --git a/vendor/github.com/go-ole/go-ole/oleutil/connection_func.go b/vendor/github.com/go-ole/go-ole/oleutil/connection_func.go new file mode 100644 index 000000000000..8818fb8275ad --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/oleutil/connection_func.go @@ -0,0 +1,10 @@ +// +build !windows + +package oleutil + +import ole "github.com/go-ole/go-ole" + +// ConnectObject creates a connection point between two services for communication. +func ConnectObject(disp *ole.IDispatch, iid *ole.GUID, idisp interface{}) (uint32, error) { + return 0, ole.NewError(ole.E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/oleutil/connection_windows.go b/vendor/github.com/go-ole/go-ole/oleutil/connection_windows.go new file mode 100644 index 000000000000..ab9c0d8dcbd4 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/oleutil/connection_windows.go @@ -0,0 +1,58 @@ +// +build windows + +package oleutil + +import ( + "reflect" + "syscall" + "unsafe" + + ole "github.com/go-ole/go-ole" +) + +// ConnectObject creates a connection point between two services for communication. +func ConnectObject(disp *ole.IDispatch, iid *ole.GUID, idisp interface{}) (cookie uint32, err error) { + unknown, err := disp.QueryInterface(ole.IID_IConnectionPointContainer) + if err != nil { + return + } + + container := (*ole.IConnectionPointContainer)(unsafe.Pointer(unknown)) + var point *ole.IConnectionPoint + err = container.FindConnectionPoint(iid, &point) + if err != nil { + return + } + if edisp, ok := idisp.(*ole.IUnknown); ok { + cookie, err = point.Advise(edisp) + container.Release() + if err != nil { + return + } + } + rv := reflect.ValueOf(disp).Elem() + if rv.Type().Kind() == reflect.Struct { + dest := &stdDispatch{} + dest.lpVtbl = &stdDispatchVtbl{} + dest.lpVtbl.pQueryInterface = syscall.NewCallback(dispQueryInterface) + dest.lpVtbl.pAddRef = syscall.NewCallback(dispAddRef) + dest.lpVtbl.pRelease = syscall.NewCallback(dispRelease) + dest.lpVtbl.pGetTypeInfoCount = syscall.NewCallback(dispGetTypeInfoCount) + dest.lpVtbl.pGetTypeInfo = syscall.NewCallback(dispGetTypeInfo) + dest.lpVtbl.pGetIDsOfNames = syscall.NewCallback(dispGetIDsOfNames) + dest.lpVtbl.pInvoke = syscall.NewCallback(dispInvoke) + dest.iface = disp + dest.iid = iid + cookie, err = point.Advise((*ole.IUnknown)(unsafe.Pointer(dest))) + container.Release() + if err != nil { + point.Release() + return + } + return + } + + container.Release() + + return 0, ole.NewError(ole.E_INVALIDARG) +} diff --git a/vendor/github.com/go-ole/go-ole/oleutil/go-get.go b/vendor/github.com/go-ole/go-ole/oleutil/go-get.go new file mode 100644 index 000000000000..58347628f24c --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/oleutil/go-get.go @@ -0,0 +1,6 @@ +// This file is here so go get succeeds as without it errors with: +// no buildable Go source files in ... +// +// +build !windows + +package oleutil diff --git a/vendor/github.com/go-ole/go-ole/oleutil/oleutil.go b/vendor/github.com/go-ole/go-ole/oleutil/oleutil.go new file mode 100644 index 000000000000..f7803c1e30f2 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/oleutil/oleutil.go @@ -0,0 +1,127 @@ +package oleutil + +import ole "github.com/go-ole/go-ole" + +// ClassIDFrom retrieves class ID whether given is program ID or application string. +func ClassIDFrom(programID string) (classID *ole.GUID, err error) { + return ole.ClassIDFrom(programID) +} + +// CreateObject creates object from programID based on interface type. +// +// Only supports IUnknown. +// +// Program ID can be either program ID or application string. +func CreateObject(programID string) (unknown *ole.IUnknown, err error) { + classID, err := ole.ClassIDFrom(programID) + if err != nil { + return + } + + unknown, err = ole.CreateInstance(classID, ole.IID_IUnknown) + if err != nil { + return + } + + return +} + +// GetActiveObject retrieves active object for program ID and interface ID based +// on interface type. +// +// Only supports IUnknown. +// +// Program ID can be either program ID or application string. +func GetActiveObject(programID string) (unknown *ole.IUnknown, err error) { + classID, err := ole.ClassIDFrom(programID) + if err != nil { + return + } + + unknown, err = ole.GetActiveObject(classID, ole.IID_IUnknown) + if err != nil { + return + } + + return +} + +// CallMethod calls method on IDispatch with parameters. +func CallMethod(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT, err error) { + return disp.InvokeWithOptionalArgs(name, ole.DISPATCH_METHOD, params) +} + +// MustCallMethod calls method on IDispatch with parameters or panics. +func MustCallMethod(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT) { + r, err := CallMethod(disp, name, params...) + if err != nil { + panic(err.Error()) + } + return r +} + +// GetProperty retrieves property from IDispatch. +func GetProperty(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT, err error) { + return disp.InvokeWithOptionalArgs(name, ole.DISPATCH_PROPERTYGET, params) +} + +// MustGetProperty retrieves property from IDispatch or panics. +func MustGetProperty(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT) { + r, err := GetProperty(disp, name, params...) + if err != nil { + panic(err.Error()) + } + return r +} + +// PutProperty mutates property. +func PutProperty(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT, err error) { + return disp.InvokeWithOptionalArgs(name, ole.DISPATCH_PROPERTYPUT, params) +} + +// MustPutProperty mutates property or panics. +func MustPutProperty(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT) { + r, err := PutProperty(disp, name, params...) + if err != nil { + panic(err.Error()) + } + return r +} + +// PutPropertyRef mutates property reference. +func PutPropertyRef(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT, err error) { + return disp.InvokeWithOptionalArgs(name, ole.DISPATCH_PROPERTYPUTREF, params) +} + +// MustPutPropertyRef mutates property reference or panics. +func MustPutPropertyRef(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT) { + r, err := PutPropertyRef(disp, name, params...) + if err != nil { + panic(err.Error()) + } + return r +} + +func ForEach(disp *ole.IDispatch, f func(v *ole.VARIANT) error) error { + newEnum, err := disp.GetProperty("_NewEnum") + if err != nil { + return err + } + defer newEnum.Clear() + + enum, err := newEnum.ToIUnknown().IEnumVARIANT(ole.IID_IEnumVariant) + if err != nil { + return err + } + defer enum.Release() + + for item, length, err := enum.Next(1); length > 0; item, length, err = enum.Next(1) { + if err != nil { + return err + } + if ferr := f(&item); ferr != nil { + return ferr + } + } + return nil +} diff --git a/vendor/github.com/go-ole/go-ole/safearray.go b/vendor/github.com/go-ole/go-ole/safearray.go new file mode 100644 index 000000000000..a5201b56c3d9 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/safearray.go @@ -0,0 +1,27 @@ +// Package is meant to retrieve and process safe array data returned from COM. + +package ole + +// SafeArrayBound defines the SafeArray boundaries. +type SafeArrayBound struct { + Elements uint32 + LowerBound int32 +} + +// SafeArray is how COM handles arrays. +type SafeArray struct { + Dimensions uint16 + FeaturesFlag uint16 + ElementsSize uint32 + LocksAmount uint32 + Data uint32 + Bounds [16]byte +} + +// SAFEARRAY is obsolete, exists for backwards compatibility. +// Use SafeArray +type SAFEARRAY SafeArray + +// SAFEARRAYBOUND is obsolete, exists for backwards compatibility. +// Use SafeArrayBound +type SAFEARRAYBOUND SafeArrayBound diff --git a/vendor/github.com/go-ole/go-ole/safearray_func.go b/vendor/github.com/go-ole/go-ole/safearray_func.go new file mode 100644 index 000000000000..0dee670ceb6d --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/safearray_func.go @@ -0,0 +1,211 @@ +// +build !windows + +package ole + +import ( + "unsafe" +) + +// safeArrayAccessData returns raw array pointer. +// +// AKA: SafeArrayAccessData in Windows API. +func safeArrayAccessData(safearray *SafeArray) (uintptr, error) { + return uintptr(0), NewError(E_NOTIMPL) +} + +// safeArrayUnaccessData releases raw array. +// +// AKA: SafeArrayUnaccessData in Windows API. +func safeArrayUnaccessData(safearray *SafeArray) error { + return NewError(E_NOTIMPL) +} + +// safeArrayAllocData allocates SafeArray. +// +// AKA: SafeArrayAllocData in Windows API. +func safeArrayAllocData(safearray *SafeArray) error { + return NewError(E_NOTIMPL) +} + +// safeArrayAllocDescriptor allocates SafeArray. +// +// AKA: SafeArrayAllocDescriptor in Windows API. +func safeArrayAllocDescriptor(dimensions uint32) (*SafeArray, error) { + return nil, NewError(E_NOTIMPL) +} + +// safeArrayAllocDescriptorEx allocates SafeArray. +// +// AKA: SafeArrayAllocDescriptorEx in Windows API. +func safeArrayAllocDescriptorEx(variantType VT, dimensions uint32) (*SafeArray, error) { + return nil, NewError(E_NOTIMPL) +} + +// safeArrayCopy returns copy of SafeArray. +// +// AKA: SafeArrayCopy in Windows API. +func safeArrayCopy(original *SafeArray) (*SafeArray, error) { + return nil, NewError(E_NOTIMPL) +} + +// safeArrayCopyData duplicates SafeArray into another SafeArray object. +// +// AKA: SafeArrayCopyData in Windows API. +func safeArrayCopyData(original *SafeArray, duplicate *SafeArray) error { + return NewError(E_NOTIMPL) +} + +// safeArrayCreate creates SafeArray. +// +// AKA: SafeArrayCreate in Windows API. +func safeArrayCreate(variantType VT, dimensions uint32, bounds *SafeArrayBound) (*SafeArray, error) { + return nil, NewError(E_NOTIMPL) +} + +// safeArrayCreateEx creates SafeArray. +// +// AKA: SafeArrayCreateEx in Windows API. +func safeArrayCreateEx(variantType VT, dimensions uint32, bounds *SafeArrayBound, extra uintptr) (*SafeArray, error) { + return nil, NewError(E_NOTIMPL) +} + +// safeArrayCreateVector creates SafeArray. +// +// AKA: SafeArrayCreateVector in Windows API. +func safeArrayCreateVector(variantType VT, lowerBound int32, length uint32) (*SafeArray, error) { + return nil, NewError(E_NOTIMPL) +} + +// safeArrayCreateVectorEx creates SafeArray. +// +// AKA: SafeArrayCreateVectorEx in Windows API. +func safeArrayCreateVectorEx(variantType VT, lowerBound int32, length uint32, extra uintptr) (*SafeArray, error) { + return nil, NewError(E_NOTIMPL) +} + +// safeArrayDestroy destroys SafeArray object. +// +// AKA: SafeArrayDestroy in Windows API. +func safeArrayDestroy(safearray *SafeArray) error { + return NewError(E_NOTIMPL) +} + +// safeArrayDestroyData destroys SafeArray object. +// +// AKA: SafeArrayDestroyData in Windows API. +func safeArrayDestroyData(safearray *SafeArray) error { + return NewError(E_NOTIMPL) +} + +// safeArrayDestroyDescriptor destroys SafeArray object. +// +// AKA: SafeArrayDestroyDescriptor in Windows API. +func safeArrayDestroyDescriptor(safearray *SafeArray) error { + return NewError(E_NOTIMPL) +} + +// safeArrayGetDim is the amount of dimensions in the SafeArray. +// +// SafeArrays may have multiple dimensions. Meaning, it could be +// multidimensional array. +// +// AKA: SafeArrayGetDim in Windows API. +func safeArrayGetDim(safearray *SafeArray) (*uint32, error) { + u := uint32(0) + return &u, NewError(E_NOTIMPL) +} + +// safeArrayGetElementSize is the element size in bytes. +// +// AKA: SafeArrayGetElemsize in Windows API. +func safeArrayGetElementSize(safearray *SafeArray) (*uint32, error) { + u := uint32(0) + return &u, NewError(E_NOTIMPL) +} + +// safeArrayGetElement retrieves element at given index. +func safeArrayGetElement(safearray *SafeArray, index int32, pv unsafe.Pointer) error { + return NewError(E_NOTIMPL) +} + +// safeArrayGetElement retrieves element at given index and converts to string. +func safeArrayGetElementString(safearray *SafeArray, index int32) (string, error) { + return "", NewError(E_NOTIMPL) +} + +// safeArrayGetIID is the InterfaceID of the elements in the SafeArray. +// +// AKA: SafeArrayGetIID in Windows API. +func safeArrayGetIID(safearray *SafeArray) (*GUID, error) { + return nil, NewError(E_NOTIMPL) +} + +// safeArrayGetLBound returns lower bounds of SafeArray. +// +// SafeArrays may have multiple dimensions. Meaning, it could be +// multidimensional array. +// +// AKA: SafeArrayGetLBound in Windows API. +func safeArrayGetLBound(safearray *SafeArray, dimension uint32) (int32, error) { + return int32(0), NewError(E_NOTIMPL) +} + +// safeArrayGetUBound returns upper bounds of SafeArray. +// +// SafeArrays may have multiple dimensions. Meaning, it could be +// multidimensional array. +// +// AKA: SafeArrayGetUBound in Windows API. +func safeArrayGetUBound(safearray *SafeArray, dimension uint32) (int32, error) { + return int32(0), NewError(E_NOTIMPL) +} + +// safeArrayGetVartype returns data type of SafeArray. +// +// AKA: SafeArrayGetVartype in Windows API. +func safeArrayGetVartype(safearray *SafeArray) (uint16, error) { + return uint16(0), NewError(E_NOTIMPL) +} + +// safeArrayLock locks SafeArray for reading to modify SafeArray. +// +// This must be called during some calls to ensure that another process does not +// read or write to the SafeArray during editing. +// +// AKA: SafeArrayLock in Windows API. +func safeArrayLock(safearray *SafeArray) error { + return NewError(E_NOTIMPL) +} + +// safeArrayUnlock unlocks SafeArray for reading. +// +// AKA: SafeArrayUnlock in Windows API. +func safeArrayUnlock(safearray *SafeArray) error { + return NewError(E_NOTIMPL) +} + +// safeArrayPutElement stores the data element at the specified location in the +// array. +// +// AKA: SafeArrayPutElement in Windows API. +func safeArrayPutElement(safearray *SafeArray, index int64, element uintptr) error { + return NewError(E_NOTIMPL) +} + +// safeArrayGetRecordInfo accesses IRecordInfo info for custom types. +// +// AKA: SafeArrayGetRecordInfo in Windows API. +// +// XXX: Must implement IRecordInfo interface for this to return. +func safeArrayGetRecordInfo(safearray *SafeArray) (interface{}, error) { + return nil, NewError(E_NOTIMPL) +} + +// safeArraySetRecordInfo mutates IRecordInfo info for custom types. +// +// AKA: SafeArraySetRecordInfo in Windows API. +// +// XXX: Must implement IRecordInfo interface for this to return. +func safeArraySetRecordInfo(safearray *SafeArray, recordInfo interface{}) error { + return NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/safearray_windows.go b/vendor/github.com/go-ole/go-ole/safearray_windows.go new file mode 100644 index 000000000000..b48a2394d1e5 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/safearray_windows.go @@ -0,0 +1,337 @@ +// +build windows + +package ole + +import ( + "unsafe" +) + +var ( + procSafeArrayAccessData, _ = modoleaut32.FindProc("SafeArrayAccessData") + procSafeArrayAllocData, _ = modoleaut32.FindProc("SafeArrayAllocData") + procSafeArrayAllocDescriptor, _ = modoleaut32.FindProc("SafeArrayAllocDescriptor") + procSafeArrayAllocDescriptorEx, _ = modoleaut32.FindProc("SafeArrayAllocDescriptorEx") + procSafeArrayCopy, _ = modoleaut32.FindProc("SafeArrayCopy") + procSafeArrayCopyData, _ = modoleaut32.FindProc("SafeArrayCopyData") + procSafeArrayCreate, _ = modoleaut32.FindProc("SafeArrayCreate") + procSafeArrayCreateEx, _ = modoleaut32.FindProc("SafeArrayCreateEx") + procSafeArrayCreateVector, _ = modoleaut32.FindProc("SafeArrayCreateVector") + procSafeArrayCreateVectorEx, _ = modoleaut32.FindProc("SafeArrayCreateVectorEx") + procSafeArrayDestroy, _ = modoleaut32.FindProc("SafeArrayDestroy") + procSafeArrayDestroyData, _ = modoleaut32.FindProc("SafeArrayDestroyData") + procSafeArrayDestroyDescriptor, _ = modoleaut32.FindProc("SafeArrayDestroyDescriptor") + procSafeArrayGetDim, _ = modoleaut32.FindProc("SafeArrayGetDim") + procSafeArrayGetElement, _ = modoleaut32.FindProc("SafeArrayGetElement") + procSafeArrayGetElemsize, _ = modoleaut32.FindProc("SafeArrayGetElemsize") + procSafeArrayGetIID, _ = modoleaut32.FindProc("SafeArrayGetIID") + procSafeArrayGetLBound, _ = modoleaut32.FindProc("SafeArrayGetLBound") + procSafeArrayGetUBound, _ = modoleaut32.FindProc("SafeArrayGetUBound") + procSafeArrayGetVartype, _ = modoleaut32.FindProc("SafeArrayGetVartype") + procSafeArrayLock, _ = modoleaut32.FindProc("SafeArrayLock") + procSafeArrayPtrOfIndex, _ = modoleaut32.FindProc("SafeArrayPtrOfIndex") + procSafeArrayUnaccessData, _ = modoleaut32.FindProc("SafeArrayUnaccessData") + procSafeArrayUnlock, _ = modoleaut32.FindProc("SafeArrayUnlock") + procSafeArrayPutElement, _ = modoleaut32.FindProc("SafeArrayPutElement") + //procSafeArrayRedim, _ = modoleaut32.FindProc("SafeArrayRedim") // TODO + //procSafeArraySetIID, _ = modoleaut32.FindProc("SafeArraySetIID") // TODO + procSafeArrayGetRecordInfo, _ = modoleaut32.FindProc("SafeArrayGetRecordInfo") + procSafeArraySetRecordInfo, _ = modoleaut32.FindProc("SafeArraySetRecordInfo") +) + +// safeArrayAccessData returns raw array pointer. +// +// AKA: SafeArrayAccessData in Windows API. +// Todo: Test +func safeArrayAccessData(safearray *SafeArray) (element uintptr, err error) { + err = convertHresultToError( + procSafeArrayAccessData.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(unsafe.Pointer(&element)))) + return +} + +// safeArrayUnaccessData releases raw array. +// +// AKA: SafeArrayUnaccessData in Windows API. +func safeArrayUnaccessData(safearray *SafeArray) (err error) { + err = convertHresultToError(procSafeArrayUnaccessData.Call(uintptr(unsafe.Pointer(safearray)))) + return +} + +// safeArrayAllocData allocates SafeArray. +// +// AKA: SafeArrayAllocData in Windows API. +func safeArrayAllocData(safearray *SafeArray) (err error) { + err = convertHresultToError(procSafeArrayAllocData.Call(uintptr(unsafe.Pointer(safearray)))) + return +} + +// safeArrayAllocDescriptor allocates SafeArray. +// +// AKA: SafeArrayAllocDescriptor in Windows API. +func safeArrayAllocDescriptor(dimensions uint32) (safearray *SafeArray, err error) { + err = convertHresultToError( + procSafeArrayAllocDescriptor.Call(uintptr(dimensions), uintptr(unsafe.Pointer(&safearray)))) + return +} + +// safeArrayAllocDescriptorEx allocates SafeArray. +// +// AKA: SafeArrayAllocDescriptorEx in Windows API. +func safeArrayAllocDescriptorEx(variantType VT, dimensions uint32) (safearray *SafeArray, err error) { + err = convertHresultToError( + procSafeArrayAllocDescriptorEx.Call( + uintptr(variantType), + uintptr(dimensions), + uintptr(unsafe.Pointer(&safearray)))) + return +} + +// safeArrayCopy returns copy of SafeArray. +// +// AKA: SafeArrayCopy in Windows API. +func safeArrayCopy(original *SafeArray) (safearray *SafeArray, err error) { + err = convertHresultToError( + procSafeArrayCopy.Call( + uintptr(unsafe.Pointer(original)), + uintptr(unsafe.Pointer(&safearray)))) + return +} + +// safeArrayCopyData duplicates SafeArray into another SafeArray object. +// +// AKA: SafeArrayCopyData in Windows API. +func safeArrayCopyData(original *SafeArray, duplicate *SafeArray) (err error) { + err = convertHresultToError( + procSafeArrayCopyData.Call( + uintptr(unsafe.Pointer(original)), + uintptr(unsafe.Pointer(duplicate)))) + return +} + +// safeArrayCreate creates SafeArray. +// +// AKA: SafeArrayCreate in Windows API. +func safeArrayCreate(variantType VT, dimensions uint32, bounds *SafeArrayBound) (safearray *SafeArray, err error) { + sa, _, err := procSafeArrayCreate.Call( + uintptr(variantType), + uintptr(dimensions), + uintptr(unsafe.Pointer(bounds))) + safearray = (*SafeArray)(unsafe.Pointer(&sa)) + return +} + +// safeArrayCreateEx creates SafeArray. +// +// AKA: SafeArrayCreateEx in Windows API. +func safeArrayCreateEx(variantType VT, dimensions uint32, bounds *SafeArrayBound, extra uintptr) (safearray *SafeArray, err error) { + sa, _, err := procSafeArrayCreateEx.Call( + uintptr(variantType), + uintptr(dimensions), + uintptr(unsafe.Pointer(bounds)), + extra) + safearray = (*SafeArray)(unsafe.Pointer(sa)) + return +} + +// safeArrayCreateVector creates SafeArray. +// +// AKA: SafeArrayCreateVector in Windows API. +func safeArrayCreateVector(variantType VT, lowerBound int32, length uint32) (safearray *SafeArray, err error) { + sa, _, err := procSafeArrayCreateVector.Call( + uintptr(variantType), + uintptr(lowerBound), + uintptr(length)) + safearray = (*SafeArray)(unsafe.Pointer(sa)) + return +} + +// safeArrayCreateVectorEx creates SafeArray. +// +// AKA: SafeArrayCreateVectorEx in Windows API. +func safeArrayCreateVectorEx(variantType VT, lowerBound int32, length uint32, extra uintptr) (safearray *SafeArray, err error) { + sa, _, err := procSafeArrayCreateVectorEx.Call( + uintptr(variantType), + uintptr(lowerBound), + uintptr(length), + extra) + safearray = (*SafeArray)(unsafe.Pointer(sa)) + return +} + +// safeArrayDestroy destroys SafeArray object. +// +// AKA: SafeArrayDestroy in Windows API. +func safeArrayDestroy(safearray *SafeArray) (err error) { + err = convertHresultToError(procSafeArrayDestroy.Call(uintptr(unsafe.Pointer(safearray)))) + return +} + +// safeArrayDestroyData destroys SafeArray object. +// +// AKA: SafeArrayDestroyData in Windows API. +func safeArrayDestroyData(safearray *SafeArray) (err error) { + err = convertHresultToError(procSafeArrayDestroyData.Call(uintptr(unsafe.Pointer(safearray)))) + return +} + +// safeArrayDestroyDescriptor destroys SafeArray object. +// +// AKA: SafeArrayDestroyDescriptor in Windows API. +func safeArrayDestroyDescriptor(safearray *SafeArray) (err error) { + err = convertHresultToError(procSafeArrayDestroyDescriptor.Call(uintptr(unsafe.Pointer(safearray)))) + return +} + +// safeArrayGetDim is the amount of dimensions in the SafeArray. +// +// SafeArrays may have multiple dimensions. Meaning, it could be +// multidimensional array. +// +// AKA: SafeArrayGetDim in Windows API. +func safeArrayGetDim(safearray *SafeArray) (dimensions *uint32, err error) { + l, _, err := procSafeArrayGetDim.Call(uintptr(unsafe.Pointer(safearray))) + dimensions = (*uint32)(unsafe.Pointer(l)) + return +} + +// safeArrayGetElementSize is the element size in bytes. +// +// AKA: SafeArrayGetElemsize in Windows API. +func safeArrayGetElementSize(safearray *SafeArray) (length *uint32, err error) { + l, _, err := procSafeArrayGetElemsize.Call(uintptr(unsafe.Pointer(safearray))) + length = (*uint32)(unsafe.Pointer(l)) + return +} + +// safeArrayGetElement retrieves element at given index. +func safeArrayGetElement(safearray *SafeArray, index int32, pv unsafe.Pointer) error { + return convertHresultToError( + procSafeArrayGetElement.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(unsafe.Pointer(&index)), + uintptr(pv))) +} + +// safeArrayGetElementString retrieves element at given index and converts to string. +func safeArrayGetElementString(safearray *SafeArray, index int32) (str string, err error) { + var element *int16 + err = convertHresultToError( + procSafeArrayGetElement.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(unsafe.Pointer(&index)), + uintptr(unsafe.Pointer(&element)))) + str = BstrToString(*(**uint16)(unsafe.Pointer(&element))) + SysFreeString(element) + return +} + +// safeArrayGetIID is the InterfaceID of the elements in the SafeArray. +// +// AKA: SafeArrayGetIID in Windows API. +func safeArrayGetIID(safearray *SafeArray) (guid *GUID, err error) { + err = convertHresultToError( + procSafeArrayGetIID.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(unsafe.Pointer(&guid)))) + return +} + +// safeArrayGetLBound returns lower bounds of SafeArray. +// +// SafeArrays may have multiple dimensions. Meaning, it could be +// multidimensional array. +// +// AKA: SafeArrayGetLBound in Windows API. +func safeArrayGetLBound(safearray *SafeArray, dimension uint32) (lowerBound int32, err error) { + err = convertHresultToError( + procSafeArrayGetLBound.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(dimension), + uintptr(unsafe.Pointer(&lowerBound)))) + return +} + +// safeArrayGetUBound returns upper bounds of SafeArray. +// +// SafeArrays may have multiple dimensions. Meaning, it could be +// multidimensional array. +// +// AKA: SafeArrayGetUBound in Windows API. +func safeArrayGetUBound(safearray *SafeArray, dimension uint32) (upperBound int32, err error) { + err = convertHresultToError( + procSafeArrayGetUBound.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(dimension), + uintptr(unsafe.Pointer(&upperBound)))) + return +} + +// safeArrayGetVartype returns data type of SafeArray. +// +// AKA: SafeArrayGetVartype in Windows API. +func safeArrayGetVartype(safearray *SafeArray) (varType uint16, err error) { + err = convertHresultToError( + procSafeArrayGetVartype.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(unsafe.Pointer(&varType)))) + return +} + +// safeArrayLock locks SafeArray for reading to modify SafeArray. +// +// This must be called during some calls to ensure that another process does not +// read or write to the SafeArray during editing. +// +// AKA: SafeArrayLock in Windows API. +func safeArrayLock(safearray *SafeArray) (err error) { + err = convertHresultToError(procSafeArrayLock.Call(uintptr(unsafe.Pointer(safearray)))) + return +} + +// safeArrayUnlock unlocks SafeArray for reading. +// +// AKA: SafeArrayUnlock in Windows API. +func safeArrayUnlock(safearray *SafeArray) (err error) { + err = convertHresultToError(procSafeArrayUnlock.Call(uintptr(unsafe.Pointer(safearray)))) + return +} + +// safeArrayPutElement stores the data element at the specified location in the +// array. +// +// AKA: SafeArrayPutElement in Windows API. +func safeArrayPutElement(safearray *SafeArray, index int64, element uintptr) (err error) { + err = convertHresultToError( + procSafeArrayPutElement.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(unsafe.Pointer(&index)), + uintptr(unsafe.Pointer(element)))) + return +} + +// safeArrayGetRecordInfo accesses IRecordInfo info for custom types. +// +// AKA: SafeArrayGetRecordInfo in Windows API. +// +// XXX: Must implement IRecordInfo interface for this to return. +func safeArrayGetRecordInfo(safearray *SafeArray) (recordInfo interface{}, err error) { + err = convertHresultToError( + procSafeArrayGetRecordInfo.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(unsafe.Pointer(&recordInfo)))) + return +} + +// safeArraySetRecordInfo mutates IRecordInfo info for custom types. +// +// AKA: SafeArraySetRecordInfo in Windows API. +// +// XXX: Must implement IRecordInfo interface for this to return. +func safeArraySetRecordInfo(safearray *SafeArray, recordInfo interface{}) (err error) { + err = convertHresultToError( + procSafeArraySetRecordInfo.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(unsafe.Pointer(&recordInfo)))) + return +} diff --git a/vendor/github.com/go-ole/go-ole/safearrayconversion.go b/vendor/github.com/go-ole/go-ole/safearrayconversion.go new file mode 100644 index 000000000000..259f488ec7f9 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/safearrayconversion.go @@ -0,0 +1,140 @@ +// Helper for converting SafeArray to array of objects. + +package ole + +import ( + "unsafe" +) + +type SafeArrayConversion struct { + Array *SafeArray +} + +func (sac *SafeArrayConversion) ToStringArray() (strings []string) { + totalElements, _ := sac.TotalElements(0) + strings = make([]string, totalElements) + + for i := int32(0); i < totalElements; i++ { + strings[int32(i)], _ = safeArrayGetElementString(sac.Array, i) + } + + return +} + +func (sac *SafeArrayConversion) ToByteArray() (bytes []byte) { + totalElements, _ := sac.TotalElements(0) + bytes = make([]byte, totalElements) + + for i := int32(0); i < totalElements; i++ { + safeArrayGetElement(sac.Array, i, unsafe.Pointer(&bytes[int32(i)])) + } + + return +} + +func (sac *SafeArrayConversion) ToValueArray() (values []interface{}) { + totalElements, _ := sac.TotalElements(0) + values = make([]interface{}, totalElements) + vt, _ := safeArrayGetVartype(sac.Array) + + for i := int32(0); i < totalElements; i++ { + switch VT(vt) { + case VT_BOOL: + var v bool + safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v)) + values[i] = v + case VT_I1: + var v int8 + safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v)) + values[i] = v + case VT_I2: + var v int16 + safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v)) + values[i] = v + case VT_I4: + var v int32 + safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v)) + values[i] = v + case VT_I8: + var v int64 + safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v)) + values[i] = v + case VT_UI1: + var v uint8 + safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v)) + values[i] = v + case VT_UI2: + var v uint16 + safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v)) + values[i] = v + case VT_UI4: + var v uint32 + safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v)) + values[i] = v + case VT_UI8: + var v uint64 + safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v)) + values[i] = v + case VT_R4: + var v float32 + safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v)) + values[i] = v + case VT_R8: + var v float64 + safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v)) + values[i] = v + case VT_BSTR: + var v string + safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v)) + values[i] = v + case VT_VARIANT: + var v VARIANT + safeArrayGetElement(sac.Array, i, unsafe.Pointer(&v)) + values[i] = v.Value() + default: + // TODO + } + } + + return +} + +func (sac *SafeArrayConversion) GetType() (varType uint16, err error) { + return safeArrayGetVartype(sac.Array) +} + +func (sac *SafeArrayConversion) GetDimensions() (dimensions *uint32, err error) { + return safeArrayGetDim(sac.Array) +} + +func (sac *SafeArrayConversion) GetSize() (length *uint32, err error) { + return safeArrayGetElementSize(sac.Array) +} + +func (sac *SafeArrayConversion) TotalElements(index uint32) (totalElements int32, err error) { + if index < 1 { + index = 1 + } + + // Get array bounds + var LowerBounds int32 + var UpperBounds int32 + + LowerBounds, err = safeArrayGetLBound(sac.Array, index) + if err != nil { + return + } + + UpperBounds, err = safeArrayGetUBound(sac.Array, index) + if err != nil { + return + } + + totalElements = UpperBounds - LowerBounds + 1 + return +} + +// Release Safe Array memory +func (sac *SafeArrayConversion) Release() { + safeArrayDestroy(sac.Array) +} diff --git a/vendor/github.com/go-ole/go-ole/safearrayslices.go b/vendor/github.com/go-ole/go-ole/safearrayslices.go new file mode 100644 index 000000000000..a9fa885f1d81 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/safearrayslices.go @@ -0,0 +1,33 @@ +// +build windows + +package ole + +import ( + "unsafe" +) + +func safeArrayFromByteSlice(slice []byte) *SafeArray { + array, _ := safeArrayCreateVector(VT_UI1, 0, uint32(len(slice))) + + if array == nil { + panic("Could not convert []byte to SAFEARRAY") + } + + for i, v := range slice { + safeArrayPutElement(array, int64(i), uintptr(unsafe.Pointer(&v))) + } + return array +} + +func safeArrayFromStringSlice(slice []string) *SafeArray { + array, _ := safeArrayCreateVector(VT_BSTR, 0, uint32(len(slice))) + + if array == nil { + panic("Could not convert []string to SAFEARRAY") + } + // SysAllocStringLen(s) + for i, v := range slice { + safeArrayPutElement(array, int64(i), uintptr(unsafe.Pointer(SysAllocStringLen(v)))) + } + return array +} diff --git a/vendor/github.com/go-ole/go-ole/utility.go b/vendor/github.com/go-ole/go-ole/utility.go new file mode 100644 index 000000000000..99ee82dc3451 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/utility.go @@ -0,0 +1,101 @@ +package ole + +import ( + "unicode/utf16" + "unsafe" +) + +// ClassIDFrom retrieves class ID whether given is program ID or application string. +// +// Helper that provides check against both Class ID from Program ID and Class ID from string. It is +// faster, if you know which you are using, to use the individual functions, but this will check +// against available functions for you. +func ClassIDFrom(programID string) (classID *GUID, err error) { + classID, err = CLSIDFromProgID(programID) + if err != nil { + classID, err = CLSIDFromString(programID) + if err != nil { + return + } + } + return +} + +// BytePtrToString converts byte pointer to a Go string. +func BytePtrToString(p *byte) string { + a := (*[10000]uint8)(unsafe.Pointer(p)) + i := 0 + for a[i] != 0 { + i++ + } + return string(a[:i]) +} + +// UTF16PtrToString is alias for LpOleStrToString. +// +// Kept for compatibility reasons. +func UTF16PtrToString(p *uint16) string { + return LpOleStrToString(p) +} + +// LpOleStrToString converts COM Unicode to Go string. +func LpOleStrToString(p *uint16) string { + if p == nil { + return "" + } + + length := lpOleStrLen(p) + a := make([]uint16, length) + + ptr := unsafe.Pointer(p) + + for i := 0; i < int(length); i++ { + a[i] = *(*uint16)(ptr) + ptr = unsafe.Pointer(uintptr(ptr) + 2) + } + + return string(utf16.Decode(a)) +} + +// BstrToString converts COM binary string to Go string. +func BstrToString(p *uint16) string { + if p == nil { + return "" + } + length := SysStringLen((*int16)(unsafe.Pointer(p))) + a := make([]uint16, length) + + ptr := unsafe.Pointer(p) + + for i := 0; i < int(length); i++ { + a[i] = *(*uint16)(ptr) + ptr = unsafe.Pointer(uintptr(ptr) + 2) + } + return string(utf16.Decode(a)) +} + +// lpOleStrLen returns the length of Unicode string. +func lpOleStrLen(p *uint16) (length int64) { + if p == nil { + return 0 + } + + ptr := unsafe.Pointer(p) + + for i := 0; ; i++ { + if 0 == *(*uint16)(ptr) { + length = int64(i) + break + } + ptr = unsafe.Pointer(uintptr(ptr) + 2) + } + return +} + +// convertHresultToError converts syscall to error, if call is unsuccessful. +func convertHresultToError(hr uintptr, r2 uintptr, ignore error) (err error) { + if hr != 0 { + err = NewError(hr) + } + return +} diff --git a/vendor/github.com/go-ole/go-ole/variables.go b/vendor/github.com/go-ole/go-ole/variables.go new file mode 100644 index 000000000000..ebe00f1cfc9b --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/variables.go @@ -0,0 +1,16 @@ +// +build windows + +package ole + +import ( + "syscall" +) + +var ( + modcombase = syscall.NewLazyDLL("combase.dll") + modkernel32, _ = syscall.LoadDLL("kernel32.dll") + modole32, _ = syscall.LoadDLL("ole32.dll") + modoleaut32, _ = syscall.LoadDLL("oleaut32.dll") + modmsvcrt, _ = syscall.LoadDLL("msvcrt.dll") + moduser32, _ = syscall.LoadDLL("user32.dll") +) diff --git a/vendor/github.com/go-ole/go-ole/variant.go b/vendor/github.com/go-ole/go-ole/variant.go new file mode 100644 index 000000000000..967a23fea9ab --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/variant.go @@ -0,0 +1,105 @@ +package ole + +import "unsafe" + +// NewVariant returns new variant based on type and value. +func NewVariant(vt VT, val int64) VARIANT { + return VARIANT{VT: vt, Val: val} +} + +// ToIUnknown converts Variant to Unknown object. +func (v *VARIANT) ToIUnknown() *IUnknown { + if v.VT != VT_UNKNOWN { + return nil + } + return (*IUnknown)(unsafe.Pointer(uintptr(v.Val))) +} + +// ToIDispatch converts variant to dispatch object. +func (v *VARIANT) ToIDispatch() *IDispatch { + if v.VT != VT_DISPATCH { + return nil + } + return (*IDispatch)(unsafe.Pointer(uintptr(v.Val))) +} + +// ToArray converts variant to SafeArray helper. +func (v *VARIANT) ToArray() *SafeArrayConversion { + if v.VT != VT_SAFEARRAY { + if v.VT&VT_ARRAY == 0 { + return nil + } + } + var safeArray *SafeArray = (*SafeArray)(unsafe.Pointer(uintptr(v.Val))) + return &SafeArrayConversion{safeArray} +} + +// ToString converts variant to Go string. +func (v *VARIANT) ToString() string { + if v.VT != VT_BSTR { + return "" + } + return BstrToString(*(**uint16)(unsafe.Pointer(&v.Val))) +} + +// Clear the memory of variant object. +func (v *VARIANT) Clear() error { + return VariantClear(v) +} + +// Value returns variant value based on its type. +// +// Currently supported types: 2- and 4-byte integers, strings, bools. +// Note that 64-bit integers, datetimes, and other types are stored as strings +// and will be returned as strings. +// +// Needs to be further converted, because this returns an interface{}. +func (v *VARIANT) Value() interface{} { + switch v.VT { + case VT_I1: + return int8(v.Val) + case VT_UI1: + return uint8(v.Val) + case VT_I2: + return int16(v.Val) + case VT_UI2: + return uint16(v.Val) + case VT_I4: + return int32(v.Val) + case VT_UI4: + return uint32(v.Val) + case VT_I8: + return int64(v.Val) + case VT_UI8: + return uint64(v.Val) + case VT_INT: + return int(v.Val) + case VT_UINT: + return uint(v.Val) + case VT_INT_PTR: + return uintptr(v.Val) // TODO + case VT_UINT_PTR: + return uintptr(v.Val) + case VT_R4: + return *(*float32)(unsafe.Pointer(&v.Val)) + case VT_R8: + return *(*float64)(unsafe.Pointer(&v.Val)) + case VT_BSTR: + return v.ToString() + case VT_DATE: + // VT_DATE type will either return float64 or time.Time. + d := uint64(v.Val) + date, err := GetVariantDate(d) + if err != nil { + return float64(v.Val) + } + return date + case VT_UNKNOWN: + return v.ToIUnknown() + case VT_DISPATCH: + return v.ToIDispatch() + case VT_BOOL: + return v.Val != 0 + } + return nil +} diff --git a/vendor/github.com/go-ole/go-ole/variant_386.go b/vendor/github.com/go-ole/go-ole/variant_386.go new file mode 100644 index 000000000000..e73736bf3917 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/variant_386.go @@ -0,0 +1,11 @@ +// +build 386 + +package ole + +type VARIANT struct { + VT VT // 2 + wReserved1 uint16 // 4 + wReserved2 uint16 // 6 + wReserved3 uint16 // 8 + Val int64 // 16 +} diff --git a/vendor/github.com/go-ole/go-ole/variant_amd64.go b/vendor/github.com/go-ole/go-ole/variant_amd64.go new file mode 100644 index 000000000000..dccdde132333 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/variant_amd64.go @@ -0,0 +1,12 @@ +// +build amd64 + +package ole + +type VARIANT struct { + VT VT // 2 + wReserved1 uint16 // 4 + wReserved2 uint16 // 6 + wReserved3 uint16 // 8 + Val int64 // 16 + _ [8]byte // 24 +} diff --git a/vendor/github.com/go-ole/go-ole/variant_date_386.go b/vendor/github.com/go-ole/go-ole/variant_date_386.go new file mode 100644 index 000000000000..1b970f63f5fb --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/variant_date_386.go @@ -0,0 +1,22 @@ +// +build windows,386 + +package ole + +import ( + "errors" + "syscall" + "time" + "unsafe" +) + +// GetVariantDate converts COM Variant Time value to Go time.Time. +func GetVariantDate(value uint64) (time.Time, error) { + var st syscall.Systemtime + v1 := uint32(value) + v2 := uint32(value >> 32) + r, _, _ := procVariantTimeToSystemTime.Call(uintptr(v1), uintptr(v2), uintptr(unsafe.Pointer(&st))) + if r != 0 { + return time.Date(int(st.Year), time.Month(st.Month), int(st.Day), int(st.Hour), int(st.Minute), int(st.Second), int(st.Milliseconds/1000), time.UTC), nil + } + return time.Now(), errors.New("Could not convert to time, passing current time.") +} diff --git a/vendor/github.com/go-ole/go-ole/variant_date_amd64.go b/vendor/github.com/go-ole/go-ole/variant_date_amd64.go new file mode 100644 index 000000000000..6952f1f0de64 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/variant_date_amd64.go @@ -0,0 +1,20 @@ +// +build windows,amd64 + +package ole + +import ( + "errors" + "syscall" + "time" + "unsafe" +) + +// GetVariantDate converts COM Variant Time value to Go time.Time. +func GetVariantDate(value uint64) (time.Time, error) { + var st syscall.Systemtime + r, _, _ := procVariantTimeToSystemTime.Call(uintptr(value), uintptr(unsafe.Pointer(&st))) + if r != 0 { + return time.Date(int(st.Year), time.Month(st.Month), int(st.Day), int(st.Hour), int(st.Minute), int(st.Second), int(st.Milliseconds/1000), time.UTC), nil + } + return time.Now(), errors.New("Could not convert to time, passing current time.") +} diff --git a/vendor/github.com/go-ole/go-ole/variant_ppc64le.go b/vendor/github.com/go-ole/go-ole/variant_ppc64le.go new file mode 100644 index 000000000000..326427a7d144 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/variant_ppc64le.go @@ -0,0 +1,12 @@ +// +build ppc64le + +package ole + +type VARIANT struct { + VT VT // 2 + wReserved1 uint16 // 4 + wReserved2 uint16 // 6 + wReserved3 uint16 // 8 + Val int64 // 16 + _ [8]byte // 24 +} diff --git a/vendor/github.com/go-ole/go-ole/variant_s390x.go b/vendor/github.com/go-ole/go-ole/variant_s390x.go new file mode 100644 index 000000000000..9874ca66b4f5 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/variant_s390x.go @@ -0,0 +1,12 @@ +// +build s390x + +package ole + +type VARIANT struct { + VT VT // 2 + wReserved1 uint16 // 4 + wReserved2 uint16 // 6 + wReserved3 uint16 // 8 + Val int64 // 16 + _ [8]byte // 24 +} diff --git a/vendor/github.com/go-ole/go-ole/vt_string.go b/vendor/github.com/go-ole/go-ole/vt_string.go new file mode 100644 index 000000000000..729b4a04dd9d --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/vt_string.go @@ -0,0 +1,58 @@ +// generated by stringer -output vt_string.go -type VT; DO NOT EDIT + +package ole + +import "fmt" + +const ( + _VT_name_0 = "VT_EMPTYVT_NULLVT_I2VT_I4VT_R4VT_R8VT_CYVT_DATEVT_BSTRVT_DISPATCHVT_ERRORVT_BOOLVT_VARIANTVT_UNKNOWNVT_DECIMAL" + _VT_name_1 = "VT_I1VT_UI1VT_UI2VT_UI4VT_I8VT_UI8VT_INTVT_UINTVT_VOIDVT_HRESULTVT_PTRVT_SAFEARRAYVT_CARRAYVT_USERDEFINEDVT_LPSTRVT_LPWSTR" + _VT_name_2 = "VT_RECORDVT_INT_PTRVT_UINT_PTR" + _VT_name_3 = "VT_FILETIMEVT_BLOBVT_STREAMVT_STORAGEVT_STREAMED_OBJECTVT_STORED_OBJECTVT_BLOB_OBJECTVT_CFVT_CLSID" + _VT_name_4 = "VT_BSTR_BLOBVT_VECTOR" + _VT_name_5 = "VT_ARRAY" + _VT_name_6 = "VT_BYREF" + _VT_name_7 = "VT_RESERVED" + _VT_name_8 = "VT_ILLEGAL" +) + +var ( + _VT_index_0 = [...]uint8{0, 8, 15, 20, 25, 30, 35, 40, 47, 54, 65, 73, 80, 90, 100, 110} + _VT_index_1 = [...]uint8{0, 5, 11, 17, 23, 28, 34, 40, 47, 54, 64, 70, 82, 91, 105, 113, 122} + _VT_index_2 = [...]uint8{0, 9, 19, 30} + _VT_index_3 = [...]uint8{0, 11, 18, 27, 37, 55, 71, 85, 90, 98} + _VT_index_4 = [...]uint8{0, 12, 21} + _VT_index_5 = [...]uint8{0, 8} + _VT_index_6 = [...]uint8{0, 8} + _VT_index_7 = [...]uint8{0, 11} + _VT_index_8 = [...]uint8{0, 10} +) + +func (i VT) String() string { + switch { + case 0 <= i && i <= 14: + return _VT_name_0[_VT_index_0[i]:_VT_index_0[i+1]] + case 16 <= i && i <= 31: + i -= 16 + return _VT_name_1[_VT_index_1[i]:_VT_index_1[i+1]] + case 36 <= i && i <= 38: + i -= 36 + return _VT_name_2[_VT_index_2[i]:_VT_index_2[i+1]] + case 64 <= i && i <= 72: + i -= 64 + return _VT_name_3[_VT_index_3[i]:_VT_index_3[i+1]] + case 4095 <= i && i <= 4096: + i -= 4095 + return _VT_name_4[_VT_index_4[i]:_VT_index_4[i+1]] + case i == 8192: + return _VT_name_5 + case i == 16384: + return _VT_name_6 + case i == 32768: + return _VT_name_7 + case i == 65535: + return _VT_name_8 + default: + return fmt.Sprintf("VT(%d)", i) + } +} diff --git a/vendor/github.com/go-ole/go-ole/winrt.go b/vendor/github.com/go-ole/go-ole/winrt.go new file mode 100644 index 000000000000..4e9eca73244e --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/winrt.go @@ -0,0 +1,99 @@ +// +build windows + +package ole + +import ( + "reflect" + "syscall" + "unicode/utf8" + "unsafe" +) + +var ( + procRoInitialize = modcombase.NewProc("RoInitialize") + procRoActivateInstance = modcombase.NewProc("RoActivateInstance") + procRoGetActivationFactory = modcombase.NewProc("RoGetActivationFactory") + procWindowsCreateString = modcombase.NewProc("WindowsCreateString") + procWindowsDeleteString = modcombase.NewProc("WindowsDeleteString") + procWindowsGetStringRawBuffer = modcombase.NewProc("WindowsGetStringRawBuffer") +) + +func RoInitialize(thread_type uint32) (err error) { + hr, _, _ := procRoInitialize.Call(uintptr(thread_type)) + if hr != 0 { + err = NewError(hr) + } + return +} + +func RoActivateInstance(clsid string) (ins *IInspectable, err error) { + hClsid, err := NewHString(clsid) + if err != nil { + return nil, err + } + defer DeleteHString(hClsid) + + hr, _, _ := procRoActivateInstance.Call( + uintptr(unsafe.Pointer(hClsid)), + uintptr(unsafe.Pointer(&ins))) + if hr != 0 { + err = NewError(hr) + } + return +} + +func RoGetActivationFactory(clsid string, iid *GUID) (ins *IInspectable, err error) { + hClsid, err := NewHString(clsid) + if err != nil { + return nil, err + } + defer DeleteHString(hClsid) + + hr, _, _ := procRoGetActivationFactory.Call( + uintptr(unsafe.Pointer(hClsid)), + uintptr(unsafe.Pointer(iid)), + uintptr(unsafe.Pointer(&ins))) + if hr != 0 { + err = NewError(hr) + } + return +} + +// HString is handle string for pointers. +type HString uintptr + +// NewHString returns a new HString for Go string. +func NewHString(s string) (hstring HString, err error) { + u16 := syscall.StringToUTF16Ptr(s) + len := uint32(utf8.RuneCountInString(s)) + hr, _, _ := procWindowsCreateString.Call( + uintptr(unsafe.Pointer(u16)), + uintptr(len), + uintptr(unsafe.Pointer(&hstring))) + if hr != 0 { + err = NewError(hr) + } + return +} + +// DeleteHString deletes HString. +func DeleteHString(hstring HString) (err error) { + hr, _, _ := procWindowsDeleteString.Call(uintptr(hstring)) + if hr != 0 { + err = NewError(hr) + } + return +} + +// String returns Go string value of HString. +func (h HString) String() string { + var u16buf uintptr + var u16len uint32 + u16buf, _, _ = procWindowsGetStringRawBuffer.Call( + uintptr(h), + uintptr(unsafe.Pointer(&u16len))) + + u16hdr := reflect.SliceHeader{Data: u16buf, Len: int(u16len), Cap: int(u16len)} + u16 := *(*[]uint16)(unsafe.Pointer(&u16hdr)) + return syscall.UTF16ToString(u16) +} diff --git a/vendor/github.com/go-ole/go-ole/winrt_doc.go b/vendor/github.com/go-ole/go-ole/winrt_doc.go new file mode 100644 index 000000000000..52e6d74c9ab3 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/winrt_doc.go @@ -0,0 +1,36 @@ +// +build !windows + +package ole + +// RoInitialize +func RoInitialize(thread_type uint32) (err error) { + return NewError(E_NOTIMPL) +} + +// RoActivateInstance +func RoActivateInstance(clsid string) (ins *IInspectable, err error) { + return nil, NewError(E_NOTIMPL) +} + +// RoGetActivationFactory +func RoGetActivationFactory(clsid string, iid *GUID) (ins *IInspectable, err error) { + return nil, NewError(E_NOTIMPL) +} + +// HString is handle string for pointers. +type HString uintptr + +// NewHString returns a new HString for Go string. +func NewHString(s string) (hstring HString, err error) { + return HString(uintptr(0)), NewError(E_NOTIMPL) +} + +// DeleteHString deletes HString. +func DeleteHString(hstring HString) (err error) { + return NewError(E_NOTIMPL) +} + +// String returns Go string value of HString. +func (h HString) String() string { + return "" +} diff --git a/vendor/github.com/leoluk/perflib_exporter/LICENSE b/vendor/github.com/leoluk/perflib_exporter/LICENSE new file mode 100644 index 000000000000..169f2ab94741 --- /dev/null +++ b/vendor/github.com/leoluk/perflib_exporter/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2018 Leopold Schabel / The perflib_exporter authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/leoluk/perflib_exporter/collector/collector.go b/vendor/github.com/leoluk/perflib_exporter/collector/collector.go new file mode 100644 index 000000000000..990cfca13c20 --- /dev/null +++ b/vendor/github.com/leoluk/perflib_exporter/collector/collector.go @@ -0,0 +1,184 @@ +package collector + +import ( + "strings" + + "github.com/leoluk/perflib_exporter/perflib" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +// ... +const ( + Namespace = "perflib" + + // Conversion factors + hundredNsToSecondsScaleFactor = 1 / 1e7 +) + +// Collector is the interface a collector has to implement. +type Collector interface { + // Get new metrics and expose them via prometheus registry. + Collect(ch chan<- prometheus.Metric) (err error) +} + +type CounterKey struct { + ObjectIndex uint + CounterIndex uint + CounterType uint32 // This is a bit mask +} + +func NewCounterKey(object *perflib.PerfObject, def *perflib.PerfCounterDef) CounterKey { + return CounterKey{object.NameIndex, def.NameIndex, def.CounterType} +} + +type PerflibCollector struct { + perflibQuery string + perflibDescs map[CounterKey]*prometheus.Desc +} + +func NewPerflibCollector(query string) (c PerflibCollector) { + c.perflibQuery = query + + objects, err := perflib.QueryPerformanceData(c.perflibQuery) + + if err != nil { + panic(err) + } + + log.Debugf("Number of objects: %d", len(objects)) + + c.perflibDescs = make(map[CounterKey]*prometheus.Desc) + + for _, object := range objects { + for _, def := range object.CounterDefs { + desc := descFromCounterDef(*object, *def) + + key := NewCounterKey(object, def) + c.perflibDescs[key] = desc + } + } + + return +} + +func (c PerflibCollector) Collect(ch chan<- prometheus.Metric) (err error) { + // TODO QueryPerformanceData timing metric + objects, err := perflib.QueryPerformanceData(c.perflibQuery) + + if err != nil { + // TODO - we shouldn't panic if a single call fails + panic(err) + } + + log.Debugf("Number of objects: %d", len(objects)) + + for _, object := range objects { + n := object.NameIndex + + for _, instance := range object.Instances { + name := instance.Name + + // _Total metrics do not fit into the Prometheus model - we try to merge similar + // metrics and give them labels, so you'd sum() them instead. Having a _Total label + // would make + if strings.HasSuffix(name, "_Total") || strings.HasPrefix(name, "Total") { + continue + } + + for _, counter := range instance.Counters { + if IsDefPromotedLabel(n, counter.Def.NameIndex) { + continue + } + + if counter == nil { + log.Debugf("nil counter for %s -> %s", object.Name, instance.Name) + continue + } + + if counter.Def.NameIndex == 0 { + log.Debugf("null counter index for %s -> %s", object.Name, instance.Name) + continue + } + + if counter.Def.Name == "" { + log.Debugf("no counter name for %s -> %s", object.Name, instance.Name) + continue + } + + if counter.Def.Name == "No name" { + log.Debugf("no name counter %s -> %s -> %s", object.Name, instance.Name, counter.Def.Name) + continue + } + + key := NewCounterKey(object, counter.Def) + + desc, ok := c.perflibDescs[key] + + if !ok { + log.Debugf("missing metric description for counter %s -> %s -> %s", object.Name, instance.Name, counter.Def.Name) + continue + } + + labels := []string{name} + + if len(object.Instances) == 1 { + labels = []string{} + } + + if HasPromotedLabels(n) { + labels = append(labels, PromotedLabelValuesForInstance(n, instance)...) + } + + // TODO - Label merging needs to be fixed for [230] Process + //if HasMergedLabels(n) { + // _, value := MergedMetricForInstance(n, counter.Def.NameIndex) + // + // // Null string in definition means we should skip this metric (it's probably a sum) + // if value == "" { + // log.Debugf("Skipping %d -> %s (empty merge label)", n, counter.Def.NameIndex) + // continue + // } + // labels = append(labels, value) + //} + + valueType, err := GetPrometheusValueType(counter.Def.CounterType) + + if err != nil { + // TODO - Is this too verbose? There will always be counter types we don't support + log.Debug(err) + continue + } + + value := float64(counter.Value) + + if counter.Def.IsNanosecondCounter { + value = value * hundredNsToSecondsScaleFactor + } + + if IsElapsedTime(counter.Def.CounterType) { + // convert from Windows timestamp (1 jan 1601) to unix timestamp (1 jan 1970) + value = float64(counter.Value-116444736000000000) / float64(object.Frequency) + } + + metric := prometheus.MustNewConstMetric( + desc, + valueType, + value, + labels..., + ) + + ch <- metric + } + } + } + + /*ch <- prometheus.MustNewConstMetric( + prometheus.NewDesc(), + prometheus.CounterValue, + float64(0), + "ds_client", + )*/ + + return nil +} diff --git a/vendor/github.com/leoluk/perflib_exporter/collector/mangle.go b/vendor/github.com/leoluk/perflib_exporter/collector/mangle.go new file mode 100644 index 000000000000..cc1ed1b7f4a4 --- /dev/null +++ b/vendor/github.com/leoluk/perflib_exporter/collector/mangle.go @@ -0,0 +1,90 @@ +package collector + +import ( + "fmt" + "strings" + + "github.com/leoluk/perflib_exporter/perflib" + "github.com/prometheus/client_golang/prometheus" +) + +func manglePerflibName(s string) string { + s = strings.ToLower(s) + s = strings.Replace(s, " ", "_", -1) + s = strings.Replace(s, ".", "", -1) + s = strings.Replace(s, "(", "", -1) + s = strings.Replace(s, ")", "", -1) + s = strings.Replace(s, "+", "", -1) + s = strings.Replace(s, "-", "", -1) + s = strings.Replace(s, ",", "", -1) + + return s +} + +func manglePerflibCounterName(s string) string { + s = manglePerflibName(s) + + s = strings.Replace(s, "total_", "", -1) + s = strings.Replace(s, "_total", "", -1) + s = strings.Replace(s, "/second", "", -1) + s = strings.Replace(s, "/sec", "", -1) + s = strings.Replace(s, "_%", "", -1) + s = strings.Replace(s, "%_", "", -1) + s = strings.Replace(s, "/", "_per_", -1) + s = strings.Replace(s, "&", "and", -1) + s = strings.Replace(s, "#_of_", "", -1) + s = strings.Replace(s, ":", "", -1) + s = strings.Replace(s, "__", "_", -1) + + s = strings.Trim(s, " _") + + return s +} + +func MakePrometheusLabel(def *perflib.PerfCounterDef) (s string) { + s = manglePerflibCounterName(def.Name) + + if len(s) > 0 { + if IsCounter(def.CounterType) { + s += "_total" + } else if IsBaseValue(def.CounterType) && !strings.HasSuffix(s, "_base") { + s += "_max" + } + } + + return +} + +func pdhNameFromCounterDef(obj perflib.PerfObject, def perflib.PerfCounterDef) string { + return fmt.Sprintf(`\%s(*)\%s`, obj.Name, def.Name) +} + +func descFromCounterDef(obj perflib.PerfObject, def perflib.PerfCounterDef) *prometheus.Desc { + subsystem := manglePerflibName(obj.Name) + counterName := MakePrometheusLabel(&def) + + labels := []string{"name"} + + if len(obj.Instances) == 1 { + labels = []string{} + } + + if HasPromotedLabels(obj.NameIndex) { + labels = append(labels, PromotedLabelsForObject(obj.NameIndex)...) + } + + // TODO - Label merging needs to be fixed for [230] Process + //if HasMergedLabels(obj.NameIndex) { + // s, labelsForObject := MergedLabelsForInstance(obj.NameIndex, def.NameIndex) + // counterName = s + // labels = append(labels, labelsForObject) + //} + + return prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, counterName), + fmt.Sprintf("perflib metric: %s (see /dump for docs) [%d]", + pdhNameFromCounterDef(obj, def), def.NameIndex), + labels, + nil, + ) +} diff --git a/vendor/github.com/leoluk/perflib_exporter/collector/mapper.go b/vendor/github.com/leoluk/perflib_exporter/collector/mapper.go new file mode 100644 index 000000000000..f9f2278e1e1a --- /dev/null +++ b/vendor/github.com/leoluk/perflib_exporter/collector/mapper.go @@ -0,0 +1,91 @@ +package collector + +import ( + "fmt" + + "github.com/prometheus/client_golang/prometheus" +) + +const ( + PERF_COUNTER_RAWCOUNT_HEX = 0x00000000 + PERF_COUNTER_LARGE_RAWCOUNT_HEX = 0x00000100 + PERF_COUNTER_TEXT = 0x00000b00 + PERF_COUNTER_RAWCOUNT = 0x00010000 + PERF_COUNTER_LARGE_RAWCOUNT = 0x00010100 + PERF_DOUBLE_RAW = 0x00012000 + PERF_COUNTER_DELTA = 0x00400400 + PERF_COUNTER_LARGE_DELTA = 0x00400500 + PERF_SAMPLE_COUNTER = 0x00410400 + PERF_COUNTER_QUEUELEN_TYPE = 0x00450400 + PERF_COUNTER_LARGE_QUEUELEN_TYPE = 0x00450500 + PERF_COUNTER_100NS_QUEUELEN_TYPE = 0x00550500 + PERF_COUNTER_OBJ_TIME_QUEUELEN_TYPE = 0x00650500 + PERF_COUNTER_COUNTER = 0x10410400 + PERF_COUNTER_BULK_COUNT = 0x10410500 + PERF_RAW_FRACTION = 0x20020400 + PERF_LARGE_RAW_FRACTION = 0x20020500 + PERF_COUNTER_TIMER = 0x20410500 + PERF_PRECISION_SYSTEM_TIMER = 0x20470500 + PERF_100NSEC_TIMER = 0x20510500 + PERF_PRECISION_100NS_TIMER = 0x20570500 + PERF_OBJ_TIME_TIMER = 0x20610500 + PERF_PRECISION_OBJECT_TIMER = 0x20670500 + PERF_SAMPLE_FRACTION = 0x20c20400 + PERF_COUNTER_TIMER_INV = 0x21410500 + PERF_100NSEC_TIMER_INV = 0x21510500 + PERF_COUNTER_MULTI_TIMER = 0x22410500 + PERF_100NSEC_MULTI_TIMER = 0x22510500 + PERF_COUNTER_MULTI_TIMER_INV = 0x23410500 + PERF_100NSEC_MULTI_TIMER_INV = 0x23510500 + PERF_AVERAGE_TIMER = 0x30020400 + PERF_ELAPSED_TIME = 0x30240500 + PERF_COUNTER_NODATA = 0x40000200 + PERF_AVERAGE_BULK = 0x40020500 + PERF_SAMPLE_BASE = 0x40030401 + PERF_AVERAGE_BASE = 0x40030402 + PERF_RAW_BASE = 0x40030403 + PERF_PRECISION_TIMESTAMP = 0x40030500 + PERF_LARGE_RAW_BASE = 0x40030503 + PERF_COUNTER_MULTI_BASE = 0x42030500 + PERF_COUNTER_HISTOGRAM_TYPE = 0x80000000 +) + +var supportedCounterTypes = map[uint32]prometheus.ValueType{ + PERF_COUNTER_RAWCOUNT_HEX: prometheus.GaugeValue, + PERF_COUNTER_LARGE_RAWCOUNT_HEX: prometheus.GaugeValue, + PERF_COUNTER_RAWCOUNT: prometheus.GaugeValue, + PERF_COUNTER_LARGE_RAWCOUNT: prometheus.GaugeValue, + PERF_COUNTER_DELTA: prometheus.CounterValue, + PERF_COUNTER_COUNTER: prometheus.CounterValue, + PERF_COUNTER_BULK_COUNT: prometheus.CounterValue, + PERF_RAW_FRACTION: prometheus.GaugeValue, + PERF_LARGE_RAW_FRACTION: prometheus.GaugeValue, + PERF_100NSEC_TIMER: prometheus.CounterValue, + PERF_PRECISION_100NS_TIMER: prometheus.CounterValue, + PERF_SAMPLE_FRACTION: prometheus.GaugeValue, + PERF_100NSEC_TIMER_INV: prometheus.CounterValue, + PERF_ELAPSED_TIME: prometheus.GaugeValue, + PERF_SAMPLE_BASE: prometheus.GaugeValue, + PERF_RAW_BASE: prometheus.GaugeValue, + PERF_LARGE_RAW_BASE: prometheus.GaugeValue, +} + +func IsCounter(counterType uint32) bool { + return supportedCounterTypes[counterType] == prometheus.CounterValue +} + +func IsBaseValue(counterType uint32) bool { + return counterType == PERF_SAMPLE_BASE || counterType == PERF_RAW_BASE || counterType == PERF_LARGE_RAW_BASE +} + +func IsElapsedTime(counterType uint32) bool { + return counterType == PERF_ELAPSED_TIME +} + +func GetPrometheusValueType(counterType uint32) (prometheus.ValueType, error) { + val, ok := supportedCounterTypes[counterType] + if !ok { + return 0, fmt.Errorf("counter type %#08x is not supported", counterType) + } + return val, nil +} diff --git a/vendor/github.com/leoluk/perflib_exporter/collector/merge.go b/vendor/github.com/leoluk/perflib_exporter/collector/merge.go new file mode 100644 index 000000000000..9832e7f5a31c --- /dev/null +++ b/vendor/github.com/leoluk/perflib_exporter/collector/merge.go @@ -0,0 +1,38 @@ +package collector + +import "fmt" + +var mergedDefinitions = map[uint]map[string]map[uint]string{ + 230: { + "processor_time_total": { + 0: "mode", + 6: "", // Processor Time (drop) + 142: "user", // User Time + 144: "privileged", // Privileged Time + }, + }, +} + +// Return if a given object has merge definitions +func HasMergedLabels(index uint) bool { + _, ok := mergedDefinitions[index] + return ok +} + +// Return a list of merged label names for an instance +func MergedLabelsForInstance(objIndex uint, def uint) (name string, labelName string) { + return MergedMetricForInstance(objIndex, 0) +} + +// Return merged metric name and label value for an instance +func MergedMetricForInstance(objIndex uint, def uint) (name string, label string) { + for k, v := range mergedDefinitions[objIndex] { + for n := range v { + if def == n { + return k, v[n] + } + } + } + + panic(fmt.Sprintf("No merge definition for obj %d, inst %d", objIndex, def)) +} diff --git a/vendor/github.com/leoluk/perflib_exporter/collector/promote.go b/vendor/github.com/leoluk/perflib_exporter/collector/promote.go new file mode 100644 index 000000000000..db45b5ac8a82 --- /dev/null +++ b/vendor/github.com/leoluk/perflib_exporter/collector/promote.go @@ -0,0 +1,56 @@ +package collector + +import ( + "strconv" + + "github.com/leoluk/perflib_exporter/perflib" +) + +var labelPromotionLabels = map[uint][]string{ + 230: { + "process_id", + "creating_process_id", + }, +} +var labelPromotionValues = map[uint][]uint{ + 230: { + 784, // process_id + 1410, // creating_process_id + }, +} + +// Get a list of promoted labels for an object +func PromotedLabelsForObject(index uint) []string { + return labelPromotionLabels[index] +} + +// Get a list of label values for a given object and instance +func PromotedLabelValuesForInstance(index uint, instance *perflib.PerfInstance) []string { + values := make([]string, len(labelPromotionValues[index])) + + for _, c := range instance.Counters { + for i, v := range labelPromotionValues[index] { + if c.Def.NameIndex == v { + values[i] = strconv.Itoa(int(c.Value)) + } + } + } + + return values +} + +// Return if a given object has label promotion definitions +func HasPromotedLabels(index uint) bool { + _, ok := labelPromotionLabels[index] + return ok +} + +// Return if a given definition is a promoted label for an object +func IsDefPromotedLabel(objIndex uint, def uint) bool { + for _, v := range labelPromotionValues[objIndex] { + if v == def { + return true + } + } + return false +} diff --git a/vendor/github.com/leoluk/perflib_exporter/perflib/nametable.go b/vendor/github.com/leoluk/perflib_exporter/perflib/nametable.go new file mode 100644 index 000000000000..c620f3aa934b --- /dev/null +++ b/vendor/github.com/leoluk/perflib_exporter/perflib/nametable.go @@ -0,0 +1,75 @@ +package perflib + +import ( + "bytes" + "strconv" + "fmt" +) + +type nameTableLookuper interface { + LookupName() string + LookupHelp() string +} + +func (p *perfObjectType) LookupName() string { + return counterNameTable.LookupString(p.ObjectNameTitleIndex) +} + +func (p *perfObjectType) LookupHelp() string { + return helpNameTable.LookupString(p.ObjectHelpTitleIndex) +} + +type NameTable struct { + byIndex map[uint32]string + byString map[string]uint32 +} + +func (t *NameTable) LookupString(index uint32) string { + return t.byIndex[index] +} + +func (t *NameTable) LookupIndex(str string) uint32 { + return t.byString[str] +} + +// Query a perflib name table from the registry. Specify the type and the language +// code (i.e. "Counter 009" or "Help 009") for English language. +func QueryNameTable(tableName string) *NameTable { + nameTable := new(NameTable) + nameTable.byIndex = make(map[uint32]string) + + buffer, err := queryRawData(tableName) + if err != nil { + panic(err) + } + r := bytes.NewReader(buffer) + for { + index, err := readUTF16String(r) + + if err != nil { + break + } + + desc, err := readUTF16String(r) + + if err != nil { + break + } + + indexInt, _ := strconv.Atoi(index) + + if err != nil { + panic(fmt.Sprint("Invalid index ", index)) + } + + nameTable.byIndex[uint32(indexInt)] = desc + } + + nameTable.byString = make(map[string]uint32) + + for k, v := range nameTable.byIndex { + nameTable.byString[v] = k + } + + return nameTable +} diff --git a/vendor/github.com/leoluk/perflib_exporter/perflib/perflib.go b/vendor/github.com/leoluk/perflib_exporter/perflib/perflib.go new file mode 100644 index 000000000000..81601b435589 --- /dev/null +++ b/vendor/github.com/leoluk/perflib_exporter/perflib/perflib.go @@ -0,0 +1,460 @@ +/* + Go bindings for the HKEY_PERFORMANCE_DATA perflib / Performance Counters interface. + + Overview + + HKEY_PERFORMANCE_DATA is a low-level alternative to the higher-level PDH library and WMI. + It operates on blocks of counters and only returns raw values without calculating rates + or formatting them, which is exactly what you want for, say, a Prometheus exporter + (not so much for a GUI like Windows Performance Monitor). + + Its overhead is much lower than the high-level libraries. + + It operates on the same set of perflib providers as PDH and WMI. See this document + for more details on the relationship between the different libraries: + https://msdn.microsoft.com/en-us/library/windows/desktop/aa371643(v=vs.85).aspx + + Example C++ source code: + https://msdn.microsoft.com/de-de/library/windows/desktop/aa372138(v=vs.85).aspx + + For now, the API is not stable and is probably going to change in future + perflib_exporter releases. If you want to use this library, send the author an email + so we can discuss your requirements and stabilize the API. + + Names + + Counter names and help texts are resolved by looking up an index in a name table. + Since Microsoft loves internalization, both names and help texts can be requested + any locally available language. + + The library automatically loads the name tables and resolves all identifiers + in English ("Name" and "HelpText" struct members). You can manually resolve + identifiers in a different language by using the NameTable API. + + Performance Counters intro + + Windows has a system-wide performance counter mechanism. Most performance counters + are stored as actual counters, not gauges (with some exceptions). + There's additional metadata which defines how the counter should be presented to the user + (for example, as a calculated rate). This library disregards all of the display metadata. + + At the top level, there's a number of performance counter objects. + Each object has counter definitions, which contain the metadata for a particular + counter, and either zero or multiple instances. We hide the fact that there are + objects with no instances, and simply return a single null instance. + + There's one counter per counter definition and instance (or the object itself, if + there are no instances). + + Behind the scenes, every perflib DLL provides one or more objects. + Perflib has a registry where DLLs are dynamically registered and + unregistered. Some third party applications like VMWare provide their own counters, + but this is, sadly, a rare occurrence. + + Different Windows releases have different numbers of counters. + + Objects and counters are identified by well-known indices. + + Here's an example object with one instance: + + 4320 WSMan Quota Statistics [7 counters, 1 instance(s)] + `-- "WinRMService" + `-- Total Requests/Second [4322] = 59 + `-- User Quota Violations/Second [4324] = 0 + `-- System Quota Violations/Second [4326] = 0 + `-- Active Shells [4328] = 0 + `-- Active Operations [4330] = 0 + `-- Active Users [4332] = 0 + `-- Process ID [4334] = 928 + + All "per second" metrics are counters, the rest are gauges. + + Another example, with no instance: + + 4600 Network QoS Policy [6 counters, 1 instance(s)] + `-- (default) + `-- Packets transmitted [4602] = 1744 + `-- Packets transmitted/sec [4604] = 4852 + `-- Bytes transmitted [4606] = 4853 + `-- Bytes transmitted/sec [4608] = 180388626632 + `-- Packets dropped [4610] = 0 + `-- Packets dropped/sec [4612] = 0 + + You can access the same values using PowerShell's Get-Counter cmdlet + or the Performance Monitor. + + > Get-Counter '\WSMan Quota Statistics(WinRMService)\Process ID' + + Timestamp CounterSamples + --------- -------------- + 1/28/2018 10:18:00 PM \\DEV\wsman quota statistics(winrmservice)\process id : + 928 + + > (Get-Counter '\Process(Idle)\% Processor Time').CounterSamples[0] | Format-List * + [..detailed output...] + + Data for some of the objects is also available through WMI: + + > Get-CimInstance Win32_PerfRawData_Counters_WSManQuotaStatistics + + Name : WinRMService + [...] + ActiveOperations : 0 + ActiveShells : 0 + ActiveUsers : 0 + ProcessID : 928 + SystemQuotaViolationsPerSecond : 0 + TotalRequestsPerSecond : 59 + UserQuotaViolationsPerSecond : 0 + +*/ +package perflib + +import ( + "bytes" + "encoding/binary" + "fmt" + "io" + "sort" + "strings" + "syscall" + "unsafe" +) + +// TODO: There's a LittleEndian field in the PERF header - we ought to check it +var bo = binary.LittleEndian + +var counterNameTable NameTable +var helpNameTable NameTable + +// Top-level performance object (like "Process"). +type PerfObject struct { + Name string + // Same index you pass to QueryPerformanceData + NameIndex uint + HelpText string + HelpTextIndex uint + Instances []*PerfInstance + CounterDefs []*PerfCounterDef + + Frequency int64 + + rawData *perfObjectType +} + +// Each object can have multiple instances. For example, +// In case the object has no instances, we return one single PerfInstance with an empty name. +type PerfInstance struct { + // *not* resolved using a name table + Name string + Counters []*PerfCounter + + rawData *perfInstanceDefinition + rawCounterBlock *perfCounterBlock +} + +type PerfCounterDef struct { + Name string + NameIndex uint + HelpText string + HelpTextIndex uint + + // For debugging - subject to removal. CounterType is a perflib + // implementation detail (see perflib.h) and should not be used outside + // of this package. We export it so we can show it on /dump. + CounterType uint32 + + // PERF_TYPE_COUNTER (otherwise, it's a gauge) + IsCounter bool + // PERF_COUNTER_BASE (base value of a multi-value fraction) + IsBaseValue bool + // PERF_TIMER_100NS + IsNanosecondCounter bool + + rawData *perfCounterDefinition +} + +type PerfCounter struct { + Value int64 + Def *PerfCounterDef +} + +// Error value returned by RegQueryValueEx if the buffer isn't sufficiently large +const errorMoreData = syscall.Errno(234) + +var ( + bufLenGlobal = uint32(400000) + bufLenCostly = uint32(2000000) +) + +// Queries the performance counter buffer using RegQueryValueEx, returning raw bytes. See: +// https://msdn.microsoft.com/de-de/library/windows/desktop/aa373219(v=vs.85).aspx +func queryRawData(query string) ([]byte, error) { + var ( + valType uint32 + buffer []byte + bufLen uint32 + ) + + switch query { + case "Global": + bufLen = bufLenGlobal + case "Costly": + bufLen = bufLenCostly + default: + // TODO: depends on the number of values requested + // need make an educated guess + numCounters := len(strings.Split(query, " ")) + bufLen = uint32(150000 * numCounters) + } + + buffer = make([]byte, bufLen) + + name, err := syscall.UTF16PtrFromString(query) + + if err != nil { + return nil, fmt.Errorf("failed to encode query string: %v", err) + } + + for { + bufLen := uint32(len(buffer)) + + err := syscall.RegQueryValueEx( + syscall.HKEY_PERFORMANCE_DATA, + name, + nil, + &valType, + (*byte)(unsafe.Pointer(&buffer[0])), + &bufLen) + + if err == errorMoreData { + newBuffer := make([]byte, len(buffer)+16384) + copy(newBuffer, buffer) + buffer = newBuffer + continue + } else if err != nil { + if errno, ok := err.(syscall.Errno); ok { + return nil, fmt.Errorf("ReqQueryValueEx failed: %v errno %d", err, uint(errno)) + } + + return nil, err + } + + buffer = buffer[:bufLen] + + switch query { + case "Global": + if bufLen > bufLenGlobal { + bufLenGlobal = bufLen + } + case "Costly": + if bufLen > bufLenCostly { + bufLenCostly = bufLen + } + } + + return buffer, nil + } +} + +func init() { + // Initialize global name tables + // TODO: profiling, add option to disable name tables if necessary + // Not sure if we should resolve the names at all or just have the caller do it on demand + // (for many use cases the index is sufficient) + + counterNameTable = *QueryNameTable("Counter 009") + helpNameTable = *QueryNameTable("Help 009") +} + +/* +Query all performance counters that match a given query. + +The query can be any of the following: + +- "Global" (all performance counters except those Windows marked as costly) + +- "Costly" (only the costly ones) + +- One or more object indices, separated by spaces ("238 2 5") + +Many objects have dependencies - if you query one of them, you often get back +more than you asked for. +*/ +func QueryPerformanceData(query string) ([]*PerfObject, error) { + buffer, err := queryRawData(query) + + if err != nil { + return nil, err + } + + r := bytes.NewReader(buffer) + + // Read global header + + header := new(perfDataBlock) + err = header.BinaryReadFrom(r) + + if err != nil { + return nil, err + } + + // Check for "PERF" signature + if header.Signature != [4]uint16{80, 69, 82, 70} { + panic("Invalid performance block header") + } + + // Parse the performance data + + numObjects := int(header.NumObjectTypes) + objects := make([]*PerfObject, numObjects) + + objOffset := int64(header.HeaderLength) + + for i := 0; i < numObjects; i++ { + r.Seek(objOffset, io.SeekStart) + + obj := new(perfObjectType) + obj.BinaryReadFrom(r) + + numCounterDefs := int(obj.NumCounters) + numInstances := int(obj.NumInstances) + + // Perf objects can have no instances. The perflib differentiates + // between objects with instances and without, but we just create + // an empty instance in order to simplify the interface. + if numInstances <= 0 { + numInstances = 1 + } + + instances := make([]*PerfInstance, numInstances) + counterDefs := make([]*PerfCounterDef, numCounterDefs) + + objects[i] = &PerfObject{ + Name: obj.LookupName(), + NameIndex: uint(obj.ObjectNameTitleIndex), + HelpText: obj.LookupHelp(), + HelpTextIndex: uint(obj.ObjectHelpTitleIndex), + Instances: instances, + CounterDefs: counterDefs, + Frequency: obj.PerfFreq, + rawData: obj, + } + + for i := 0; i < numCounterDefs; i++ { + def := new(perfCounterDefinition) + def.BinaryReadFrom(r) + + counterDefs[i] = &PerfCounterDef{ + Name: def.LookupName(), + NameIndex: uint(def.CounterNameTitleIndex), + HelpText: def.LookupHelp(), + HelpTextIndex: uint(def.CounterHelpTitleIndex), + rawData: def, + + CounterType: def.CounterType, + + IsCounter: def.CounterType&0x400 == 0x400, + IsBaseValue: def.CounterType&0x00030000 == 0x00030000, + IsNanosecondCounter: def.CounterType&0x00100000 == 0x00100000, + } + } + + if obj.NumInstances <= 0 { + blockOffset := objOffset + int64(obj.DefinitionLength) + r.Seek(blockOffset, io.SeekStart) + + _, counters := parseCounterBlock(buffer, r, blockOffset, counterDefs) + + instances[0] = &PerfInstance{ + Name: "", + Counters: counters, + rawData: nil, + rawCounterBlock: nil, + } + } else { + instOffset := objOffset + int64(obj.DefinitionLength) + + for i := 0; i < numInstances; i++ { + r.Seek(instOffset, io.SeekStart) + + inst := new(perfInstanceDefinition) + inst.BinaryReadFrom(r) + + name, _ := readUTF16StringAtPos(r, instOffset+int64(inst.NameOffset), inst.NameLength) + pos := instOffset + int64(inst.ByteLength) + offset, counters := parseCounterBlock(buffer, r, pos, counterDefs) + + instances[i] = &PerfInstance{ + Name: name, + Counters: counters, + rawData: inst, + } + + instOffset = pos + offset + } + } + + // Next perfObjectType + objOffset += int64(obj.TotalByteLength) + } + + return objects, nil +} + +func parseCounterBlock(b []byte, r io.ReadSeeker, pos int64, defs []*PerfCounterDef) (int64, []*PerfCounter) { + r.Seek(pos, io.SeekStart) + block := new(perfCounterBlock) + block.BinaryReadFrom(r) + + counters := make([]*PerfCounter, len(defs)) + + for i, def := range defs { + valueOffset := pos + int64(def.rawData.CounterOffset) + value := convertCounterValue(def.rawData, b, valueOffset) + + counters[i] = &PerfCounter{ + Value: value, + Def: def, + } + } + + return int64(block.ByteLength), counters +} + +func convertCounterValue(counterDef *perfCounterDefinition, buffer []byte, valueOffset int64) (value int64) { + /* + We can safely ignore the type since we're not interested in anything except the raw value. + We also ignore all of the other attributes (timestamp, presentation, multi counter values...) + + See also: winperf.h. + + Here's the most common value for CounterType: + + 65536 32bit counter + 65792 64bit counter + 272696320 32bit rate + 272696576 64bit rate + + */ + + switch counterDef.CounterSize { + case 4: + value = int64(bo.Uint32(buffer[valueOffset:(valueOffset + 4)])) + case 8: + value = int64(bo.Uint64(buffer[valueOffset:(valueOffset + 8)])) + default: + value = int64(bo.Uint32(buffer[valueOffset:(valueOffset + 4)])) + } + + return +} + +// Sort slice of objects by index. This is useful for displaying +// a human-readable list or dump, but unnecessary otherwise. +func SortObjects(p []*PerfObject) { + sort.Slice(p, func(i, j int) bool { + return p[i].NameIndex < p[j].NameIndex + }) + +} diff --git a/vendor/github.com/leoluk/perflib_exporter/perflib/raw_types.go b/vendor/github.com/leoluk/perflib_exporter/perflib/raw_types.go new file mode 100644 index 000000000000..cc1ebff4f115 --- /dev/null +++ b/vendor/github.com/leoluk/perflib_exporter/perflib/raw_types.go @@ -0,0 +1,180 @@ +package perflib + +import ( + "syscall" + "io" + "encoding/binary" +) + +type binaryReaderFrom interface { + BinaryReadFrom(r io.Reader) error +} + +/* +https://msdn.microsoft.com/de-de/library/windows/desktop/aa373157(v=vs.85).aspx + +typedef struct _PERF_DATA_BLOCK { + WCHAR Signature[4]; + DWORD LittleEndian; + DWORD Version; + DWORD Revision; + DWORD TotalByteLength; + DWORD HeaderLength; + DWORD NumObjectTypes; + DWORD DefaultObject; + SYSTEMTIME SystemTime; + LARGE_INTEGER PerfTime; + LARGE_INTEGER PerfFreq; + LARGE_INTEGER PerfTime100nSec; + DWORD SystemNameLength; + DWORD SystemNameOffset; +} PERF_DATA_BLOCK; +*/ + +type perfDataBlock struct { + Signature [4]uint16 + LittleEndian uint32 + Version uint32 + Revision uint32 + TotalByteLength uint32 + HeaderLength uint32 + NumObjectTypes uint32 + DefaultObject int32 + SystemTime syscall.Systemtime + _ uint32 // TODO + PerfTime int64 + PerfFreq int64 + PerfTime100nSec int64 + SystemNameLength uint32 + SystemNameOffset uint32 +} + +func (p *perfDataBlock) BinaryReadFrom(r io.Reader) error { + return binary.Read(r, bo, p) +} + +/* +https://msdn.microsoft.com/en-us/library/windows/desktop/aa373160(v=vs.85).aspx + +typedef struct _PERF_OBJECT_TYPE { + DWORD TotalByteLength; + DWORD DefinitionLength; + DWORD HeaderLength; + DWORD ObjectNameTitleIndex; + LPWSTR ObjectNameTitle; + DWORD ObjectHelpTitleIndex; + LPWSTR ObjectHelpTitle; + DWORD DetailLevel; + DWORD NumCounters; + DWORD DefaultCounter; + DWORD NumInstances; + DWORD CodePage; + LARGE_INTEGER PerfTime; + LARGE_INTEGER PerfFreq; +} PERF_OBJECT_TYPE; +*/ + +type perfObjectType struct { + TotalByteLength uint32 + DefinitionLength uint32 + HeaderLength uint32 + ObjectNameTitleIndex uint32 + ObjectNameTitle uint32 + ObjectHelpTitleIndex uint32 + ObjectHelpTitle uint32 + DetailLevel uint32 + NumCounters uint32 + DefaultCounter int32 + NumInstances int32 + CodePage uint32 + PerfTime int64 + PerfFreq int64 +} + +func (p *perfObjectType) BinaryReadFrom(r io.Reader) error { + return binary.Read(r, bo, p) +} + +/* +https://msdn.microsoft.com/en-us/library/windows/desktop/aa373150(v=vs.85).aspx + +typedef struct _PERF_COUNTER_DEFINITION { + DWORD ByteLength; + DWORD CounterNameTitleIndex; + LPWSTR CounterNameTitle; + DWORD CounterHelpTitleIndex; + LPWSTR CounterHelpTitle; + LONG DefaultScale; + DWORD DetailLevel; + DWORD CounterType; + DWORD CounterSize; + DWORD CounterOffset; +} PERF_COUNTER_DEFINITION; +*/ + +type perfCounterDefinition struct { + ByteLength uint32 + CounterNameTitleIndex uint32 + CounterNameTitle uint32 + CounterHelpTitleIndex uint32 + CounterHelpTitle uint32 + DefaultScale int32 + DetailLevel uint32 + CounterType uint32 + CounterSize uint32 + CounterOffset uint32 +} + +func (p *perfCounterDefinition) BinaryReadFrom(r io.Reader) error { + return binary.Read(r, bo, p) +} + +func (p *perfCounterDefinition) LookupName() string { + return counterNameTable.LookupString(p.CounterNameTitleIndex) +} + +func (p *perfCounterDefinition) LookupHelp() string { + return helpNameTable.LookupString(p.CounterHelpTitleIndex) +} + +/* +https://msdn.microsoft.com/en-us/library/windows/desktop/aa373147(v=vs.85).aspx + +typedef struct _PERF_COUNTER_BLOCK { + DWORD ByteLength; +} PERF_COUNTER_BLOCK; +*/ + +type perfCounterBlock struct { + ByteLength uint32 +} + +func (p *perfCounterBlock) BinaryReadFrom(r io.Reader) error { + return binary.Read(r, bo, p) +} + +/* +https://msdn.microsoft.com/en-us/library/windows/desktop/aa373159(v=vs.85).aspx + +typedef struct _PERF_INSTANCE_DEFINITION { + DWORD ByteLength; + DWORD ParentObjectTitleIndex; + DWORD ParentObjectInstance; + DWORD UniqueID; + DWORD NameOffset; + DWORD NameLength; +} PERF_INSTANCE_DEFINITION; +*/ + +type perfInstanceDefinition struct { + ByteLength uint32 + ParentObjectTitleIndex uint32 + ParentObjectInstance uint32 + UniqueID uint32 + NameOffset uint32 + NameLength uint32 +} + +func (p *perfInstanceDefinition) BinaryReadFrom(r io.Reader) error { + return binary.Read(r, bo, p) +} diff --git a/vendor/github.com/leoluk/perflib_exporter/perflib/utf16.go b/vendor/github.com/leoluk/perflib_exporter/perflib/utf16.go new file mode 100644 index 000000000000..5aa5b433be59 --- /dev/null +++ b/vendor/github.com/leoluk/perflib_exporter/perflib/utf16.go @@ -0,0 +1,49 @@ +package perflib + +import ( + "io" + "encoding/binary" + "syscall" +) + +// Read an unterminated UTF16 string at a given position, specifying its length +func readUTF16StringAtPos(r io.ReadSeeker, absPos int64, length uint32) (string, error) { + value := make([]uint16, length/2) + _, err := r.Seek(absPos, io.SeekStart) + + if err != nil { + return "", err + } + + err = binary.Read(r, bo, value) + + if err != nil { + return "", err + } + + return syscall.UTF16ToString(value), nil +} + +// Reads a null-terminated UTF16 string at the current offset +func readUTF16String(r io.Reader) (string, error) { + var err error + + b := make([]byte, 2) + out := make([]uint16, 0, 100) + + for i := 0; err == nil; i += 2 { + _, err = r.Read(b) + + if b[0] == 0 && b[1] == 0 { + break + } + + out = append(out, bo.Uint16(b)) + } + + if err != nil { + return "", err + } + + return syscall.UTF16ToString(out), nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/LICENSE b/vendor/github.com/prometheus-community/windows_exporter/LICENSE new file mode 100644 index 000000000000..a5ff228e4e01 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Martin Lindhe + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/ad.go b/vendor/github.com/prometheus-community/windows_exporter/collector/ad.go new file mode 100644 index 000000000000..6a01944df044 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/ad.go @@ -0,0 +1,1314 @@ +// +build windows + +package collector + +import ( + "errors" + + "github.com/StackExchange/wmi" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +func init() { + registerCollector("ad", NewADCollector) +} + +// A ADCollector is a Prometheus collector for WMI Win32_PerfRawData_DirectoryServices_DirectoryServices metrics +type ADCollector struct { + AddressBookOperationsTotal *prometheus.Desc + AddressBookClientSessions *prometheus.Desc + ApproximateHighestDistinguishedNameTag *prometheus.Desc + AtqEstimatedDelaySeconds *prometheus.Desc + AtqOutstandingRequests *prometheus.Desc + AtqAverageRequestLatency *prometheus.Desc + AtqCurrentThreads *prometheus.Desc + SearchesTotal *prometheus.Desc + DatabaseOperationsTotal *prometheus.Desc + BindsTotal *prometheus.Desc + ReplicationHighestUsn *prometheus.Desc + IntersiteReplicationDataBytesTotal *prometheus.Desc + IntrasiteReplicationDataBytesTotal *prometheus.Desc + ReplicationInboundSyncObjectsRemaining *prometheus.Desc + ReplicationInboundLinkValueUpdatesRemaining *prometheus.Desc + ReplicationInboundObjectsUpdatedTotal *prometheus.Desc + ReplicationInboundObjectsFilteredTotal *prometheus.Desc + ReplicationInboundPropertiesUpdatedTotal *prometheus.Desc + ReplicationInboundPropertiesFilteredTotal *prometheus.Desc + ReplicationPendingOperations *prometheus.Desc + ReplicationPendingSynchronizations *prometheus.Desc + ReplicationSyncRequestsTotal *prometheus.Desc + ReplicationSyncRequestsSuccessTotal *prometheus.Desc + ReplicationSyncRequestsSchemaMismatchFailureTotal *prometheus.Desc + DirectoryOperationsTotal *prometheus.Desc + NameTranslationsTotal *prometheus.Desc + ChangeMonitorsRegistered *prometheus.Desc + ChangeMonitorUpdatesPending *prometheus.Desc + NameCacheHitsTotal *prometheus.Desc + NameCacheLookupsTotal *prometheus.Desc + DirectorySearchSuboperationsTotal *prometheus.Desc + SecurityDescriptorPropagationEventsTotal *prometheus.Desc + SecurityDescriptorPropagationEventsQueued *prometheus.Desc + SecurityDescriptorPropagationAccessWaitTotalSeconds *prometheus.Desc + SecurityDescriptorPropagationItemsQueuedTotal *prometheus.Desc + DirectoryServiceThreads *prometheus.Desc + LdapClosedConnectionsTotal *prometheus.Desc + LdapOpenedConnectionsTotal *prometheus.Desc + LdapActiveThreads *prometheus.Desc + LdapLastBindTimeSeconds *prometheus.Desc + LdapSearchesTotal *prometheus.Desc + LdapUdpOperationsTotal *prometheus.Desc + LdapWritesTotal *prometheus.Desc + LinkValuesCleanedTotal *prometheus.Desc + PhantomObjectsCleanedTotal *prometheus.Desc + PhantomObjectsVisitedTotal *prometheus.Desc + SamGroupMembershipEvaluationsTotal *prometheus.Desc + SamGroupMembershipGlobalCatalogEvaluationsTotal *prometheus.Desc + SamGroupMembershipEvaluationsNontransitiveTotal *prometheus.Desc + SamGroupMembershipEvaluationsTransitiveTotal *prometheus.Desc + SamGroupEvaluationLatency *prometheus.Desc + SamComputerCreationRequestsTotal *prometheus.Desc + SamComputerCreationSuccessfulRequestsTotal *prometheus.Desc + SamUserCreationRequestsTotal *prometheus.Desc + SamUserCreationSuccessfulRequestsTotal *prometheus.Desc + SamQueryDisplayRequestsTotal *prometheus.Desc + SamEnumerationsTotal *prometheus.Desc + SamMembershipChangesTotal *prometheus.Desc + SamPasswordChangesTotal *prometheus.Desc + TombstonedObjectsCollectedTotal *prometheus.Desc + TombstonedObjectsVisitedTotal *prometheus.Desc +} + +// NewADCollector ... +func NewADCollector() (Collector, error) { + const subsystem = "ad" + return &ADCollector{ + AddressBookOperationsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "address_book_operations_total"), + "", + []string{"operation"}, + nil, + ), + AddressBookClientSessions: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "address_book_client_sessions"), + "", + nil, + nil, + ), + ApproximateHighestDistinguishedNameTag: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "approximate_highest_distinguished_name_tag"), + "", + nil, + nil, + ), + AtqEstimatedDelaySeconds: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "atq_estimated_delay_seconds"), + "", + nil, + nil, + ), + AtqOutstandingRequests: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "atq_outstanding_requests"), + "", + nil, + nil, + ), + AtqAverageRequestLatency: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "atq_average_request_latency"), + "", + nil, + nil, + ), + AtqCurrentThreads: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "atq_current_threads"), + "", + []string{"service"}, + nil, + ), + SearchesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "searches_total"), + "", + []string{"scope"}, + nil, + ), + DatabaseOperationsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "database_operations_total"), + "", + []string{"operation"}, + nil, + ), + BindsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "binds_total"), + "", + []string{"bind_method"}, + nil, + ), + ReplicationHighestUsn: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "replication_highest_usn"), + "", + []string{"state"}, + nil, + ), + IntrasiteReplicationDataBytesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "replication_data_intrasite_bytes_total"), + "", + []string{"direction"}, + nil, + ), + IntersiteReplicationDataBytesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "replication_data_intersite_bytes_total"), + "", + []string{"direction"}, + nil, + ), + ReplicationInboundSyncObjectsRemaining: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "replication_inbound_sync_objects_remaining"), + "", + nil, + nil, + ), + ReplicationInboundLinkValueUpdatesRemaining: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "replication_inbound_link_value_updates_remaining"), + "", + nil, + nil, + ), + ReplicationInboundObjectsUpdatedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "replication_inbound_objects_updated_total"), + "", + nil, + nil, + ), + ReplicationInboundObjectsFilteredTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "replication_inbound_objects_filtered_total"), + "", + nil, + nil, + ), + ReplicationInboundPropertiesUpdatedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "replication_inbound_properties_updated_total"), + "", + nil, + nil, + ), + ReplicationInboundPropertiesFilteredTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "replication_inbound_properties_filtered_total"), + "", + nil, + nil, + ), + ReplicationPendingOperations: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "replication_pending_operations"), + "", + nil, + nil, + ), + ReplicationPendingSynchronizations: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "replication_pending_synchronizations"), + "", + nil, + nil, + ), + ReplicationSyncRequestsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "replication_sync_requests_total"), + "", + nil, + nil, + ), + ReplicationSyncRequestsSuccessTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "replication_sync_requests_success_total"), + "", + nil, + nil, + ), + ReplicationSyncRequestsSchemaMismatchFailureTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "replication_sync_requests_schema_mismatch_failure_total"), + "", + nil, + nil, + ), + NameTranslationsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "name_translations_total"), + "", + []string{"target_name"}, + nil, + ), + ChangeMonitorsRegistered: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "change_monitors_registered"), + "", + nil, + nil, + ), + ChangeMonitorUpdatesPending: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "change_monitor_updates_pending"), + "", + nil, + nil, + ), + NameCacheHitsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "name_cache_hits_total"), + "", + nil, + nil, + ), + NameCacheLookupsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "name_cache_lookups_total"), + "", + nil, + nil, + ), + DirectoryOperationsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "directory_operations_total"), + "", + []string{"operation", "origin"}, + nil, + ), + DirectorySearchSuboperationsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "directory_search_suboperations_total"), + "", + nil, + nil, + ), + SecurityDescriptorPropagationEventsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "security_descriptor_propagation_events_total"), + "", + nil, + nil, + ), + SecurityDescriptorPropagationEventsQueued: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "security_descriptor_propagation_events_queued"), + "", + nil, + nil, + ), + SecurityDescriptorPropagationAccessWaitTotalSeconds: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "security_descriptor_propagation_access_wait_total_seconds"), + "", + nil, + nil, + ), + SecurityDescriptorPropagationItemsQueuedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "security_descriptor_propagation_items_queued_total"), + "", + nil, + nil, + ), + DirectoryServiceThreads: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "directory_service_threads"), + "", + nil, + nil, + ), + LdapClosedConnectionsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "ldap_closed_connections_total"), + "", + nil, + nil, + ), + LdapOpenedConnectionsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "ldap_opened_connections_total"), + "", + []string{"type"}, + nil, + ), + LdapActiveThreads: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "ldap_active_threads"), + "", + nil, + nil, + ), + LdapLastBindTimeSeconds: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "ldap_last_bind_time_seconds"), + "", + nil, + nil, + ), + LdapSearchesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "ldap_searches_total"), + "", + nil, + nil, + ), + LdapUdpOperationsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "ldap_udp_operations_total"), + "", + nil, + nil, + ), + LdapWritesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "ldap_writes_total"), + "", + nil, + nil, + ), + LinkValuesCleanedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "link_values_cleaned_total"), + "", + nil, + nil, + ), + PhantomObjectsCleanedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "phantom_objects_cleaned_total"), + "", + nil, + nil, + ), + PhantomObjectsVisitedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "phantom_objects_visited_total"), + "", + nil, + nil, + ), + SamGroupMembershipEvaluationsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "sam_group_membership_evaluations_total"), + "", + []string{"group_type"}, + nil, + ), + SamGroupMembershipGlobalCatalogEvaluationsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "sam_group_membership_global_catalog_evaluations_total"), + "", + nil, + nil, + ), + SamGroupMembershipEvaluationsNontransitiveTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "sam_group_membership_evaluations_nontransitive_total"), + "", + nil, + nil, + ), + SamGroupMembershipEvaluationsTransitiveTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "sam_group_membership_evaluations_transitive_total"), + "", + nil, + nil, + ), + SamGroupEvaluationLatency: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "sam_group_evaluation_latency"), + "The mean latency of the last 100 group evaluations performed for authentication", + []string{"evaluation_type"}, + nil, + ), + SamComputerCreationRequestsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "sam_computer_creation_requests_total"), + "", + nil, + nil, + ), + SamComputerCreationSuccessfulRequestsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "sam_computer_creation_successful_requests_total"), + "", + nil, + nil, + ), + SamUserCreationRequestsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "sam_user_creation_requests_total"), + "", + nil, + nil, + ), + SamUserCreationSuccessfulRequestsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "sam_user_creation_successful_requests_total"), + "", + nil, + nil, + ), + SamQueryDisplayRequestsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "sam_query_display_requests_total"), + "", + nil, + nil, + ), + SamEnumerationsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "sam_enumerations_total"), + "", + nil, + nil, + ), + SamMembershipChangesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "sam_membership_changes_total"), + "", + nil, + nil, + ), + SamPasswordChangesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "sam_password_changes_total"), + "", + nil, + nil, + ), + TombstonedObjectsCollectedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "tombstoned_objects_collected_total"), + "", + nil, + nil, + ), + TombstonedObjectsVisitedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "tombstoned_objects_visited_total"), + "", + nil, + nil, + ), + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *ADCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + log.Error("failed collecting ad metrics:", desc, err) + return err + } + return nil +} + +// Win32_PerfRawData_DirectoryServices_DirectoryServices docs: +// - https://msdn.microsoft.com/en-us/library/ms803980.aspx +type Win32_PerfRawData_DirectoryServices_DirectoryServices struct { + Name string + + ABANRPersec uint32 + ABBrowsesPersec uint32 + ABClientSessions uint32 + ABMatchesPersec uint32 + ABPropertyReadsPersec uint32 + ABProxyLookupsPersec uint32 + ABSearchesPersec uint32 + ApproximatehighestDNT uint32 + ATQEstimatedQueueDelay uint32 + ATQOutstandingQueuedRequests uint32 + ATQRequestLatency uint32 + ATQThreadsLDAP uint32 + ATQThreadsOther uint32 + ATQThreadsTotal uint32 + BasesearchesPersec uint32 + DatabaseaddsPersec uint32 + DatabasedeletesPersec uint32 + DatabasemodifysPersec uint32 + DatabaserecyclesPersec uint32 + DigestBindsPersec uint32 + DRAHighestUSNCommittedHighpart uint64 + DRAHighestUSNCommittedLowpart uint64 + DRAHighestUSNIssuedHighpart uint64 + DRAHighestUSNIssuedLowpart uint64 + DRAInboundBytesCompressedBetweenSitesAfterCompressionPersec uint32 + DRAInboundBytesCompressedBetweenSitesAfterCompressionSinceBoot uint32 + DRAInboundBytesCompressedBetweenSitesBeforeCompressionPersec uint32 + DRAInboundBytesCompressedBetweenSitesBeforeCompressionSinceBoot uint32 + DRAInboundBytesNotCompressedWithinSitePersec uint32 + DRAInboundBytesNotCompressedWithinSiteSinceBoot uint32 + DRAInboundBytesTotalPersec uint32 + DRAInboundBytesTotalSinceBoot uint32 + DRAInboundFullSyncObjectsRemaining uint32 + DRAInboundLinkValueUpdatesRemaininginPacket uint32 + DRAInboundObjectsAppliedPersec uint32 + DRAInboundObjectsFilteredPersec uint32 + DRAInboundObjectsPersec uint32 + DRAInboundObjectUpdatesRemaininginPacket uint32 + DRAInboundPropertiesAppliedPersec uint32 + DRAInboundPropertiesFilteredPersec uint32 + DRAInboundPropertiesTotalPersec uint32 + DRAInboundTotalUpdatesRemaininginPacket uint32 + DRAInboundValuesDNsonlyPersec uint32 + DRAInboundValuesTotalPersec uint32 + DRAOutboundBytesCompressedBetweenSitesAfterCompressionPersec uint32 + DRAOutboundBytesCompressedBetweenSitesAfterCompressionSinceBoot uint32 + DRAOutboundBytesCompressedBetweenSitesBeforeCompressionPersec uint32 + DRAOutboundBytesCompressedBetweenSitesBeforeCompressionSinceBoot uint32 + DRAOutboundBytesNotCompressedWithinSitePersec uint32 + DRAOutboundBytesNotCompressedWithinSiteSinceBoot uint32 + DRAOutboundBytesTotalPersec uint32 + DRAOutboundBytesTotalSinceBoot uint32 + DRAOutboundObjectsFilteredPersec uint32 + DRAOutboundObjectsPersec uint32 + DRAOutboundPropertiesPersec uint32 + DRAOutboundValuesDNsonlyPersec uint32 + DRAOutboundValuesTotalPersec uint32 + DRAPendingReplicationOperations uint32 + DRAPendingReplicationSynchronizations uint32 + DRASyncFailuresonSchemaMismatch uint32 + DRASyncRequestsMade uint32 + DRASyncRequestsSuccessful uint32 + DRAThreadsGettingNCChanges uint32 + DRAThreadsGettingNCChangesHoldingSemaphore uint32 + DSClientBindsPersec uint32 + DSClientNameTranslationsPersec uint32 + DSDirectoryReadsPersec uint32 + DSDirectorySearchesPersec uint32 + DSDirectoryWritesPersec uint32 + DSMonitorListSize uint32 + DSNameCachehitrate uint32 + DSNameCachehitrate_Base uint32 + DSNotifyQueueSize uint32 + DSPercentReadsfromDRA uint32 + DSPercentReadsfromKCC uint32 + DSPercentReadsfromLSA uint32 + DSPercentReadsfromNSPI uint32 + DSPercentReadsfromNTDSAPI uint32 + DSPercentReadsfromSAM uint32 + DSPercentReadsOther uint32 + DSPercentSearchesfromDRA uint32 + DSPercentSearchesfromKCC uint32 + DSPercentSearchesfromLDAP uint32 + DSPercentSearchesfromLSA uint32 + DSPercentSearchesfromNSPI uint32 + DSPercentSearchesfromNTDSAPI uint32 + DSPercentSearchesfromSAM uint32 + DSPercentSearchesOther uint32 + DSPercentWritesfromDRA uint32 + DSPercentWritesfromKCC uint32 + DSPercentWritesfromLDAP uint32 + DSPercentWritesfromLSA uint32 + DSPercentWritesfromNSPI uint32 + DSPercentWritesfromNTDSAPI uint32 + DSPercentWritesfromSAM uint32 + DSPercentWritesOther uint32 + DSSearchsuboperationsPersec uint32 + DSSecurityDescriptorPropagationsEvents uint32 + DSSecurityDescriptorPropagatorAverageExclusionTime uint32 + DSSecurityDescriptorPropagatorRuntimeQueue uint32 + DSSecurityDescriptorsuboperationsPersec uint32 + DSServerBindsPersec uint32 + DSServerNameTranslationsPersec uint32 + DSThreadsinUse uint32 + ExternalBindsPersec uint32 + FastBindsPersec uint32 + LDAPActiveThreads uint32 + LDAPBindTime uint32 + LDAPClientSessions uint32 + LDAPClosedConnectionsPersec uint32 + LDAPNewConnectionsPersec uint32 + LDAPNewSSLConnectionsPersec uint32 + LDAPSearchesPersec uint32 + LDAPSuccessfulBindsPersec uint32 + LDAPUDPoperationsPersec uint32 + LDAPWritesPersec uint32 + LinkValuesCleanedPersec uint32 + NegotiatedBindsPersec uint32 + NTLMBindsPersec uint32 + OnelevelsearchesPersec uint32 + PhantomsCleanedPersec uint32 + PhantomsVisitedPersec uint32 + SAMAccountGroupEvaluationLatency uint32 + SAMDisplayInformationQueriesPersec uint32 + SAMDomainLocalGroupMembershipEvaluationsPersec uint32 + SAMEnumerationsPersec uint32 + SAMGCEvaluationsPersec uint32 + SAMGlobalGroupMembershipEvaluationsPersec uint32 + SAMMachineCreationAttemptsPersec uint32 + SAMMembershipChangesPersec uint32 + SAMNonTransitiveMembershipEvaluationsPersec uint32 + SAMPasswordChangesPersec uint32 + SAMResourceGroupEvaluationLatency uint32 + SAMSuccessfulComputerCreationsPersecIncludesallrequests uint32 + SAMSuccessfulUserCreationsPersec uint32 + SAMTransitiveMembershipEvaluationsPersec uint32 + SAMUniversalGroupMembershipEvaluationsPersec uint32 + SAMUserCreationAttemptsPersec uint32 + SimpleBindsPersec uint32 + SubtreesearchesPersec uint32 + TombstonesGarbageCollectedPersec uint32 + TombstonesVisitedPersec uint32 + Transitiveoperationsmillisecondsrun uint32 + TransitiveoperationsPersec uint32 + TransitivesuboperationsPersec uint32 +} + +func (c *ADCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_DirectoryServices_DirectoryServices + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + if len(dst) == 0 { + return nil, errors.New("WMI query returned empty result set") + } + + ch <- prometheus.MustNewConstMetric( + c.AddressBookOperationsTotal, + prometheus.CounterValue, + float64(dst[0].ABANRPersec), + "ambiguous_name_resolution", + ) + ch <- prometheus.MustNewConstMetric( + c.AddressBookOperationsTotal, + prometheus.CounterValue, + float64(dst[0].ABBrowsesPersec), + "browse", + ) + ch <- prometheus.MustNewConstMetric( + c.AddressBookOperationsTotal, + prometheus.CounterValue, + float64(dst[0].ABMatchesPersec), + "find", + ) + ch <- prometheus.MustNewConstMetric( + c.AddressBookOperationsTotal, + prometheus.CounterValue, + float64(dst[0].ABPropertyReadsPersec), + "property_read", + ) + ch <- prometheus.MustNewConstMetric( + c.AddressBookOperationsTotal, + prometheus.CounterValue, + float64(dst[0].ABSearchesPersec), + "search", + ) + ch <- prometheus.MustNewConstMetric( + c.AddressBookOperationsTotal, + prometheus.CounterValue, + float64(dst[0].ABProxyLookupsPersec), + "proxy_search", + ) + + ch <- prometheus.MustNewConstMetric( + c.AddressBookClientSessions, + prometheus.GaugeValue, + float64(dst[0].ABClientSessions), + ) + + ch <- prometheus.MustNewConstMetric( + c.ApproximateHighestDistinguishedNameTag, + prometheus.GaugeValue, + float64(dst[0].ApproximatehighestDNT), + ) + + ch <- prometheus.MustNewConstMetric( + c.AtqEstimatedDelaySeconds, + prometheus.GaugeValue, + float64(dst[0].ATQEstimatedQueueDelay)/1000, + ) + ch <- prometheus.MustNewConstMetric( + c.AtqOutstandingRequests, + prometheus.GaugeValue, + float64(dst[0].ATQOutstandingQueuedRequests), + ) + ch <- prometheus.MustNewConstMetric( + c.AtqAverageRequestLatency, + prometheus.GaugeValue, + float64(dst[0].ATQRequestLatency), + ) + ch <- prometheus.MustNewConstMetric( + c.AtqCurrentThreads, + prometheus.GaugeValue, + float64(dst[0].ATQThreadsLDAP), + "ldap", + ) + ch <- prometheus.MustNewConstMetric( + c.AtqCurrentThreads, + prometheus.GaugeValue, + float64(dst[0].ATQThreadsOther), + "other", + ) + + ch <- prometheus.MustNewConstMetric( + c.SearchesTotal, + prometheus.CounterValue, + float64(dst[0].BasesearchesPersec), + "base", + ) + ch <- prometheus.MustNewConstMetric( + c.SearchesTotal, + prometheus.CounterValue, + float64(dst[0].SubtreesearchesPersec), + "subtree", + ) + ch <- prometheus.MustNewConstMetric( + c.SearchesTotal, + prometheus.CounterValue, + float64(dst[0].OnelevelsearchesPersec), + "one_level", + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabaseOperationsTotal, + prometheus.CounterValue, + float64(dst[0].DatabaseaddsPersec), + "add", + ) + ch <- prometheus.MustNewConstMetric( + c.DatabaseOperationsTotal, + prometheus.CounterValue, + float64(dst[0].DatabasedeletesPersec), + "delete", + ) + ch <- prometheus.MustNewConstMetric( + c.DatabaseOperationsTotal, + prometheus.CounterValue, + float64(dst[0].DatabasemodifysPersec), + "modify", + ) + ch <- prometheus.MustNewConstMetric( + c.DatabaseOperationsTotal, + prometheus.CounterValue, + float64(dst[0].DatabaserecyclesPersec), + "recycle", + ) + + ch <- prometheus.MustNewConstMetric( + c.BindsTotal, + prometheus.CounterValue, + float64(dst[0].DigestBindsPersec), + "digest", + ) + ch <- prometheus.MustNewConstMetric( + c.BindsTotal, + prometheus.CounterValue, + float64(dst[0].DSClientBindsPersec), + "ds_client", + ) + ch <- prometheus.MustNewConstMetric( + c.BindsTotal, + prometheus.CounterValue, + float64(dst[0].DSServerBindsPersec), + "ds_server", + ) + ch <- prometheus.MustNewConstMetric( + c.BindsTotal, + prometheus.CounterValue, + float64(dst[0].ExternalBindsPersec), + "external", + ) + ch <- prometheus.MustNewConstMetric( + c.BindsTotal, + prometheus.CounterValue, + float64(dst[0].FastBindsPersec), + "fast", + ) + ch <- prometheus.MustNewConstMetric( + c.BindsTotal, + prometheus.CounterValue, + float64(dst[0].NegotiatedBindsPersec), + "negotiate", + ) + ch <- prometheus.MustNewConstMetric( + c.BindsTotal, + prometheus.CounterValue, + float64(dst[0].NTLMBindsPersec), + "ntlm", + ) + ch <- prometheus.MustNewConstMetric( + c.BindsTotal, + prometheus.CounterValue, + float64(dst[0].SimpleBindsPersec), + "simple", + ) + ch <- prometheus.MustNewConstMetric( + c.BindsTotal, + prometheus.CounterValue, + float64(dst[0].LDAPSuccessfulBindsPersec), + "ldap", + ) + + ch <- prometheus.MustNewConstMetric( + c.ReplicationHighestUsn, + prometheus.CounterValue, + float64(dst[0].DRAHighestUSNCommittedHighpart<<32)+float64(dst[0].DRAHighestUSNCommittedLowpart), + "committed", + ) + ch <- prometheus.MustNewConstMetric( + c.ReplicationHighestUsn, + prometheus.CounterValue, + float64(dst[0].DRAHighestUSNIssuedHighpart<<32)+float64(dst[0].DRAHighestUSNIssuedLowpart), + "issued", + ) + + ch <- prometheus.MustNewConstMetric( + c.IntersiteReplicationDataBytesTotal, + prometheus.CounterValue, + float64(dst[0].DRAInboundBytesCompressedBetweenSitesAfterCompressionPersec), + "inbound", + ) + // The pre-compression data size seems to have little value? Skipping for now + // ch <- prometheus.MustNewConstMetric( + // c.IntersiteReplicationDataBytesTotal, + // prometheus.CounterValue, + // float64(dst[0].DRAInboundBytesCompressedBetweenSitesBeforeCompressionPersec), + // "inbound", + // ) + ch <- prometheus.MustNewConstMetric( + c.IntersiteReplicationDataBytesTotal, + prometheus.CounterValue, + float64(dst[0].DRAOutboundBytesCompressedBetweenSitesAfterCompressionPersec), + "outbound", + ) + // ch <- prometheus.MustNewConstMetric( + // c.IntersiteReplicationDataBytesTotal, + // prometheus.CounterValue, + // float64(dst[0].DRAOutboundBytesCompressedBetweenSitesBeforeCompressionPersec), + // "outbound", + // ) + ch <- prometheus.MustNewConstMetric( + c.IntrasiteReplicationDataBytesTotal, + prometheus.CounterValue, + float64(dst[0].DRAInboundBytesNotCompressedWithinSitePersec), + "inbound", + ) + ch <- prometheus.MustNewConstMetric( + c.IntrasiteReplicationDataBytesTotal, + prometheus.CounterValue, + float64(dst[0].DRAOutboundBytesNotCompressedWithinSitePersec), + "outbound", + ) + + ch <- prometheus.MustNewConstMetric( + c.ReplicationInboundSyncObjectsRemaining, + prometheus.GaugeValue, + float64(dst[0].DRAInboundFullSyncObjectsRemaining), + ) + + ch <- prometheus.MustNewConstMetric( + c.ReplicationInboundLinkValueUpdatesRemaining, + prometheus.GaugeValue, + float64(dst[0].DRAInboundLinkValueUpdatesRemaininginPacket), + ) + + ch <- prometheus.MustNewConstMetric( + c.ReplicationInboundObjectsUpdatedTotal, + prometheus.CounterValue, + float64(dst[0].DRAInboundObjectsAppliedPersec), + ) + ch <- prometheus.MustNewConstMetric( + c.ReplicationInboundObjectsFilteredTotal, + prometheus.CounterValue, + float64(dst[0].DRAInboundObjectsFilteredPersec), + ) + + ch <- prometheus.MustNewConstMetric( + c.ReplicationInboundPropertiesUpdatedTotal, + prometheus.CounterValue, + float64(dst[0].DRAInboundPropertiesAppliedPersec), + ) + ch <- prometheus.MustNewConstMetric( + c.ReplicationInboundPropertiesFilteredTotal, + prometheus.CounterValue, + float64(dst[0].DRAInboundPropertiesFilteredPersec), + ) + + ch <- prometheus.MustNewConstMetric( + c.ReplicationPendingOperations, + prometheus.GaugeValue, + float64(dst[0].DRAPendingReplicationOperations), + ) + ch <- prometheus.MustNewConstMetric( + c.ReplicationPendingSynchronizations, + prometheus.GaugeValue, + float64(dst[0].DRAPendingReplicationSynchronizations), + ) + + ch <- prometheus.MustNewConstMetric( + c.ReplicationSyncRequestsTotal, + prometheus.CounterValue, + float64(dst[0].DRASyncRequestsMade), + ) + ch <- prometheus.MustNewConstMetric( + c.ReplicationSyncRequestsSuccessTotal, + prometheus.CounterValue, + float64(dst[0].DRASyncRequestsSuccessful), + ) + ch <- prometheus.MustNewConstMetric( + c.ReplicationSyncRequestsSchemaMismatchFailureTotal, + prometheus.CounterValue, + float64(dst[0].DRASyncFailuresonSchemaMismatch), + ) + + ch <- prometheus.MustNewConstMetric( + c.NameTranslationsTotal, + prometheus.CounterValue, + float64(dst[0].DSClientNameTranslationsPersec), + "client", + ) + ch <- prometheus.MustNewConstMetric( + c.NameTranslationsTotal, + prometheus.CounterValue, + float64(dst[0].DSServerNameTranslationsPersec), + "server", + ) + + ch <- prometheus.MustNewConstMetric( + c.ChangeMonitorsRegistered, + prometheus.GaugeValue, + float64(dst[0].DSMonitorListSize), + ) + ch <- prometheus.MustNewConstMetric( + c.ChangeMonitorUpdatesPending, + prometheus.GaugeValue, + float64(dst[0].DSNotifyQueueSize), + ) + + ch <- prometheus.MustNewConstMetric( + c.NameCacheHitsTotal, + prometheus.CounterValue, + float64(dst[0].DSNameCachehitrate), + ) + ch <- prometheus.MustNewConstMetric( + c.NameCacheLookupsTotal, + prometheus.CounterValue, + float64(dst[0].DSNameCachehitrate_Base), + ) + + ch <- prometheus.MustNewConstMetric( + c.DirectoryOperationsTotal, + prometheus.CounterValue, + float64(dst[0].DSPercentReadsfromDRA), + "read", + "replication_agent", + ) + ch <- prometheus.MustNewConstMetric( + c.DirectoryOperationsTotal, + prometheus.CounterValue, + float64(dst[0].DSPercentReadsfromKCC), + "read", + "knowledge_consistency_checker", + ) + ch <- prometheus.MustNewConstMetric( + c.DirectoryOperationsTotal, + prometheus.CounterValue, + float64(dst[0].DSPercentReadsfromLSA), + "read", + "local_security_authority", + ) + ch <- prometheus.MustNewConstMetric( + c.DirectoryOperationsTotal, + prometheus.CounterValue, + float64(dst[0].DSPercentReadsfromNSPI), + "read", + "name_service_provider_interface", + ) + ch <- prometheus.MustNewConstMetric( + c.DirectoryOperationsTotal, + prometheus.CounterValue, + float64(dst[0].DSPercentReadsfromNTDSAPI), + "read", + "directory_service_api", + ) + ch <- prometheus.MustNewConstMetric( + c.DirectoryOperationsTotal, + prometheus.CounterValue, + float64(dst[0].DSPercentReadsfromSAM), + "read", + "security_account_manager", + ) + ch <- prometheus.MustNewConstMetric( + c.DirectoryOperationsTotal, + prometheus.CounterValue, + float64(dst[0].DSPercentReadsOther), + "read", + "other", + ) + ch <- prometheus.MustNewConstMetric( + c.DirectoryOperationsTotal, + prometheus.CounterValue, + float64(dst[0].DSPercentSearchesfromDRA), + "search", + "replication_agent", + ) + ch <- prometheus.MustNewConstMetric( + c.DirectoryOperationsTotal, + prometheus.CounterValue, + float64(dst[0].DSPercentSearchesfromKCC), + "search", + "knowledge_consistency_checker", + ) + ch <- prometheus.MustNewConstMetric( + c.DirectoryOperationsTotal, + prometheus.CounterValue, + float64(dst[0].DSPercentSearchesfromLDAP), + "search", + "ldap", + ) + ch <- prometheus.MustNewConstMetric( + c.DirectoryOperationsTotal, + prometheus.CounterValue, + float64(dst[0].DSPercentSearchesfromLSA), + "search", + "local_security_authority", + ) + ch <- prometheus.MustNewConstMetric( + c.DirectoryOperationsTotal, + prometheus.CounterValue, + float64(dst[0].DSPercentSearchesfromNSPI), + "search", + "name_service_provider_interface", + ) + ch <- prometheus.MustNewConstMetric( + c.DirectoryOperationsTotal, + prometheus.CounterValue, + float64(dst[0].DSPercentSearchesfromNTDSAPI), + "search", + "directory_service_api", + ) + ch <- prometheus.MustNewConstMetric( + c.DirectoryOperationsTotal, + prometheus.CounterValue, + float64(dst[0].DSPercentSearchesfromSAM), + "search", + "security_account_manager", + ) + ch <- prometheus.MustNewConstMetric( + c.DirectoryOperationsTotal, + prometheus.CounterValue, + float64(dst[0].DSPercentSearchesOther), + "search", + "other", + ) + ch <- prometheus.MustNewConstMetric( + c.DirectoryOperationsTotal, + prometheus.CounterValue, + float64(dst[0].DSPercentWritesfromDRA), + "write", + "replication_agent", + ) + ch <- prometheus.MustNewConstMetric( + c.DirectoryOperationsTotal, + prometheus.CounterValue, + float64(dst[0].DSPercentWritesfromKCC), + "write", + "knowledge_consistency_checker", + ) + ch <- prometheus.MustNewConstMetric( + c.DirectoryOperationsTotal, + prometheus.CounterValue, + float64(dst[0].DSPercentWritesfromLDAP), + "write", + "ldap", + ) + ch <- prometheus.MustNewConstMetric( + c.DirectoryOperationsTotal, + prometheus.CounterValue, + float64(dst[0].DSPercentWritesfromLSA), + "write", + "local_security_authority", + ) + ch <- prometheus.MustNewConstMetric( + c.DirectoryOperationsTotal, + prometheus.CounterValue, + float64(dst[0].DSPercentWritesfromNSPI), + "write", + "name_service_provider_interface", + ) + ch <- prometheus.MustNewConstMetric( + c.DirectoryOperationsTotal, + prometheus.CounterValue, + float64(dst[0].DSPercentWritesfromNTDSAPI), + "write", + "directory_service_api", + ) + ch <- prometheus.MustNewConstMetric( + c.DirectoryOperationsTotal, + prometheus.CounterValue, + float64(dst[0].DSPercentWritesfromSAM), + "write", + "security_account_manager", + ) + ch <- prometheus.MustNewConstMetric( + c.DirectoryOperationsTotal, + prometheus.CounterValue, + float64(dst[0].DSPercentWritesOther), + "write", + "other", + ) + + ch <- prometheus.MustNewConstMetric( + c.DirectorySearchSuboperationsTotal, + prometheus.CounterValue, + float64(dst[0].DSSearchsuboperationsPersec), + ) + + ch <- prometheus.MustNewConstMetric( + c.SecurityDescriptorPropagationEventsTotal, + prometheus.CounterValue, + float64(dst[0].DSSecurityDescriptorsuboperationsPersec), + ) + ch <- prometheus.MustNewConstMetric( + c.SecurityDescriptorPropagationEventsQueued, + prometheus.GaugeValue, + float64(dst[0].DSSecurityDescriptorPropagationsEvents), + ) + ch <- prometheus.MustNewConstMetric( + c.SecurityDescriptorPropagationAccessWaitTotalSeconds, + prometheus.GaugeValue, + float64(dst[0].DSSecurityDescriptorPropagatorAverageExclusionTime), + ) + ch <- prometheus.MustNewConstMetric( + c.SecurityDescriptorPropagationItemsQueuedTotal, + prometheus.CounterValue, + float64(dst[0].DSSecurityDescriptorPropagatorRuntimeQueue), + ) + + ch <- prometheus.MustNewConstMetric( + c.DirectoryServiceThreads, + prometheus.GaugeValue, + float64(dst[0].DSThreadsinUse), + ) + + ch <- prometheus.MustNewConstMetric( + c.LdapClosedConnectionsTotal, + prometheus.CounterValue, + float64(dst[0].LDAPClosedConnectionsPersec), + ) + ch <- prometheus.MustNewConstMetric( + c.LdapOpenedConnectionsTotal, + prometheus.CounterValue, + float64(dst[0].LDAPNewConnectionsPersec), + "ldap", + ) + ch <- prometheus.MustNewConstMetric( + c.LdapOpenedConnectionsTotal, + prometheus.CounterValue, + float64(dst[0].LDAPNewSSLConnectionsPersec), + "ldaps", + ) + + ch <- prometheus.MustNewConstMetric( + c.LdapActiveThreads, + prometheus.GaugeValue, + float64(dst[0].LDAPActiveThreads), + ) + + ch <- prometheus.MustNewConstMetric( + c.LdapLastBindTimeSeconds, + prometheus.GaugeValue, + float64(dst[0].LDAPBindTime)/1000, + ) + + ch <- prometheus.MustNewConstMetric( + c.LdapSearchesTotal, + prometheus.CounterValue, + float64(dst[0].LDAPSearchesPersec), + ) + + ch <- prometheus.MustNewConstMetric( + c.LdapUdpOperationsTotal, + prometheus.CounterValue, + float64(dst[0].LDAPUDPoperationsPersec), + ) + ch <- prometheus.MustNewConstMetric( + c.LdapWritesTotal, + prometheus.CounterValue, + float64(dst[0].LDAPWritesPersec), + ) + + ch <- prometheus.MustNewConstMetric( + c.LinkValuesCleanedTotal, + prometheus.CounterValue, + float64(dst[0].LinkValuesCleanedPersec), + ) + + ch <- prometheus.MustNewConstMetric( + c.PhantomObjectsCleanedTotal, + prometheus.CounterValue, + float64(dst[0].PhantomsCleanedPersec), + ) + ch <- prometheus.MustNewConstMetric( + c.PhantomObjectsVisitedTotal, + prometheus.CounterValue, + float64(dst[0].PhantomsVisitedPersec), + ) + + ch <- prometheus.MustNewConstMetric( + c.SamGroupMembershipEvaluationsTotal, + prometheus.CounterValue, + float64(dst[0].SAMGlobalGroupMembershipEvaluationsPersec), + "global", + ) + ch <- prometheus.MustNewConstMetric( + c.SamGroupMembershipEvaluationsTotal, + prometheus.CounterValue, + float64(dst[0].SAMDomainLocalGroupMembershipEvaluationsPersec), + "domain_local", + ) + ch <- prometheus.MustNewConstMetric( + c.SamGroupMembershipEvaluationsTotal, + prometheus.CounterValue, + float64(dst[0].SAMUniversalGroupMembershipEvaluationsPersec), + "universal", + ) + ch <- prometheus.MustNewConstMetric( + c.SamGroupMembershipGlobalCatalogEvaluationsTotal, + prometheus.CounterValue, + float64(dst[0].SAMGCEvaluationsPersec), + ) + + ch <- prometheus.MustNewConstMetric( + c.SamGroupMembershipEvaluationsNontransitiveTotal, + prometheus.CounterValue, + float64(dst[0].SAMNonTransitiveMembershipEvaluationsPersec), + ) + ch <- prometheus.MustNewConstMetric( + c.SamGroupMembershipEvaluationsTransitiveTotal, + prometheus.CounterValue, + float64(dst[0].SAMTransitiveMembershipEvaluationsPersec), + ) + + ch <- prometheus.MustNewConstMetric( + c.SamGroupEvaluationLatency, + prometheus.GaugeValue, + float64(dst[0].SAMAccountGroupEvaluationLatency), + "account_group", + ) + ch <- prometheus.MustNewConstMetric( + c.SamGroupEvaluationLatency, + prometheus.GaugeValue, + float64(dst[0].SAMResourceGroupEvaluationLatency), + "resource_group", + ) + + ch <- prometheus.MustNewConstMetric( + c.SamComputerCreationRequestsTotal, + prometheus.CounterValue, + float64(dst[0].SAMSuccessfulComputerCreationsPersecIncludesallrequests), + ) + ch <- prometheus.MustNewConstMetric( + c.SamComputerCreationSuccessfulRequestsTotal, + prometheus.CounterValue, + float64(dst[0].SAMMachineCreationAttemptsPersec), + ) + + ch <- prometheus.MustNewConstMetric( + c.SamUserCreationRequestsTotal, + prometheus.CounterValue, + float64(dst[0].SAMUserCreationAttemptsPersec), + ) + ch <- prometheus.MustNewConstMetric( + c.SamUserCreationSuccessfulRequestsTotal, + prometheus.CounterValue, + float64(dst[0].SAMSuccessfulUserCreationsPersec), + ) + + ch <- prometheus.MustNewConstMetric( + c.SamQueryDisplayRequestsTotal, + prometheus.CounterValue, + float64(dst[0].SAMDisplayInformationQueriesPersec), + ) + ch <- prometheus.MustNewConstMetric( + c.SamEnumerationsTotal, + prometheus.CounterValue, + float64(dst[0].SAMEnumerationsPersec), + ) + + ch <- prometheus.MustNewConstMetric( + c.SamMembershipChangesTotal, + prometheus.CounterValue, + float64(dst[0].SAMMembershipChangesPersec), + ) + + ch <- prometheus.MustNewConstMetric( + c.SamPasswordChangesTotal, + prometheus.CounterValue, + float64(dst[0].SAMPasswordChangesPersec), + ) + + ch <- prometheus.MustNewConstMetric( + c.TombstonedObjectsCollectedTotal, + prometheus.CounterValue, + float64(dst[0].TombstonesGarbageCollectedPersec), + ) + ch <- prometheus.MustNewConstMetric( + c.TombstonedObjectsVisitedTotal, + prometheus.CounterValue, + float64(dst[0].TombstonesVisitedPersec), + ) + + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/adfs.go b/vendor/github.com/prometheus-community/windows_exporter/collector/adfs.go new file mode 100644 index 000000000000..9357b8b17eef --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/adfs.go @@ -0,0 +1,188 @@ +// +build windows + +package collector + +import ( + "github.com/prometheus/client_golang/prometheus" +) + +func init() { + registerCollector("adfs", newADFSCollector, "AD FS") +} + +type adfsCollector struct { + adLoginConnectionFailures *prometheus.Desc + certificateAuthentications *prometheus.Desc + deviceAuthentications *prometheus.Desc + extranetAccountLockouts *prometheus.Desc + federatedAuthentications *prometheus.Desc + passportAuthentications *prometheus.Desc + passiveRequests *prometheus.Desc + passwordChangeFailed *prometheus.Desc + passwordChangeSucceeded *prometheus.Desc + tokenRequests *prometheus.Desc + windowsIntegratedAuthentications *prometheus.Desc +} + +// newADFSCollector constructs a new adfsCollector +func newADFSCollector() (Collector, error) { + const subsystem = "adfs" + + return &adfsCollector{ + adLoginConnectionFailures: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "ad_login_connection_failures_total"), + "Total number of connection failures to an Active Directory domain controller", + nil, + nil, + ), + certificateAuthentications: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "certificate_authentications_total"), + "Total number of User Certificate authentications", + nil, + nil, + ), + deviceAuthentications: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "device_authentications_total"), + "Total number of Device authentications", + nil, + nil, + ), + extranetAccountLockouts: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "extranet_account_lockouts_total"), + "Total number of Extranet Account Lockouts", + nil, + nil, + ), + federatedAuthentications: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "federated_authentications_total"), + "Total number of authentications from a federated source", + nil, + nil, + ), + passportAuthentications: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "passport_authentications_total"), + "Total number of Microsoft Passport SSO authentications", + nil, + nil, + ), + passiveRequests: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "passive_requests_total"), + "Total number of passive (browser-based) requests", + nil, + nil, + ), + passwordChangeFailed: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "password_change_failed_total"), + "Total number of failed password changes", + nil, + nil, + ), + passwordChangeSucceeded: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "password_change_succeeded_total"), + "Total number of successful password changes", + nil, + nil, + ), + tokenRequests: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "token_requests_total"), + "Total number of token requests", + nil, + nil, + ), + windowsIntegratedAuthentications: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "windows_integrated_authentications_total"), + "Total number of Windows integrated authentications (Kerberos/NTLM)", + nil, + nil, + ), + }, nil +} + +type perflibADFS struct { + AdLoginConnectionFailures float64 `perflib:"AD login Connection Failures"` + CertificateAuthentications float64 `perflib:"Certificate Authentications"` + DeviceAuthentications float64 `perflib:"Device Authentications"` + ExtranetAccountLockouts float64 `perflib:"Extranet Account Lockouts"` + FederatedAuthentications float64 `perflib:"Federated Authentications"` + PassportAuthentications float64 `perflib:"Microsoft Passport Authentications"` + PassiveRequests float64 `perflib:"Passive Requests"` + PasswordChangeFailed float64 `perflib:"Password Change Failed Requests"` + PasswordChangeSucceeded float64 `perflib:"Password Change Successful Requests"` + TokenRequests float64 `perflib:"Token Requests"` + WindowsIntegratedAuthentications float64 `perflib:"Windows Integrated Authentications"` +} + +func (c *adfsCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + var adfsData []perflibADFS + err := unmarshalObject(ctx.perfObjects["AD FS"], &adfsData) + if err != nil { + return err + } + + ch <- prometheus.MustNewConstMetric( + c.adLoginConnectionFailures, + prometheus.CounterValue, + adfsData[0].AdLoginConnectionFailures, + ) + + ch <- prometheus.MustNewConstMetric( + c.certificateAuthentications, + prometheus.CounterValue, + adfsData[0].CertificateAuthentications, + ) + + ch <- prometheus.MustNewConstMetric( + c.deviceAuthentications, + prometheus.CounterValue, + adfsData[0].DeviceAuthentications, + ) + + ch <- prometheus.MustNewConstMetric( + c.extranetAccountLockouts, + prometheus.CounterValue, + adfsData[0].ExtranetAccountLockouts, + ) + + ch <- prometheus.MustNewConstMetric( + c.federatedAuthentications, + prometheus.CounterValue, + adfsData[0].FederatedAuthentications, + ) + + ch <- prometheus.MustNewConstMetric( + c.passportAuthentications, + prometheus.CounterValue, + adfsData[0].PassportAuthentications, + ) + + ch <- prometheus.MustNewConstMetric( + c.passiveRequests, + prometheus.CounterValue, + adfsData[0].PassiveRequests, + ) + + ch <- prometheus.MustNewConstMetric( + c.passwordChangeFailed, + prometheus.CounterValue, + adfsData[0].PasswordChangeFailed, + ) + + ch <- prometheus.MustNewConstMetric( + c.passwordChangeSucceeded, + prometheus.CounterValue, + adfsData[0].PasswordChangeSucceeded, + ) + + ch <- prometheus.MustNewConstMetric( + c.tokenRequests, + prometheus.CounterValue, + adfsData[0].TokenRequests, + ) + + ch <- prometheus.MustNewConstMetric( + c.windowsIntegratedAuthentications, + prometheus.CounterValue, + adfsData[0].WindowsIntegratedAuthentications, + ) + return nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/collector.go b/vendor/github.com/prometheus-community/windows_exporter/collector/collector.go new file mode 100644 index 000000000000..a55548b23472 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/collector.go @@ -0,0 +1,180 @@ +package collector + +import ( + "fmt" + "sort" + "strconv" + "strings" + + "gopkg.in/alecthomas/kingpin.v2" + + "github.com/leoluk/perflib_exporter/perflib" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" + "golang.org/x/sys/windows/registry" +) + +// ... +const ( + // TODO: Make package-local + Namespace = "windows" + + // Conversion factors + ticksToSecondsScaleFactor = 1 / 1e7 + windowsEpoch = 116444736000000000 +) + +// getWindowsVersion reads the version number of the OS from the Registry +// See https://docs.microsoft.com/en-us/windows/desktop/sysinfo/operating-system-version +func getWindowsVersion() float64 { + k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE) + if err != nil { + log.Warn("Couldn't open registry", err) + return 0 + } + defer func() { + err = k.Close() + if err != nil { + log.Warnf("Failed to close registry key: %v", err) + } + }() + + currentv, _, err := k.GetStringValue("CurrentVersion") + if err != nil { + log.Warn("Couldn't open registry to determine current Windows version:", err) + return 0 + } + + currentv_flt, err := strconv.ParseFloat(currentv, 64) + + log.Debugf("Detected Windows version %f\n", currentv_flt) + + return currentv_flt +} + +type Config interface { + RegisterKingpin(ka *kingpin.Application) + Build() (Collector, error) +} + +type configBuilder func() Config +type collectorBuilder func() (Collector, error) + +var ( + builders = make(map[string]collectorBuilder) + perfCounterDependencies = make(map[string]string) + configBuilders = make(map[string]configBuilder) +) + +func registerCollector(name string, builder collectorBuilder, perfCounterNames ...string) { + builders[name] = builder + addPerfCounterDependencies(name, perfCounterNames) +} + +func registerCollectorWithConfig(name string, config configBuilder, perfCounterNames ...string) { + configBuilders[name] = config + addPerfCounterDependencies(name, perfCounterNames) +} + +func addPerfCounterDependencies(name string, perfCounterNames []string) { + perfIndicies := make([]string, 0, len(perfCounterNames)) + for _, cn := range perfCounterNames { + perfIndicies = append(perfIndicies, MapCounterToIndex(cn)) + } + perfCounterDependencies[name] = strings.Join(perfIndicies, " ") +} + +func Available() []string { + cs := make([]string, 0, len(builders)+len(configBuilders)) + for c := range builders { + cs = append(cs, c) + } + for c := range configBuilders { + cs = append(cs, c) + } + return cs +} + +func Build(collector string) (Collector, error) { + builder, exists := builders[collector] + if !exists { + return nil, fmt.Errorf("Unknown collector %q", collector) + } + return builder() +} + +func getPerfQuery(collectors []string) string { + parts := make([]string, 0, len(collectors)) + for _, c := range collectors { + if p := perfCounterDependencies[c]; p != "" { + parts = append(parts, p) + } + } + return strings.Join(parts, " ") +} + +// Collector is the interface a collector has to implement. +type Collector interface { + // Get new metrics and expose them via prometheus registry. + Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (err error) +} + +type ScrapeContext struct { + perfObjects map[string]*perflib.PerfObject +} + +// PrepareScrapeContext creates a ScrapeContext to be used during a single scrape +func PrepareScrapeContext(collectors []string) (*ScrapeContext, error) { + q := getPerfQuery(collectors) // TODO: Memoize + objs, err := getPerflibSnapshot(q) + if err != nil { + return nil, err + } + + return &ScrapeContext{objs}, nil +} + +func boolToFloat(b bool) float64 { + if b { + return 1.0 + } + return 0.0 +} + +func find(slice []string, val string) bool { + for _, item := range slice { + if item == val { + return true + } + } + return false +} + +// Used by more complex collectors where user input specifies enabled child collectors. +// Splits provided child collectors and deduplicate. +func expandEnabledChildCollectors(enabled string) []string { + separated := strings.Split(enabled, ",") + unique := map[string]bool{} + for _, s := range separated { + if s != "" { + unique[s] = true + } + } + result := make([]string, 0, len(unique)) + for s := range unique { + result = append(result, s) + } + // Ensure result is ordered, to prevent test failure + sort.Strings(result) + return result +} + +func GenerateConfigs(ka *kingpin.Application) map[string]Config { + cm := make(map[string]Config, len(configBuilders)) + for k, v := range configBuilders { + c := v() + c.RegisterKingpin(ka) + cm[k] = c + } + return cm +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/container.go b/vendor/github.com/prometheus-community/windows_exporter/collector/container.go new file mode 100644 index 000000000000..8d2ef1926280 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/container.go @@ -0,0 +1,282 @@ +// +build windows + +package collector + +import ( + "github.com/Microsoft/hcsshim" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +func init() { + registerCollector("container", NewContainerMetricsCollector) +} + +// A ContainerMetricsCollector is a Prometheus collector for containers metrics +type ContainerMetricsCollector struct { + // Presence + ContainerAvailable *prometheus.Desc + + // Number of containers + ContainersCount *prometheus.Desc + // memory + UsageCommitBytes *prometheus.Desc + UsageCommitPeakBytes *prometheus.Desc + UsagePrivateWorkingSetBytes *prometheus.Desc + + // CPU + RuntimeTotal *prometheus.Desc + RuntimeUser *prometheus.Desc + RuntimeKernel *prometheus.Desc + + // Network + BytesReceived *prometheus.Desc + BytesSent *prometheus.Desc + PacketsReceived *prometheus.Desc + PacketsSent *prometheus.Desc + DroppedPacketsIncoming *prometheus.Desc + DroppedPacketsOutgoing *prometheus.Desc +} + +// NewContainerMetricsCollector constructs a new ContainerMetricsCollector +func NewContainerMetricsCollector() (Collector, error) { + const subsystem = "container" + return &ContainerMetricsCollector{ + ContainerAvailable: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "available"), + "Available", + []string{"container_id"}, + nil, + ), + ContainersCount: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "count"), + "Number of containers", + nil, + nil, + ), + UsageCommitBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "memory_usage_commit_bytes"), + "Memory Usage Commit Bytes", + []string{"container_id"}, + nil, + ), + UsageCommitPeakBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "memory_usage_commit_peak_bytes"), + "Memory Usage Commit Peak Bytes", + []string{"container_id"}, + nil, + ), + UsagePrivateWorkingSetBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "memory_usage_private_working_set_bytes"), + "Memory Usage Private Working Set Bytes", + []string{"container_id"}, + nil, + ), + RuntimeTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "cpu_usage_seconds_total"), + "Total Run time in Seconds", + []string{"container_id"}, + nil, + ), + RuntimeUser: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "cpu_usage_seconds_usermode"), + "Run Time in User mode in Seconds", + []string{"container_id"}, + nil, + ), + RuntimeKernel: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "cpu_usage_seconds_kernelmode"), + "Run time in Kernel mode in Seconds", + []string{"container_id"}, + nil, + ), + BytesReceived: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "network_receive_bytes_total"), + "Bytes Received on Interface", + []string{"container_id", "interface"}, + nil, + ), + BytesSent: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "network_transmit_bytes_total"), + "Bytes Sent on Interface", + []string{"container_id", "interface"}, + nil, + ), + PacketsReceived: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "network_receive_packets_total"), + "Packets Received on Interface", + []string{"container_id", "interface"}, + nil, + ), + PacketsSent: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "network_transmit_packets_total"), + "Packets Sent on Interface", + []string{"container_id", "interface"}, + nil, + ), + DroppedPacketsIncoming: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "network_receive_packets_dropped_total"), + "Dropped Incoming Packets on Interface", + []string{"container_id", "interface"}, + nil, + ), + DroppedPacketsOutgoing: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "network_transmit_packets_dropped_total"), + "Dropped Outgoing Packets on Interface", + []string{"container_id", "interface"}, + nil, + ), + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *ContainerMetricsCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + log.Error("failed collecting ContainerMetricsCollector metrics:", desc, err) + return err + } + return nil +} + +// containerClose closes the container resource +func containerClose(c hcsshim.Container) { + err := c.Close() + if err != nil { + log.Error(err) + } +} + +func (c *ContainerMetricsCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + + // Types Container is passed to get the containers compute systems only + containers, err := hcsshim.GetContainers(hcsshim.ComputeSystemQuery{Types: []string{"Container"}}) + if err != nil { + log.Error("Err in Getting containers:", err) + return nil, err + } + + count := len(containers) + + ch <- prometheus.MustNewConstMetric( + c.ContainersCount, + prometheus.GaugeValue, + float64(count), + ) + if count == 0 { + return nil, nil + } + + for _, containerDetails := range containers { + containerId := containerDetails.ID + + container, err := hcsshim.OpenContainer(containerId) + if container != nil { + defer containerClose(container) + } + if err != nil { + log.Error("err in opening container: ", containerId, err) + continue + } + + cstats, err := container.Statistics() + if err != nil { + log.Error("err in fetching container Statistics: ", containerId, err) + continue + } + // HCS V1 is for docker runtime. Add the docker:// prefix on container_id + containerId = "docker://" + containerId + + ch <- prometheus.MustNewConstMetric( + c.ContainerAvailable, + prometheus.CounterValue, + 1, + containerId, + ) + ch <- prometheus.MustNewConstMetric( + c.UsageCommitBytes, + prometheus.GaugeValue, + float64(cstats.Memory.UsageCommitBytes), + containerId, + ) + ch <- prometheus.MustNewConstMetric( + c.UsageCommitPeakBytes, + prometheus.GaugeValue, + float64(cstats.Memory.UsageCommitPeakBytes), + containerId, + ) + ch <- prometheus.MustNewConstMetric( + c.UsagePrivateWorkingSetBytes, + prometheus.GaugeValue, + float64(cstats.Memory.UsagePrivateWorkingSetBytes), + containerId, + ) + ch <- prometheus.MustNewConstMetric( + c.RuntimeTotal, + prometheus.CounterValue, + float64(cstats.Processor.TotalRuntime100ns)*ticksToSecondsScaleFactor, + containerId, + ) + ch <- prometheus.MustNewConstMetric( + c.RuntimeUser, + prometheus.CounterValue, + float64(cstats.Processor.RuntimeUser100ns)*ticksToSecondsScaleFactor, + containerId, + ) + ch <- prometheus.MustNewConstMetric( + c.RuntimeKernel, + prometheus.CounterValue, + float64(cstats.Processor.RuntimeKernel100ns)*ticksToSecondsScaleFactor, + containerId, + ) + + if len(cstats.Network) == 0 { + log.Info("No Network Stats for container: ", containerId) + continue + } + + networkStats := cstats.Network + + for _, networkInterface := range networkStats { + ch <- prometheus.MustNewConstMetric( + c.BytesReceived, + prometheus.CounterValue, + float64(networkInterface.BytesReceived), + containerId, networkInterface.EndpointId, + ) + ch <- prometheus.MustNewConstMetric( + c.BytesSent, + prometheus.CounterValue, + float64(networkInterface.BytesSent), + containerId, networkInterface.EndpointId, + ) + ch <- prometheus.MustNewConstMetric( + c.PacketsReceived, + prometheus.CounterValue, + float64(networkInterface.PacketsReceived), + containerId, networkInterface.EndpointId, + ) + ch <- prometheus.MustNewConstMetric( + c.PacketsSent, + prometheus.CounterValue, + float64(networkInterface.PacketsSent), + containerId, networkInterface.EndpointId, + ) + ch <- prometheus.MustNewConstMetric( + c.DroppedPacketsIncoming, + prometheus.CounterValue, + float64(networkInterface.DroppedPacketsIncoming), + containerId, networkInterface.EndpointId, + ) + ch <- prometheus.MustNewConstMetric( + c.DroppedPacketsOutgoing, + prometheus.CounterValue, + float64(networkInterface.DroppedPacketsOutgoing), + containerId, networkInterface.EndpointId, + ) + break + } + } + + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/cpu.go b/vendor/github.com/prometheus-community/windows_exporter/collector/cpu.go new file mode 100644 index 000000000000..0e3e9f096b3b --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/cpu.go @@ -0,0 +1,375 @@ +// +build windows + +package collector + +import ( + "strings" + + "github.com/prometheus/client_golang/prometheus" +) + +func init() { + var deps string + // See below for 6.05 magic value + if getWindowsVersion() > 6.05 { + deps = "Processor Information" + } else { + deps = "Processor" + } + registerCollector("cpu", newCPUCollector, deps) +} + +type cpuCollectorBasic struct { + CStateSecondsTotal *prometheus.Desc + TimeTotal *prometheus.Desc + InterruptsTotal *prometheus.Desc + DPCsTotal *prometheus.Desc +} +type cpuCollectorFull struct { + CStateSecondsTotal *prometheus.Desc + TimeTotal *prometheus.Desc + InterruptsTotal *prometheus.Desc + DPCsTotal *prometheus.Desc + ClockInterruptsTotal *prometheus.Desc + IdleBreakEventsTotal *prometheus.Desc + ParkingStatus *prometheus.Desc + ProcessorFrequencyMHz *prometheus.Desc + ProcessorMaxFrequencyMHz *prometheus.Desc + ProcessorPerformance *prometheus.Desc +} + +// newCPUCollector constructs a new cpuCollector, appropriate for the running OS +func newCPUCollector() (Collector, error) { + const subsystem = "cpu" + + version := getWindowsVersion() + // For Windows 2008 (version 6.0) or earlier we only have the "Processor" + // class. As of Windows 2008 R2 (version 6.1) the more detailed + // "Processor Information" set is available (although some of the counters + // are added in later versions, so we aren't guaranteed to get all of + // them). + // Value 6.05 was selected to split between Windows versions. + if version < 6.05 { + return &cpuCollectorBasic{ + CStateSecondsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "cstate_seconds_total"), + "Time spent in low-power idle state", + []string{"core", "state"}, + nil, + ), + TimeTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "time_total"), + "Time that processor spent in different modes (idle, user, system, ...)", + []string{"core", "mode"}, + nil, + ), + InterruptsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "interrupts_total"), + "Total number of received and serviced hardware interrupts", + []string{"core"}, + nil, + ), + DPCsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dpcs_total"), + "Total number of received and serviced deferred procedure calls (DPCs)", + []string{"core"}, + nil, + ), + }, nil + } + + return &cpuCollectorFull{ + CStateSecondsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "cstate_seconds_total"), + "Time spent in low-power idle state", + []string{"core", "state"}, + nil, + ), + TimeTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "time_total"), + "Time that processor spent in different modes (idle, user, system, ...)", + []string{"core", "mode"}, + nil, + ), + InterruptsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "interrupts_total"), + "Total number of received and serviced hardware interrupts", + []string{"core"}, + nil, + ), + DPCsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dpcs_total"), + "Total number of received and serviced deferred procedure calls (DPCs)", + []string{"core"}, + nil, + ), + ClockInterruptsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "clock_interrupts_total"), + "Total number of received and serviced clock tick interrupts", + []string{"core"}, + nil, + ), + IdleBreakEventsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "idle_break_events_total"), + "Total number of time processor was woken from idle", + []string{"core"}, + nil, + ), + ParkingStatus: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "parking_status"), + "Parking Status represents whether a processor is parked or not", + []string{"core"}, + nil, + ), + ProcessorFrequencyMHz: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "core_frequency_mhz"), + "Core frequency in megahertz", + []string{"core"}, + nil, + ), + ProcessorPerformance: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "processor_performance"), + "Processor Performance is the average performance of the processor while it is executing instructions, as a percentage of the nominal performance of the processor. On some processors, Processor Performance may exceed 100%", + []string{"core"}, + nil, + ), + }, nil +} + +type perflibProcessor struct { + Name string + C1Transitions float64 `perflib:"C1 Transitions/sec"` + C2Transitions float64 `perflib:"C2 Transitions/sec"` + C3Transitions float64 `perflib:"C3 Transitions/sec"` + DPCRate float64 `perflib:"DPC Rate"` + DPCsQueued float64 `perflib:"DPCs Queued/sec"` + Interrupts float64 `perflib:"Interrupts/sec"` + PercentC2Time float64 `perflib:"% C1 Time"` + PercentC3Time float64 `perflib:"% C2 Time"` + PercentC1Time float64 `perflib:"% C3 Time"` + PercentDPCTime float64 `perflib:"% DPC Time"` + PercentIdleTime float64 `perflib:"% Idle Time"` + PercentInterruptTime float64 `perflib:"% Interrupt Time"` + PercentPrivilegedTime float64 `perflib:"% Privileged Time"` + PercentProcessorTime float64 `perflib:"% Processor Time"` + PercentUserTime float64 `perflib:"% User Time"` +} + +func (c *cpuCollectorBasic) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + data := make([]perflibProcessor, 0) + err := unmarshalObject(ctx.perfObjects["Processor"], &data) + if err != nil { + return err + } + + for _, cpu := range data { + if strings.Contains(strings.ToLower(cpu.Name), "_total") { + continue + } + core := cpu.Name + + ch <- prometheus.MustNewConstMetric( + c.CStateSecondsTotal, + prometheus.CounterValue, + cpu.PercentC1Time, + core, "c1", + ) + ch <- prometheus.MustNewConstMetric( + c.CStateSecondsTotal, + prometheus.CounterValue, + cpu.PercentC2Time, + core, "c2", + ) + ch <- prometheus.MustNewConstMetric( + c.CStateSecondsTotal, + prometheus.CounterValue, + cpu.PercentC3Time, + core, "c3", + ) + + ch <- prometheus.MustNewConstMetric( + c.TimeTotal, + prometheus.CounterValue, + cpu.PercentIdleTime, + core, "idle", + ) + ch <- prometheus.MustNewConstMetric( + c.TimeTotal, + prometheus.CounterValue, + cpu.PercentInterruptTime, + core, "interrupt", + ) + ch <- prometheus.MustNewConstMetric( + c.TimeTotal, + prometheus.CounterValue, + cpu.PercentDPCTime, + core, "dpc", + ) + ch <- prometheus.MustNewConstMetric( + c.TimeTotal, + prometheus.CounterValue, + cpu.PercentPrivilegedTime, + core, "privileged", + ) + ch <- prometheus.MustNewConstMetric( + c.TimeTotal, + prometheus.CounterValue, + cpu.PercentUserTime, + core, "user", + ) + + ch <- prometheus.MustNewConstMetric( + c.InterruptsTotal, + prometheus.CounterValue, + cpu.Interrupts, + core, + ) + ch <- prometheus.MustNewConstMetric( + c.DPCsTotal, + prometheus.CounterValue, + cpu.DPCsQueued, + core, + ) + } + + return nil +} + +type perflibProcessorInformation struct { + Name string + C1TimeSeconds float64 `perflib:"% C1 Time"` + C2TimeSeconds float64 `perflib:"% C2 Time"` + C3TimeSeconds float64 `perflib:"% C3 Time"` + C1TransitionsTotal float64 `perflib:"C1 Transitions/sec"` + C2TransitionsTotal float64 `perflib:"C2 Transitions/sec"` + C3TransitionsTotal float64 `perflib:"C3 Transitions/sec"` + ClockInterruptsTotal float64 `perflib:"Clock Interrupts/sec"` + DPCsQueuedTotal float64 `perflib:"DPCs Queued/sec"` + DPCTimeSeconds float64 `perflib:"% DPC Time"` + IdleBreakEventsTotal float64 `perflib:"Idle Break Events/sec"` + IdleTimeSeconds float64 `perflib:"% Idle Time"` + InterruptsTotal float64 `perflib:"Interrupts/sec"` + InterruptTimeSeconds float64 `perflib:"% Interrupt Time"` + ParkingStatus float64 `perflib:"Parking Status"` + PerformanceLimitPercent float64 `perflib:"% Performance Limit"` + PriorityTimeSeconds float64 `perflib:"% Priority Time"` + PrivilegedTimeSeconds float64 `perflib:"% Privileged Time"` + PrivilegedUtilitySeconds float64 `perflib:"% Privileged Utility"` + ProcessorFrequencyMHz float64 `perflib:"Processor Frequency"` + ProcessorPerformance float64 `perflib:"% Processor Performance"` + ProcessorTimeSeconds float64 `perflib:"% Processor Time"` + ProcessorUtilityRate float64 `perflib:"% Processor Utility"` + UserTimeSeconds float64 `perflib:"% User Time"` +} + +func (c *cpuCollectorFull) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + data := make([]perflibProcessorInformation, 0) + err := unmarshalObject(ctx.perfObjects["Processor Information"], &data) + if err != nil { + return err + } + + for _, cpu := range data { + if strings.Contains(strings.ToLower(cpu.Name), "_total") { + continue + } + core := cpu.Name + + ch <- prometheus.MustNewConstMetric( + c.CStateSecondsTotal, + prometheus.CounterValue, + cpu.C1TimeSeconds, + core, "c1", + ) + ch <- prometheus.MustNewConstMetric( + c.CStateSecondsTotal, + prometheus.CounterValue, + cpu.C2TimeSeconds, + core, "c2", + ) + ch <- prometheus.MustNewConstMetric( + c.CStateSecondsTotal, + prometheus.CounterValue, + cpu.C3TimeSeconds, + core, "c3", + ) + + ch <- prometheus.MustNewConstMetric( + c.TimeTotal, + prometheus.CounterValue, + cpu.IdleTimeSeconds, + core, "idle", + ) + ch <- prometheus.MustNewConstMetric( + c.TimeTotal, + prometheus.CounterValue, + cpu.InterruptTimeSeconds, + core, "interrupt", + ) + ch <- prometheus.MustNewConstMetric( + c.TimeTotal, + prometheus.CounterValue, + cpu.DPCTimeSeconds, + core, "dpc", + ) + ch <- prometheus.MustNewConstMetric( + c.TimeTotal, + prometheus.CounterValue, + cpu.PrivilegedTimeSeconds, + core, "privileged", + ) + ch <- prometheus.MustNewConstMetric( + c.TimeTotal, + prometheus.CounterValue, + cpu.UserTimeSeconds, + core, "user", + ) + + ch <- prometheus.MustNewConstMetric( + c.InterruptsTotal, + prometheus.CounterValue, + cpu.InterruptsTotal, + core, + ) + ch <- prometheus.MustNewConstMetric( + c.DPCsTotal, + prometheus.CounterValue, + cpu.DPCsQueuedTotal, + core, + ) + ch <- prometheus.MustNewConstMetric( + c.ClockInterruptsTotal, + prometheus.CounterValue, + cpu.ClockInterruptsTotal, + core, + ) + ch <- prometheus.MustNewConstMetric( + c.IdleBreakEventsTotal, + prometheus.CounterValue, + cpu.IdleBreakEventsTotal, + core, + ) + + ch <- prometheus.MustNewConstMetric( + c.ParkingStatus, + prometheus.GaugeValue, + cpu.ParkingStatus, + core, + ) + + ch <- prometheus.MustNewConstMetric( + c.ProcessorFrequencyMHz, + prometheus.GaugeValue, + cpu.ProcessorFrequencyMHz, + core, + ) + ch <- prometheus.MustNewConstMetric( + c.ProcessorPerformance, + prometheus.GaugeValue, + cpu.ProcessorPerformance, + core, + ) + } + + return nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/cs.go b/vendor/github.com/prometheus-community/windows_exporter/collector/cs.go new file mode 100644 index 000000000000..f545b7012d2a --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/cs.go @@ -0,0 +1,112 @@ +// +build windows + +package collector + +import ( + "errors" + + "github.com/StackExchange/wmi" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +func init() { + registerCollector("cs", NewCSCollector) +} + +// A CSCollector is a Prometheus collector for WMI metrics +type CSCollector struct { + PhysicalMemoryBytes *prometheus.Desc + LogicalProcessors *prometheus.Desc + Hostname *prometheus.Desc +} + +// NewCSCollector ... +func NewCSCollector() (Collector, error) { + const subsystem = "cs" + + return &CSCollector{ + LogicalProcessors: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "logical_processors"), + "ComputerSystem.NumberOfLogicalProcessors", + nil, + nil, + ), + PhysicalMemoryBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "physical_memory_bytes"), + "ComputerSystem.TotalPhysicalMemory", + nil, + nil, + ), + Hostname: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "hostname"), + "Labeled system hostname information as provided by ComputerSystem.DNSHostName and ComputerSystem.Domain", + []string{ + "hostname", + "domain", + "fqdn"}, + nil, + ), + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *CSCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + log.Error("failed collecting cs metrics:", desc, err) + return err + } + return nil +} + +// Win32_ComputerSystem docs: +// - https://msdn.microsoft.com/en-us/library/aa394102 +type Win32_ComputerSystem struct { + NumberOfLogicalProcessors uint32 + TotalPhysicalMemory uint64 + DNSHostname string + Domain string + Workgroup *string +} + +func (c *CSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_ComputerSystem + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + if len(dst) == 0 { + return nil, errors.New("WMI query returned empty result set") + } + + ch <- prometheus.MustNewConstMetric( + c.LogicalProcessors, + prometheus.GaugeValue, + float64(dst[0].NumberOfLogicalProcessors), + ) + + ch <- prometheus.MustNewConstMetric( + c.PhysicalMemoryBytes, + prometheus.GaugeValue, + float64(dst[0].TotalPhysicalMemory), + ) + + var fqdn string + if dst[0].Workgroup == nil || dst[0].Domain != *dst[0].Workgroup { + fqdn = dst[0].DNSHostname + "." + dst[0].Domain + } else { + fqdn = dst[0].DNSHostname + } + + ch <- prometheus.MustNewConstMetric( + c.Hostname, + prometheus.GaugeValue, + 1.0, + dst[0].DNSHostname, + dst[0].Domain, + fqdn, + ) + + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/dhcp.go b/vendor/github.com/prometheus-community/windows_exporter/collector/dhcp.go new file mode 100644 index 000000000000..0848df0de8a6 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/dhcp.go @@ -0,0 +1,387 @@ +// +build windows + +package collector + +import ( + "github.com/prometheus/client_golang/prometheus" +) + +func init() { + registerCollector("dhcp", NewDhcpCollector, "DHCP Server") +} + +// A DhcpCollector is a Prometheus collector perflib DHCP metrics +type DhcpCollector struct { + PacketsReceivedTotal *prometheus.Desc + DuplicatesDroppedTotal *prometheus.Desc + PacketsExpiredTotal *prometheus.Desc + ActiveQueueLength *prometheus.Desc + ConflictCheckQueueLength *prometheus.Desc + DiscoversTotal *prometheus.Desc + OffersTotal *prometheus.Desc + RequestsTotal *prometheus.Desc + InformsTotal *prometheus.Desc + AcksTotal *prometheus.Desc + NacksTotal *prometheus.Desc + DeclinesTotal *prometheus.Desc + ReleasesTotal *prometheus.Desc + OfferQueueLength *prometheus.Desc + DeniedDueToMatch *prometheus.Desc + DeniedDueToNonMatch *prometheus.Desc + FailoverBndupdSentTotal *prometheus.Desc + FailoverBndupdReceivedTotal *prometheus.Desc + FailoverBndackSentTotal *prometheus.Desc + FailoverBndackReceivedTotal *prometheus.Desc + FailoverBndupdPendingOutboundQueue *prometheus.Desc + FailoverTransitionsCommunicationinterruptedState *prometheus.Desc + FailoverTransitionsPartnerdownState *prometheus.Desc + FailoverTransitionsRecoverState *prometheus.Desc + FailoverBndupdDropped *prometheus.Desc +} + +func NewDhcpCollector() (Collector, error) { + const subsystem = "dhcp" + + return &DhcpCollector{ + PacketsReceivedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "packets_received_total"), + "Total number of packets received by the DHCP server (PacketsReceivedTotal)", + nil, + nil, + ), + DuplicatesDroppedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "duplicates_dropped_total"), + "Total number of duplicate packets received by the DHCP server (DuplicatesDroppedTotal)", + nil, + nil, + ), + PacketsExpiredTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "packets_expired_total"), + "Total number of packets expired in the DHCP server message queue (PacketsExpiredTotal)", + nil, + nil, + ), + ActiveQueueLength: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "active_queue_length"), + "Number of packets in the processing queue of the DHCP server (ActiveQueueLength)", + nil, + nil, + ), + ConflictCheckQueueLength: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "conflict_check_queue_length"), + "Number of packets in the DHCP server queue waiting on conflict detection (ping). (ConflictCheckQueueLength)", + nil, + nil, + ), + DiscoversTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "discovers_total"), + "Total DHCP Discovers received by the DHCP server (DiscoversTotal)", + nil, + nil, + ), + OffersTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "offers_total"), + "Total DHCP Offers sent by the DHCP server (OffersTotal)", + nil, + nil, + ), + RequestsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "requests_total"), + "Total DHCP Requests received by the DHCP server (RequestsTotal)", + nil, + nil, + ), + InformsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "informs_total"), + "Total DHCP Informs received by the DHCP server (InformsTotal)", + nil, + nil, + ), + AcksTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "acks_total"), + "Total DHCP Acks sent by the DHCP server (AcksTotal)", + nil, + nil, + ), + NacksTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "nacks_total"), + "Total DHCP Nacks sent by the DHCP server (NacksTotal)", + nil, + nil, + ), + DeclinesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "declines_total"), + "Total DHCP Declines received by the DHCP server (DeclinesTotal)", + nil, + nil, + ), + ReleasesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "releases_total"), + "Total DHCP Releases received by the DHCP server (ReleasesTotal)", + nil, + nil, + ), + OfferQueueLength: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "offer_queue_length"), + "Number of packets in the offer queue of the DHCP server (OfferQueueLength)", + nil, + nil, + ), + DeniedDueToMatch: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "denied_due_to_match_total"), + "Total number of DHCP requests denied, based on matches from the Deny list (DeniedDueToMatch)", + nil, + nil, + ), + DeniedDueToNonMatch: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "denied_due_to_nonmatch_total"), + "Total number of DHCP requests denied, based on non-matches from the Allow list (DeniedDueToNonMatch)", + nil, + nil, + ), + FailoverBndupdSentTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "failover_bndupd_sent_total"), + "Number of DHCP failover Binding Update messages sent (FailoverBndupdSentTotal)", + nil, + nil, + ), + FailoverBndupdReceivedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "failover_bndupd_received_total"), + "Number of DHCP failover Binding Update messages received (FailoverBndupdReceivedTotal)", + nil, + nil, + ), + FailoverBndackSentTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "failover_bndack_sent_total"), + "Number of DHCP failover Binding Ack messages sent (FailoverBndackSentTotal)", + nil, + nil, + ), + FailoverBndackReceivedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "failover_bndack_received_total"), + "Number of DHCP failover Binding Ack messages received (FailoverBndackReceivedTotal)", + nil, + nil, + ), + FailoverBndupdPendingOutboundQueue: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "failover_bndupd_pending_in_outbound_queue"), + "Number of pending outbound DHCP failover Binding Update messages (FailoverBndupdPendingOutboundQueue)", + nil, + nil, + ), + FailoverTransitionsCommunicationinterruptedState: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "failover_transitions_communicationinterrupted_state_total"), + "Total number of transitions into COMMUNICATION INTERRUPTED state (FailoverTransitionsCommunicationinterruptedState)", + nil, + nil, + ), + FailoverTransitionsPartnerdownState: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "failover_transitions_partnerdown_state_total"), + "Total number of transitions into PARTNER DOWN state (FailoverTransitionsPartnerdownState)", + nil, + nil, + ), + FailoverTransitionsRecoverState: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "failover_transitions_recover_total"), + "Total number of transitions into RECOVER state (FailoverTransitionsRecoverState)", + nil, + nil, + ), + FailoverBndupdDropped: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "failover_bndupd_dropped_total"), + "Total number of DHCP faileover Binding Updates dropped (FailoverBndupdDropped)", + nil, + nil, + ), + }, nil +} + +// represents perflib metrics from the DHCP Server class. +// While the name of a number of perflib metrics would indicate a rate is being returned (E.G. Packets Received/sec), +// perflib instead returns a counter, hence the "Total" suffix in some of the variable names. +type dhcpPerf struct { + PacketsReceivedTotal float64 `perflib:"Packets Received/sec"` + DuplicatesDroppedTotal float64 `perflib:"Duplicates Dropped/sec"` + PacketsExpiredTotal float64 `perflib:"Packets Expired/sec"` + ActiveQueueLength float64 `perflib:"Active Queue Length"` + ConflictCheckQueueLength float64 `perflib:"Conflict Check Queue Length"` + DiscoversTotal float64 `perflib:"Discovers/sec"` + OffersTotal float64 `perflib:"Offers/sec"` + RequestsTotal float64 `perflib:"Requests/sec"` + InformsTotal float64 `perflib:"Informs/sec"` + AcksTotal float64 `perflib:"Acks/sec"` + NacksTotal float64 `perflib:"Nacks/sec"` + DeclinesTotal float64 `perflib:"Declines/sec"` + ReleasesTotal float64 `perflib:"Releases/sec"` + DeniedDueToMatch float64 `perflib:"Denied due to match."` + DeniedDueToNonMatch float64 `perflib:"Denied due to match."` + OfferQueueLength float64 `perflib:"Offer Queue Length"` + FailoverBndupdSentTotal float64 `perflib:"Failover: BndUpd sent/sec."` + FailoverBndupdReceivedTotal float64 `perflib:"Failover: BndUpd received/sec."` + FailoverBndackSentTotal float64 `perflib:"Failover: BndAck sent/sec."` + FailoverBndackReceivedTotal float64 `perflib:"Failover: BndAck received/sec."` + FailoverBndupdPendingOutboundQueue float64 `perflib:"Failover: BndUpd pending in outbound queue."` + FailoverTransitionsCommunicationinterruptedState float64 `perflib:"Failover: Transitions to COMMUNICATION-INTERRUPTED state."` + FailoverTransitionsPartnerdownState float64 `perflib:"Failover: Transitions to PARTNER-DOWN state."` + FailoverTransitionsRecoverState float64 `perflib:"Failover: Transitions to RECOVER state."` + FailoverBndupdDropped float64 `perflib:"Failover: BndUpd Dropped."` +} + +func (c *DhcpCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + var perflib []dhcpPerf + if err := unmarshalObject(ctx.perfObjects["DHCP Server"], &perflib); err != nil { + return err + } + + ch <- prometheus.MustNewConstMetric( + c.PacketsReceivedTotal, + prometheus.CounterValue, + perflib[0].PacketsReceivedTotal, + ) + + ch <- prometheus.MustNewConstMetric( + c.DuplicatesDroppedTotal, + prometheus.CounterValue, + perflib[0].DuplicatesDroppedTotal, + ) + + ch <- prometheus.MustNewConstMetric( + c.PacketsExpiredTotal, + prometheus.CounterValue, + perflib[0].PacketsExpiredTotal, + ) + + ch <- prometheus.MustNewConstMetric( + c.ActiveQueueLength, + prometheus.GaugeValue, + perflib[0].ActiveQueueLength, + ) + + ch <- prometheus.MustNewConstMetric( + c.ConflictCheckQueueLength, + prometheus.GaugeValue, + perflib[0].ConflictCheckQueueLength, + ) + + ch <- prometheus.MustNewConstMetric( + c.DiscoversTotal, + prometheus.CounterValue, + perflib[0].DiscoversTotal, + ) + + ch <- prometheus.MustNewConstMetric( + c.OffersTotal, + prometheus.CounterValue, + perflib[0].OffersTotal, + ) + + ch <- prometheus.MustNewConstMetric( + c.RequestsTotal, + prometheus.CounterValue, + perflib[0].RequestsTotal, + ) + + ch <- prometheus.MustNewConstMetric( + c.InformsTotal, + prometheus.CounterValue, + perflib[0].InformsTotal, + ) + + ch <- prometheus.MustNewConstMetric( + c.AcksTotal, + prometheus.CounterValue, + perflib[0].AcksTotal, + ) + + ch <- prometheus.MustNewConstMetric( + c.NacksTotal, + prometheus.CounterValue, + perflib[0].NacksTotal, + ) + + ch <- prometheus.MustNewConstMetric( + c.DeclinesTotal, + prometheus.CounterValue, + perflib[0].DeclinesTotal, + ) + + ch <- prometheus.MustNewConstMetric( + c.ReleasesTotal, + prometheus.CounterValue, + perflib[0].ReleasesTotal, + ) + + ch <- prometheus.MustNewConstMetric( + c.OfferQueueLength, + prometheus.GaugeValue, + perflib[0].OfferQueueLength, + ) + + ch <- prometheus.MustNewConstMetric( + c.DeniedDueToMatch, + prometheus.CounterValue, + perflib[0].DeniedDueToMatch, + ) + + ch <- prometheus.MustNewConstMetric( + c.DeniedDueToNonMatch, + prometheus.CounterValue, + perflib[0].DeniedDueToNonMatch, + ) + + ch <- prometheus.MustNewConstMetric( + c.FailoverBndupdSentTotal, + prometheus.CounterValue, + perflib[0].FailoverBndupdSentTotal, + ) + + ch <- prometheus.MustNewConstMetric( + c.FailoverBndupdReceivedTotal, + prometheus.CounterValue, + perflib[0].FailoverBndupdReceivedTotal, + ) + + ch <- prometheus.MustNewConstMetric( + c.FailoverBndackSentTotal, + prometheus.CounterValue, + perflib[0].FailoverBndackSentTotal, + ) + + ch <- prometheus.MustNewConstMetric( + c.FailoverBndackReceivedTotal, + prometheus.CounterValue, + perflib[0].FailoverBndackReceivedTotal, + ) + + ch <- prometheus.MustNewConstMetric( + c.FailoverBndupdPendingOutboundQueue, + prometheus.GaugeValue, + perflib[0].FailoverBndupdPendingOutboundQueue, + ) + + ch <- prometheus.MustNewConstMetric( + c.FailoverTransitionsCommunicationinterruptedState, + prometheus.CounterValue, + perflib[0].FailoverTransitionsCommunicationinterruptedState, + ) + + ch <- prometheus.MustNewConstMetric( + c.FailoverTransitionsPartnerdownState, + prometheus.CounterValue, + perflib[0].FailoverTransitionsPartnerdownState, + ) + + ch <- prometheus.MustNewConstMetric( + c.FailoverTransitionsRecoverState, + prometheus.CounterValue, + perflib[0].FailoverTransitionsRecoverState, + ) + + ch <- prometheus.MustNewConstMetric( + c.FailoverBndupdDropped, + prometheus.CounterValue, + perflib[0].FailoverBndupdDropped, + ) + + return nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/dns.go b/vendor/github.com/prometheus-community/windows_exporter/collector/dns.go new file mode 100644 index 000000000000..d9ec9d917785 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/dns.go @@ -0,0 +1,498 @@ +// +build windows + +package collector + +import ( + "errors" + + "github.com/StackExchange/wmi" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +func init() { + registerCollector("dns", NewDNSCollector) +} + +// A DNSCollector is a Prometheus collector for WMI Win32_PerfRawData_DNS_DNS metrics +type DNSCollector struct { + ZoneTransferRequestsReceived *prometheus.Desc + ZoneTransferRequestsSent *prometheus.Desc + ZoneTransferResponsesReceived *prometheus.Desc + ZoneTransferSuccessReceived *prometheus.Desc + ZoneTransferSuccessSent *prometheus.Desc + ZoneTransferFailures *prometheus.Desc + MemoryUsedBytes *prometheus.Desc + DynamicUpdatesQueued *prometheus.Desc + DynamicUpdatesReceived *prometheus.Desc + DynamicUpdatesFailures *prometheus.Desc + NotifyReceived *prometheus.Desc + NotifySent *prometheus.Desc + SecureUpdateFailures *prometheus.Desc + SecureUpdateReceived *prometheus.Desc + Queries *prometheus.Desc + Responses *prometheus.Desc + RecursiveQueries *prometheus.Desc + RecursiveQueryFailures *prometheus.Desc + RecursiveQuerySendTimeouts *prometheus.Desc + WinsQueries *prometheus.Desc + WinsResponses *prometheus.Desc + UnmatchedResponsesReceived *prometheus.Desc +} + +// NewDNSCollector ... +func NewDNSCollector() (Collector, error) { + const subsystem = "dns" + return &DNSCollector{ + ZoneTransferRequestsReceived: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "zone_transfer_requests_received_total"), + "Number of zone transfer requests (AXFR/IXFR) received by the master DNS server", + []string{"qtype"}, + nil, + ), + ZoneTransferRequestsSent: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "zone_transfer_requests_sent_total"), + "Number of zone transfer requests (AXFR/IXFR) sent by the secondary DNS server", + []string{"qtype"}, + nil, + ), + ZoneTransferResponsesReceived: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "zone_transfer_response_received_total"), + "Number of zone transfer responses (AXFR/IXFR) received by the secondary DNS server", + []string{"qtype"}, + nil, + ), + ZoneTransferSuccessReceived: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "zone_transfer_success_received_total"), + "Number of successful zone transfers (AXFR/IXFR) received by the secondary DNS server", + []string{"qtype", "protocol"}, + nil, + ), + ZoneTransferSuccessSent: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "zone_transfer_success_sent_total"), + "Number of successful zone transfers (AXFR/IXFR) of the master DNS server", + []string{"qtype"}, + nil, + ), + ZoneTransferFailures: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "zone_transfer_failures_total"), + "Number of failed zone transfers of the master DNS server", + nil, + nil, + ), + MemoryUsedBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "memory_used_bytes"), + "Current memory used by DNS server", + []string{"area"}, + nil, + ), + DynamicUpdatesQueued: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dynamic_updates_queued"), + "Number of dynamic updates queued by the DNS server", + nil, + nil, + ), + DynamicUpdatesReceived: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dynamic_updates_received_total"), + "Number of secure update requests received by the DNS server", + []string{"operation"}, + nil, + ), + DynamicUpdatesFailures: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dynamic_updates_failures_total"), + "Number of dynamic updates which timed out or were rejected by the DNS server", + []string{"reason"}, + nil, + ), + NotifyReceived: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "notify_received_total"), + "Number of notifies received by the secondary DNS server", + nil, + nil, + ), + NotifySent: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "notify_sent_total"), + "Number of notifies sent by the master DNS server", + nil, + nil, + ), + SecureUpdateFailures: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "secure_update_failures_total"), + "Number of secure updates that failed on the DNS server", + nil, + nil, + ), + SecureUpdateReceived: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "secure_update_received_total"), + "Number of secure update requests received by the DNS server", + nil, + nil, + ), + Queries: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "queries_total"), + "Number of queries received by DNS server", + []string{"protocol"}, + nil, + ), + Responses: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "responses_total"), + "Number of reponses sent by DNS server", + []string{"protocol"}, + nil, + ), + RecursiveQueries: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "recursive_queries_total"), + "Number of recursive queries received by DNS server", + nil, + nil, + ), + RecursiveQueryFailures: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "recursive_query_failures_total"), + "Number of recursive query failures", + nil, + nil, + ), + RecursiveQuerySendTimeouts: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "recursive_query_send_timeouts_total"), + "Number of recursive query sending timeouts", + nil, + nil, + ), + WinsQueries: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "wins_queries_total"), + "Number of WINS lookup requests received by the server", + []string{"direction"}, + nil, + ), + WinsResponses: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "wins_responses_total"), + "Number of WINS lookup responses sent by the server", + []string{"direction"}, + nil, + ), + UnmatchedResponsesReceived: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "unmatched_responses_total"), + "Number of response packets received by the DNS server that do not match any outstanding remote query", + nil, + nil, + ), + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *DNSCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + log.Error("failed collecting dns metrics:", desc, err) + return err + } + return nil +} + +// Win32_PerfRawData_DNS_DNS docs: +// - https://msdn.microsoft.com/en-us/library/ms803992.aspx?f=255&MSPPError=-2147217396 +// - https://technet.microsoft.com/en-us/library/cc977686.aspx +type Win32_PerfRawData_DNS_DNS struct { + AXFRRequestReceived uint32 + AXFRRequestSent uint32 + AXFRResponseReceived uint32 + AXFRSuccessReceived uint32 + AXFRSuccessSent uint32 + CachingMemory uint32 + DatabaseNodeMemory uint32 + DynamicUpdateNoOperation uint32 + DynamicUpdateQueued uint32 + DynamicUpdateRejected uint32 + DynamicUpdateTimeOuts uint32 + DynamicUpdateWrittentoDatabase uint32 + IXFRRequestReceived uint32 + IXFRRequestSent uint32 + IXFRResponseReceived uint32 + IXFRSuccessSent uint32 + IXFRTCPSuccessReceived uint32 + IXFRUDPSuccessReceived uint32 + NbstatMemory uint32 + NotifyReceived uint32 + NotifySent uint32 + RecordFlowMemory uint32 + RecursiveQueries uint32 + RecursiveQueryFailure uint32 + RecursiveSendTimeOuts uint32 + SecureUpdateFailure uint32 + SecureUpdateReceived uint32 + TCPMessageMemory uint32 + TCPQueryReceived uint32 + TCPResponseSent uint32 + UDPMessageMemory uint32 + UDPQueryReceived uint32 + UDPResponseSent uint32 + UnmatchedResponsesReceived uint32 + WINSLookupReceived uint32 + WINSResponseSent uint32 + WINSReverseLookupReceived uint32 + WINSReverseResponseSent uint32 + ZoneTransferFailure uint32 + ZoneTransferSOARequestSent uint32 +} + +func (c *DNSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_DNS_DNS + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + if len(dst) == 0 { + return nil, errors.New("WMI query returned empty result set") + } + + ch <- prometheus.MustNewConstMetric( + c.ZoneTransferRequestsReceived, + prometheus.CounterValue, + float64(dst[0].AXFRRequestReceived), + "full", + ) + ch <- prometheus.MustNewConstMetric( + c.ZoneTransferRequestsReceived, + prometheus.CounterValue, + float64(dst[0].IXFRRequestReceived), + "incremental", + ) + + ch <- prometheus.MustNewConstMetric( + c.ZoneTransferRequestsSent, + prometheus.CounterValue, + float64(dst[0].AXFRRequestSent), + "full", + ) + ch <- prometheus.MustNewConstMetric( + c.ZoneTransferRequestsSent, + prometheus.CounterValue, + float64(dst[0].IXFRRequestSent), + "incremental", + ) + ch <- prometheus.MustNewConstMetric( + c.ZoneTransferRequestsSent, + prometheus.CounterValue, + float64(dst[0].ZoneTransferSOARequestSent), + "soa", + ) + + ch <- prometheus.MustNewConstMetric( + c.ZoneTransferResponsesReceived, + prometheus.CounterValue, + float64(dst[0].AXFRResponseReceived), + "full", + ) + ch <- prometheus.MustNewConstMetric( + c.ZoneTransferResponsesReceived, + prometheus.CounterValue, + float64(dst[0].IXFRResponseReceived), + "incremental", + ) + + ch <- prometheus.MustNewConstMetric( + c.ZoneTransferSuccessReceived, + prometheus.CounterValue, + float64(dst[0].AXFRSuccessReceived), + "full", + "tcp", + ) + ch <- prometheus.MustNewConstMetric( + c.ZoneTransferSuccessReceived, + prometheus.CounterValue, + float64(dst[0].IXFRTCPSuccessReceived), + "incremental", + "tcp", + ) + ch <- prometheus.MustNewConstMetric( + c.ZoneTransferSuccessReceived, + prometheus.CounterValue, + float64(dst[0].IXFRTCPSuccessReceived), + "incremental", + "udp", + ) + + ch <- prometheus.MustNewConstMetric( + c.ZoneTransferSuccessSent, + prometheus.CounterValue, + float64(dst[0].AXFRSuccessSent), + "full", + ) + ch <- prometheus.MustNewConstMetric( + c.ZoneTransferSuccessSent, + prometheus.CounterValue, + float64(dst[0].IXFRSuccessSent), + "incremental", + ) + + ch <- prometheus.MustNewConstMetric( + c.ZoneTransferFailures, + prometheus.CounterValue, + float64(dst[0].ZoneTransferFailure), + ) + + ch <- prometheus.MustNewConstMetric( + c.MemoryUsedBytes, + prometheus.GaugeValue, + float64(dst[0].CachingMemory), + "caching", + ) + ch <- prometheus.MustNewConstMetric( + c.MemoryUsedBytes, + prometheus.GaugeValue, + float64(dst[0].DatabaseNodeMemory), + "database_node", + ) + ch <- prometheus.MustNewConstMetric( + c.MemoryUsedBytes, + prometheus.GaugeValue, + float64(dst[0].NbstatMemory), + "nbstat", + ) + ch <- prometheus.MustNewConstMetric( + c.MemoryUsedBytes, + prometheus.GaugeValue, + float64(dst[0].RecordFlowMemory), + "record_flow", + ) + ch <- prometheus.MustNewConstMetric( + c.MemoryUsedBytes, + prometheus.GaugeValue, + float64(dst[0].TCPMessageMemory), + "tcp_message", + ) + ch <- prometheus.MustNewConstMetric( + c.MemoryUsedBytes, + prometheus.GaugeValue, + float64(dst[0].UDPMessageMemory), + "udp_message", + ) + + ch <- prometheus.MustNewConstMetric( + c.DynamicUpdatesReceived, + prometheus.CounterValue, + float64(dst[0].DynamicUpdateNoOperation), + "noop", + ) + ch <- prometheus.MustNewConstMetric( + c.DynamicUpdatesReceived, + prometheus.CounterValue, + float64(dst[0].DynamicUpdateWrittentoDatabase), + "written", + ) + ch <- prometheus.MustNewConstMetric( + c.DynamicUpdatesQueued, + prometheus.GaugeValue, + float64(dst[0].DynamicUpdateQueued), + ) + ch <- prometheus.MustNewConstMetric( + c.DynamicUpdatesFailures, + prometheus.CounterValue, + float64(dst[0].DynamicUpdateRejected), + "rejected", + ) + ch <- prometheus.MustNewConstMetric( + c.DynamicUpdatesFailures, + prometheus.CounterValue, + float64(dst[0].DynamicUpdateTimeOuts), + "timeout", + ) + + ch <- prometheus.MustNewConstMetric( + c.NotifyReceived, + prometheus.CounterValue, + float64(dst[0].NotifyReceived), + ) + ch <- prometheus.MustNewConstMetric( + c.NotifySent, + prometheus.CounterValue, + float64(dst[0].NotifySent), + ) + + ch <- prometheus.MustNewConstMetric( + c.RecursiveQueries, + prometheus.CounterValue, + float64(dst[0].RecursiveQueries), + ) + ch <- prometheus.MustNewConstMetric( + c.RecursiveQueryFailures, + prometheus.CounterValue, + float64(dst[0].RecursiveQueryFailure), + ) + ch <- prometheus.MustNewConstMetric( + c.RecursiveQuerySendTimeouts, + prometheus.CounterValue, + float64(dst[0].RecursiveSendTimeOuts), + ) + + ch <- prometheus.MustNewConstMetric( + c.Queries, + prometheus.CounterValue, + float64(dst[0].TCPQueryReceived), + "tcp", + ) + ch <- prometheus.MustNewConstMetric( + c.Queries, + prometheus.CounterValue, + float64(dst[0].UDPQueryReceived), + "udp", + ) + + ch <- prometheus.MustNewConstMetric( + c.Responses, + prometheus.CounterValue, + float64(dst[0].TCPResponseSent), + "tcp", + ) + ch <- prometheus.MustNewConstMetric( + c.Responses, + prometheus.CounterValue, + float64(dst[0].UDPResponseSent), + "udp", + ) + + ch <- prometheus.MustNewConstMetric( + c.UnmatchedResponsesReceived, + prometheus.CounterValue, + float64(dst[0].UnmatchedResponsesReceived), + ) + + ch <- prometheus.MustNewConstMetric( + c.WinsQueries, + prometheus.CounterValue, + float64(dst[0].WINSLookupReceived), + "forward", + ) + ch <- prometheus.MustNewConstMetric( + c.WinsQueries, + prometheus.CounterValue, + float64(dst[0].WINSReverseLookupReceived), + "reverse", + ) + + ch <- prometheus.MustNewConstMetric( + c.WinsResponses, + prometheus.CounterValue, + float64(dst[0].WINSResponseSent), + "forward", + ) + ch <- prometheus.MustNewConstMetric( + c.WinsResponses, + prometheus.CounterValue, + float64(dst[0].WINSReverseResponseSent), + "reverse", + ) + + ch <- prometheus.MustNewConstMetric( + c.SecureUpdateFailures, + prometheus.CounterValue, + float64(dst[0].SecureUpdateFailure), + ) + ch <- prometheus.MustNewConstMetric( + c.SecureUpdateReceived, + prometheus.CounterValue, + float64(dst[0].SecureUpdateReceived), + ) + + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/exchange.go b/vendor/github.com/prometheus-community/windows_exporter/collector/exchange.go new file mode 100644 index 000000000000..34416cd3a8c7 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/exchange.go @@ -0,0 +1,635 @@ +// +build windows + +package collector + +import ( + "fmt" + "os" + "strings" + + "gopkg.in/alecthomas/kingpin.v2" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +type ExchangeConfig struct { + List bool + Enabled string +} + +func (e *ExchangeConfig) RegisterKingpin(ka *kingpin.Application) { + ka.Flag("collectors.exchange.list", "List the collectors along with their perflib object name/ids").BoolVar(&e.List) + ka.Flag("collectors.exchange.enabled", "Comma-separated List of collectors to use. Defaults to all, if not specified.").StringVar(&e.Enabled) +} + +func (e *ExchangeConfig) Build() (Collector, error) { return newExchangeCollector(e) } + +func init() { + registerCollectorWithConfig("exchange", func() Config { return &ExchangeConfig{} }, + "MSExchange ADAccess Processes", + "MSExchangeTransport Queues", + "MSExchange HttpProxy", + "MSExchange ActiveSync", + "MSExchange Availability Service", + "MSExchange OWA", + "MSExchangeAutodiscover", + "MSExchange WorkloadManagement Workloads", + "MSExchange RpcClientAccess", + ) +} + +type exchangeCollector struct { + LDAPReadTime *prometheus.Desc + LDAPSearchTime *prometheus.Desc + LDAPWriteTime *prometheus.Desc + LDAPTimeoutErrorsPerSec *prometheus.Desc + LongRunningLDAPOperationsPerMin *prometheus.Desc + ExternalActiveRemoteDeliveryQueueLength *prometheus.Desc + InternalActiveRemoteDeliveryQueueLength *prometheus.Desc + ActiveMailboxDeliveryQueueLength *prometheus.Desc + RetryMailboxDeliveryQueueLength *prometheus.Desc + UnreachableQueueLength *prometheus.Desc + ExternalLargestDeliveryQueueLength *prometheus.Desc + InternalLargestDeliveryQueueLength *prometheus.Desc + PoisonQueueLength *prometheus.Desc + MailboxServerLocatorAverageLatency *prometheus.Desc + AverageAuthenticationLatency *prometheus.Desc + AverageCASProcessingLatency *prometheus.Desc + MailboxServerProxyFailureRate *prometheus.Desc + OutstandingProxyRequests *prometheus.Desc + ProxyRequestsPerSec *prometheus.Desc + ActiveSyncRequestsPerSec *prometheus.Desc + PingCommandsPending *prometheus.Desc + SyncCommandsPerSec *prometheus.Desc + AvailabilityRequestsSec *prometheus.Desc + CurrentUniqueUsers *prometheus.Desc + OWARequestsPerSec *prometheus.Desc + AutodiscoverRequestsPerSec *prometheus.Desc + ActiveTasks *prometheus.Desc + CompletedTasks *prometheus.Desc + QueuedTasks *prometheus.Desc + YieldedTasks *prometheus.Desc + IsActive *prometheus.Desc + RPCAveragedLatency *prometheus.Desc + RPCRequests *prometheus.Desc + ActiveUserCount *prometheus.Desc + ConnectionCount *prometheus.Desc + RPCOperationsPerSec *prometheus.Desc + UserCount *prometheus.Desc + + enabledCollectors []string + + ArgExchangeListAllCollectors bool + ArgExchangeCollectorsEnabled string +} + +var collectorDesc = map[string]string{ + "ADAccessProcesses": "[19108] MSExchange ADAccess Processes", + "TransportQueues": "[20524] MSExchangeTransport Queues", + "HttpProxy": "[36934] MSExchange HttpProxy", + "ActiveSync": "[25138] MSExchange ActiveSync", + "AvailabilityService": "[24914] MSExchange Availability Service", + "OutlookWebAccess": "[24618] MSExchange OWA", + "Autodiscover": "[29240] MSExchange Autodiscover", + "WorkloadManagement": "[19430] MSExchange WorkloadManagement Workloads", + "RpcClientAccess": "[29336] MSExchange RpcClientAccess", +} + +var ( + // All available collector functions + exchangeAllCollectorNames = []string{ + "ADAccessProcesses", + "TransportQueues", + "HttpProxy", + "ActiveSync", + "AvailabilityService", + "OutlookWebAccess", + "Autodiscover", + "WorkloadManagement", + "RpcClientAccess", + } +) + +// newExchangeCollector returns a new Collector +func newExchangeCollector(config *ExchangeConfig) (Collector, error) { + if config.List { + fmt.Printf("%-32s %-32s\n", "Collector Name", "[PerfID] Perflib Object") + for _, cname := range exchangeAllCollectorNames { + fmt.Printf("%-32s %-32s\n", cname, collectorDesc[cname]) + } + os.Exit(0) + } + // desc creates a new prometheus description + desc := func(metricName string, description string, labels ...string) *prometheus.Desc { + return prometheus.NewDesc( + prometheus.BuildFQName(Namespace, "exchange", metricName), + description, + labels, + nil, + ) + } + + c := exchangeCollector{ + RPCAveragedLatency: desc("rpc_avg_latency_sec", "The latency (sec), averaged for the past 1024 packets"), + RPCRequests: desc("rpc_requests", "Number of client requests currently being processed by the RPC Client Access service"), + ActiveUserCount: desc("rpc_active_user_count", "Number of unique users that have shown some kind of activity in the last 2 minutes"), + ConnectionCount: desc("rpc_connection_count", "Total number of client connections maintained"), + RPCOperationsPerSec: desc("rpc_operations_total", "The rate at which RPC operations occur"), + UserCount: desc("rpc_user_count", "Number of users"), + LDAPReadTime: desc("ldap_read_time_sec", "Time (sec) to send an LDAP read request and receive a response", "name"), + LDAPSearchTime: desc("ldap_search_time_sec", "Time (sec) to send an LDAP search request and receive a response", "name"), + LDAPWriteTime: desc("ldap_write_time_sec", "Time (sec) to send an LDAP Add/Modify/Delete request and receive a response", "name"), + LDAPTimeoutErrorsPerSec: desc("ldap_timeout_errors_total", "Total number of LDAP timeout errors", "name"), + LongRunningLDAPOperationsPerMin: desc("ldap_long_running_ops_per_sec", "Long Running LDAP operations per second", "name"), + ExternalActiveRemoteDeliveryQueueLength: desc("transport_queues_external_active_remote_delivery", "External Active Remote Delivery Queue length", "name"), + InternalActiveRemoteDeliveryQueueLength: desc("transport_queues_internal_active_remote_delivery", "Internal Active Remote Delivery Queue length", "name"), + ActiveMailboxDeliveryQueueLength: desc("transport_queues_active_mailbox_delivery", "Active Mailbox Delivery Queue length", "name"), + RetryMailboxDeliveryQueueLength: desc("transport_queues_retry_mailbox_delivery", "Retry Mailbox Delivery Queue length", "name"), + UnreachableQueueLength: desc("transport_queues_unreachable", "Unreachable Queue length", "name"), + ExternalLargestDeliveryQueueLength: desc("transport_queues_external_largest_delivery", "External Largest Delivery Queue length", "name"), + InternalLargestDeliveryQueueLength: desc("transport_queues_internal_largest_delivery", "Internal Largest Delivery Queue length", "name"), + PoisonQueueLength: desc("transport_queues_poison", "Poison Queue length", "name"), + MailboxServerLocatorAverageLatency: desc("http_proxy_mailbox_server_locator_avg_latency_sec", "Average latency (sec) of MailboxServerLocator web service calls", "name"), + AverageAuthenticationLatency: desc("http_proxy_avg_auth_latency", "Average time spent authenticating CAS requests over the last 200 samples", "name"), + OutstandingProxyRequests: desc("http_proxy_outstanding_proxy_requests", "Number of concurrent outstanding proxy requests", "name"), + ProxyRequestsPerSec: desc("http_proxy_requests_total", "Number of proxy requests processed each second", "name"), + AvailabilityRequestsSec: desc("avail_service_requests_per_sec", "Number of requests serviced per second"), + CurrentUniqueUsers: desc("owa_current_unique_users", "Number of unique users currently logged on to Outlook Web App"), + OWARequestsPerSec: desc("owa_requests_total", "Number of requests handled by Outlook Web App per second"), + AutodiscoverRequestsPerSec: desc("autodiscover_requests_total", "Number of autodiscover service requests processed each second"), + ActiveTasks: desc("workload_active_tasks", "Number of active tasks currently running in the background for workload management", "name"), + CompletedTasks: desc("workload_completed_tasks", "Number of workload management tasks that have been completed", "name"), + QueuedTasks: desc("workload_queued_tasks", "Number of workload management tasks that are currently queued up waiting to be processed", "name"), + YieldedTasks: desc("workload_yielded_tasks", "The total number of tasks that have been yielded by a workload", "name"), + IsActive: desc("workload_is_active", "Active indicates whether the workload is in an active (1) or paused (0) state", "name"), + ActiveSyncRequestsPerSec: desc("activesync_requests_total", "Num HTTP requests received from the client via ASP.NET per sec. Shows Current user load"), + AverageCASProcessingLatency: desc("http_proxy_avg_cas_proccessing_latency_sec", "Average latency (sec) of CAS processing time over the last 200 reqs", "name"), + MailboxServerProxyFailureRate: desc("http_proxy_mailbox_proxy_failure_rate", "% of failures between this CAS and MBX servers over the last 200 samples", "name"), + PingCommandsPending: desc("activesync_ping_cmds_pending", "Number of ping commands currently pending in the queue"), + SyncCommandsPerSec: desc("activesync_sync_cmds_total", "Number of sync commands processed per second. Clients use this command to synchronize items within a folder"), + + enabledCollectors: make([]string, 0, len(exchangeAllCollectorNames)), + } + if config.Enabled == "" { + for _, collectorName := range exchangeAllCollectorNames { + c.enabledCollectors = append(c.enabledCollectors, collectorName) + } + } else { + for _, collectorName := range strings.Split(c.ArgExchangeCollectorsEnabled, ",") { + if find(exchangeAllCollectorNames, collectorName) { + c.enabledCollectors = append(c.enabledCollectors, collectorName) + } else { + fmt.Errorf("Unknown exchange collector: %s", collectorName) + } + } + } + return &c, nil +} + +// Collect collects exchange metrics and sends them to prometheus +func (c *exchangeCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + + collectorFuncs := map[string]func(ctx *ScrapeContext, ch chan<- prometheus.Metric) error{ + "ADAccessProcesses": c.collectADAccessProcesses, + "TransportQueues": c.collectTransportQueues, + "HttpProxy": c.collectHTTPProxy, + "ActiveSync": c.collectActiveSync, + "AvailabilityService": c.collectAvailabilityService, + "OutlookWebAccess": c.collectOWA, + "Autodiscover": c.collectAutoDiscover, + "WorkloadManagement": c.collectWorkloadManagementWorkloads, + "RpcClientAccess": c.collectRPC, + } + + for _, collectorName := range c.enabledCollectors { + if err := collectorFuncs[collectorName](ctx, ch); err != nil { + log.Errorf("Error in %s: %s", collectorName, err) + return err + } + } + return nil +} + +// Perflib: [19108] MSExchange ADAccess Processes +type perflibADAccessProcesses struct { + Name string + + LDAPReadTime float64 `perflib:"LDAP Read Time"` + LDAPSearchTime float64 `perflib:"LDAP Search Time"` + LDAPWriteTime float64 `perflib:"LDAP Write Time"` + LDAPTimeoutErrorsPerSec float64 `perflib:"LDAP Timeout Errors/sec"` + LongRunningLDAPOperationsPerMin float64 `perflib:"Long Running LDAP Operations/min"` +} + +func (c *exchangeCollector) collectADAccessProcesses(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + var data []perflibADAccessProcesses + if err := unmarshalObject(ctx.perfObjects["MSExchange ADAccess Processes"], &data); err != nil { + return err + } + + labelUseCount := make(map[string]int) + for _, proc := range data { + labelName := c.toLabelName(proc.Name) + if strings.HasSuffix(labelName, "_total") { + continue + } + + // since we're not including the PID suffix from the instance names in the label names, + // we get an occational duplicate. This seems to affect about 4 instances only on this object. + labelUseCount[labelName]++ + if labelUseCount[labelName] > 1 { + labelName = fmt.Sprintf("%s_%d", labelName, labelUseCount[labelName]) + } + ch <- prometheus.MustNewConstMetric( + c.LDAPReadTime, + prometheus.CounterValue, + c.msToSec(proc.LDAPReadTime), + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.LDAPSearchTime, + prometheus.CounterValue, + c.msToSec(proc.LDAPSearchTime), + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.LDAPWriteTime, + prometheus.CounterValue, + c.msToSec(proc.LDAPWriteTime), + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.LDAPTimeoutErrorsPerSec, + prometheus.CounterValue, + proc.LDAPTimeoutErrorsPerSec, + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.LongRunningLDAPOperationsPerMin, + prometheus.CounterValue, + proc.LongRunningLDAPOperationsPerMin*60, + labelName, + ) + } + return nil +} + +// Perflib: [24914] MSExchange Availability Service +type perflibAvailabilityService struct { + RequestsSec float64 `perflib:"Availability Requests (sec)"` +} + +func (c *exchangeCollector) collectAvailabilityService(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + var data []perflibAvailabilityService + if err := unmarshalObject(ctx.perfObjects["MSExchange Availability Service"], &data); err != nil { + return err + } + + for _, availservice := range data { + ch <- prometheus.MustNewConstMetric( + c.AvailabilityRequestsSec, + prometheus.CounterValue, + availservice.RequestsSec, + ) + } + return nil +} + +// Perflib: [36934] MSExchange HttpProxy +type perflibHTTPProxy struct { + Name string + + MailboxServerLocatorAverageLatency float64 `perflib:"MailboxServerLocator Average Latency (Moving Average)"` + AverageAuthenticationLatency float64 `perflib:"Average Authentication Latency"` + AverageCASProcessingLatency float64 `perflib:"Average ClientAccess Server Processing Latency"` + MailboxServerProxyFailureRate float64 `perflib:"Mailbox Server Proxy Failure Rate"` + OutstandingProxyRequests float64 `perflib:"Outstanding Proxy Requests"` + ProxyRequestsPerSec float64 `perflib:"Proxy Requests/Sec"` +} + +func (c *exchangeCollector) collectHTTPProxy(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + var data []perflibHTTPProxy + if err := unmarshalObject(ctx.perfObjects["MSExchange HttpProxy"], &data); err != nil { + return err + } + + for _, instance := range data { + labelName := c.toLabelName(instance.Name) + ch <- prometheus.MustNewConstMetric( + c.MailboxServerLocatorAverageLatency, + prometheus.GaugeValue, + c.msToSec(instance.MailboxServerLocatorAverageLatency), + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.AverageAuthenticationLatency, + prometheus.GaugeValue, + instance.AverageAuthenticationLatency, + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.AverageCASProcessingLatency, + prometheus.GaugeValue, + c.msToSec(instance.AverageCASProcessingLatency), + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.MailboxServerProxyFailureRate, + prometheus.GaugeValue, + instance.MailboxServerProxyFailureRate, + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.OutstandingProxyRequests, + prometheus.GaugeValue, + instance.OutstandingProxyRequests, + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.ProxyRequestsPerSec, + prometheus.CounterValue, + instance.ProxyRequestsPerSec, + labelName, + ) + } + return nil +} + +// Perflib: [24618] MSExchange OWA +type perflibOWA struct { + CurrentUniqueUsers float64 `perflib:"Current Unique Users"` + RequestsPerSec float64 `perflib:"Requests/sec"` +} + +func (c *exchangeCollector) collectOWA(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + var data []perflibOWA + if err := unmarshalObject(ctx.perfObjects["MSExchange OWA"], &data); err != nil { + return err + } + + for _, owa := range data { + ch <- prometheus.MustNewConstMetric( + c.CurrentUniqueUsers, + prometheus.GaugeValue, + owa.CurrentUniqueUsers, + ) + ch <- prometheus.MustNewConstMetric( + c.OWARequestsPerSec, + prometheus.CounterValue, + owa.RequestsPerSec, + ) + } + return nil +} + +// Perflib: [25138] MSExchange ActiveSync +type perflibActiveSync struct { + RequestsPerSec float64 `perflib:"Requests/sec"` + PingCommandsPending float64 `perflib:"Ping Commands Pending"` + SyncCommandsPerSec float64 `perflib:"Sync Commands/sec"` +} + +func (c *exchangeCollector) collectActiveSync(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + var data []perflibActiveSync + if err := unmarshalObject(ctx.perfObjects["MSExchange ActiveSync"], &data); err != nil { + return err + } + + for _, instance := range data { + ch <- prometheus.MustNewConstMetric( + c.ActiveSyncRequestsPerSec, + prometheus.CounterValue, + instance.RequestsPerSec, + ) + ch <- prometheus.MustNewConstMetric( + c.PingCommandsPending, + prometheus.GaugeValue, + instance.PingCommandsPending, + ) + ch <- prometheus.MustNewConstMetric( + c.SyncCommandsPerSec, + prometheus.CounterValue, + instance.SyncCommandsPerSec, + ) + } + return nil +} + +// Perflib: [29366] MSExchange RpcClientAccess +type perflibRPCClientAccess struct { + RPCAveragedLatency float64 `perflib:"RPC Averaged Latency"` + RPCRequests float64 `perflib:"RPC Requests"` + ActiveUserCount float64 `perflib:"Active User Count"` + ConnectionCount float64 `perflib:"Connection Count"` + RPCOperationsPerSec float64 `perflib:"RPC Operations/sec"` + UserCount float64 `perflib:"User Count"` +} + +func (c *exchangeCollector) collectRPC(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + var data []perflibRPCClientAccess + if err := unmarshalObject(ctx.perfObjects["MSExchange RpcClientAccess"], &data); err != nil { + return err + } + + for _, rpc := range data { + ch <- prometheus.MustNewConstMetric( + c.RPCAveragedLatency, + prometheus.GaugeValue, + c.msToSec(rpc.RPCAveragedLatency), + ) + ch <- prometheus.MustNewConstMetric( + c.RPCRequests, + prometheus.GaugeValue, + rpc.RPCRequests, + ) + ch <- prometheus.MustNewConstMetric( + c.ActiveUserCount, + prometheus.GaugeValue, + rpc.ActiveUserCount, + ) + ch <- prometheus.MustNewConstMetric( + c.ConnectionCount, + prometheus.GaugeValue, + rpc.ConnectionCount, + ) + ch <- prometheus.MustNewConstMetric( + c.RPCOperationsPerSec, + prometheus.CounterValue, + rpc.RPCOperationsPerSec, + ) + ch <- prometheus.MustNewConstMetric( + c.UserCount, + prometheus.GaugeValue, + rpc.UserCount, + ) + } + + return nil +} + +// Perflib: [20524] MSExchangeTransport Queues +type perflibTransportQueues struct { + Name string + + ExternalActiveRemoteDeliveryQueueLength float64 `perflib:"External Active Remote Delivery Queue Length"` + InternalActiveRemoteDeliveryQueueLength float64 `perflib:"Internal Active Remote Delivery Queue Length"` + ActiveMailboxDeliveryQueueLength float64 `perflib:"Active Mailbox Delivery Queue Length"` + RetryMailboxDeliveryQueueLength float64 `perflib:"Retry Mailbox Delivery Queue Length"` + UnreachableQueueLength float64 `perflib:"Unreachable Queue Length"` + ExternalLargestDeliveryQueueLength float64 `perflib:"External Largest Delivery Queue Length"` + InternalLargestDeliveryQueueLength float64 `perflib:"Internal Largest Delivery Queue Length"` + PoisonQueueLength float64 `perflib:"Poison Queue Length"` +} + +func (c *exchangeCollector) collectTransportQueues(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + var data []perflibTransportQueues + if err := unmarshalObject(ctx.perfObjects["MSExchangeTransport Queues"], &data); err != nil { + return err + } + + for _, queue := range data { + labelName := c.toLabelName(queue.Name) + if strings.HasSuffix(labelName, "_total") { + continue + } + ch <- prometheus.MustNewConstMetric( + c.ExternalActiveRemoteDeliveryQueueLength, + prometheus.GaugeValue, + queue.ExternalActiveRemoteDeliveryQueueLength, + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.InternalActiveRemoteDeliveryQueueLength, + prometheus.GaugeValue, + queue.InternalActiveRemoteDeliveryQueueLength, + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.ActiveMailboxDeliveryQueueLength, + prometheus.GaugeValue, + queue.ActiveMailboxDeliveryQueueLength, + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.RetryMailboxDeliveryQueueLength, + prometheus.GaugeValue, + queue.RetryMailboxDeliveryQueueLength, + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.UnreachableQueueLength, + prometheus.GaugeValue, + queue.UnreachableQueueLength, + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.ExternalLargestDeliveryQueueLength, + prometheus.GaugeValue, + queue.ExternalLargestDeliveryQueueLength, + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.InternalLargestDeliveryQueueLength, + prometheus.GaugeValue, + queue.InternalLargestDeliveryQueueLength, + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.PoisonQueueLength, + prometheus.GaugeValue, + queue.PoisonQueueLength, + labelName, + ) + } + return nil +} + +// Perflib: [19430] MSExchange WorkloadManagement Workloads +type perflibWorkloadManagementWorkloads struct { + Name string + + ActiveTasks float64 `perflib:"ActiveTasks"` + CompletedTasks float64 `perflib:"CompletedTasks"` + QueuedTasks float64 `perflib:"QueuedTasks"` + YieldedTasks float64 `perflib:"YieldedTasks"` + IsActive float64 `perflib:"Active"` +} + +func (c *exchangeCollector) collectWorkloadManagementWorkloads(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + var data []perflibWorkloadManagementWorkloads + if err := unmarshalObject(ctx.perfObjects["MSExchange WorkloadManagement Workloads"], &data); err != nil { + return err + } + + for _, instance := range data { + labelName := c.toLabelName(instance.Name) + if strings.HasSuffix(labelName, "_total") { + continue + } + ch <- prometheus.MustNewConstMetric( + c.ActiveTasks, + prometheus.GaugeValue, + instance.ActiveTasks, + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.CompletedTasks, + prometheus.CounterValue, + instance.CompletedTasks, + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.QueuedTasks, + prometheus.CounterValue, + instance.QueuedTasks, + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.YieldedTasks, + prometheus.CounterValue, + instance.YieldedTasks, + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.IsActive, + prometheus.GaugeValue, + instance.IsActive, + labelName, + ) + } + + return nil +} + +// [29240] MSExchangeAutodiscover +type perflibAutodiscover struct { + RequestsPerSec float64 `perflib:"Requests/sec"` +} + +func (c *exchangeCollector) collectAutoDiscover(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + var data []perflibAutodiscover + if err := unmarshalObject(ctx.perfObjects["MSExchangeAutodiscover"], &data); err != nil { + return err + } + for _, autodisc := range data { + ch <- prometheus.MustNewConstMetric( + c.AutodiscoverRequestsPerSec, + prometheus.CounterValue, + autodisc.RequestsPerSec, + ) + } + return nil +} + +// toLabelName converts strings to lowercase and replaces all whitespace and dots with underscores +func (c *exchangeCollector) toLabelName(name string) string { + s := strings.ReplaceAll(strings.Join(strings.Fields(strings.ToLower(name)), "_"), ".", "_") + s = strings.ReplaceAll(s, "__", "_") + return s +} + +// msToSec converts from ms to seconds +func (c *exchangeCollector) msToSec(t float64) float64 { + return t / 1000 +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/fsrmquota.go b/vendor/github.com/prometheus-community/windows_exporter/collector/fsrmquota.go new file mode 100644 index 000000000000..29edec20f48a --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/fsrmquota.go @@ -0,0 +1,187 @@ +package collector + +import ( + "github.com/StackExchange/wmi" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +func init() { + registerCollector("fsrmquota", newFSRMQuotaCollector) +} + +type FSRMQuotaCollector struct { + QuotasCount *prometheus.Desc + Path *prometheus.Desc + PeakUsage *prometheus.Desc + Size *prometheus.Desc + Usage *prometheus.Desc + + Description *prometheus.Desc + Disabled *prometheus.Desc + MatchesTemplate *prometheus.Desc + SoftLimit *prometheus.Desc + Template *prometheus.Desc +} + +func newFSRMQuotaCollector() (Collector, error) { + const subsystem = "fsrmquota" + return &FSRMQuotaCollector{ + QuotasCount: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "count"), + "Number of Quotas", + nil, + nil, + ), + PeakUsage: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "peak_usage_bytes"), + "The highest amount of disk space usage charged to this quota. (PeakUsage)", + []string{"path", "template"}, + nil, + ), + Size: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "size_bytes"), + "The size of the quota. (Size)", + []string{"path", "template"}, + nil, + ), + Usage: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "usage_bytes"), + "The current amount of disk space usage charged to this quota. (Usage)", + []string{"path", "template"}, + nil, + ), + Description: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "description"), + "Description of the quota (Description)", + []string{"path", "template", "description"}, + nil, + ), + Disabled: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "disabled"), + "If 1, the quota is disabled. The default value is 0. (Disabled)", + []string{"path", "template"}, + nil, + ), + SoftLimit: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "softlimit"), + "If 1, the quota is a soft limit. If 0, the quota is a hard limit. The default value is 0. Optional (SoftLimit)", + []string{"path", "template"}, + nil, + ), + Template: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "template"), + "Quota template name. (Template)", + []string{"path", "template"}, + nil, + ), + MatchesTemplate: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "matchestemplate"), + "If 1, the property values of this quota match those values of the template from which it was derived. (MatchesTemplate)", + []string{"path", "template"}, + nil, + ), + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *FSRMQuotaCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + log.Error("failed collecting fsrmquota metrics:", desc, err) + return err + } + return nil +} + +// MSFT_FSRMQuota docs: +// https://docs.microsoft.com/en-us/previous-versions/windows/desktop/fsrm/msft-fsrmquota +type MSFT_FSRMQuota struct { + Name string + + Path string + PeakUsage uint64 + Size uint64 + Usage uint64 + Description string + Template string + //Threshold string + Disabled bool + MatchesTemplate bool + SoftLimit bool +} + +func (c *FSRMQuotaCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []MSFT_FSRMQuota + q := queryAll(&dst) + + var count int + + if err := wmi.QueryNamespace(q, &dst, "root/microsoft/windows/fsrm"); err != nil { + return nil, err + } + + for _, quota := range dst { + + count++ + path := quota.Path + template := quota.Template + Description := quota.Description + + ch <- prometheus.MustNewConstMetric( + c.PeakUsage, + prometheus.GaugeValue, + float64(quota.PeakUsage), + path, + template, + ) + ch <- prometheus.MustNewConstMetric( + c.Size, + prometheus.GaugeValue, + float64(quota.Size), + path, + template, + ) + ch <- prometheus.MustNewConstMetric( + c.Usage, + prometheus.GaugeValue, + float64(quota.Usage), + path, + template, + ) + ch <- prometheus.MustNewConstMetric( + c.Description, + prometheus.GaugeValue, + 1.0, + path, template, Description, + ) + ch <- prometheus.MustNewConstMetric( + c.Disabled, + prometheus.GaugeValue, + boolToFloat(quota.Disabled), + path, + template, + ) + ch <- prometheus.MustNewConstMetric( + c.MatchesTemplate, + prometheus.GaugeValue, + boolToFloat(quota.MatchesTemplate), + path, + template, + ) + ch <- prometheus.MustNewConstMetric( + c.SoftLimit, + prometheus.GaugeValue, + boolToFloat(quota.SoftLimit), + path, + template, + ) + } + + ch <- prometheus.MustNewConstMetric( + c.QuotasCount, + prometheus.GaugeValue, + float64(count), + ) + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/hyperv.go b/vendor/github.com/prometheus-community/windows_exporter/collector/hyperv.go new file mode 100644 index 000000000000..5f47639029ce --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/hyperv.go @@ -0,0 +1,1432 @@ +// +build windows + +package collector + +import ( + "strings" + + "github.com/StackExchange/wmi" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +func init() { + registerCollector("hyperv", NewHyperVCollector) +} + +// HyperVCollector is a Prometheus collector for hyper-v +type HyperVCollector struct { + // Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary + HealthCritical *prometheus.Desc + HealthOk *prometheus.Desc + + // Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition + PhysicalPagesAllocated *prometheus.Desc + PreferredNUMANodeIndex *prometheus.Desc + RemotePhysicalPages *prometheus.Desc + + // Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition + AddressSpaces *prometheus.Desc + AttachedDevices *prometheus.Desc + DepositedPages *prometheus.Desc + DeviceDMAErrors *prometheus.Desc + DeviceInterruptErrors *prometheus.Desc + DeviceInterruptMappings *prometheus.Desc + DeviceInterruptThrottleEvents *prometheus.Desc + GPAPages *prometheus.Desc + GPASpaceModifications *prometheus.Desc + IOTLBFlushCost *prometheus.Desc + IOTLBFlushes *prometheus.Desc + RecommendedVirtualTLBSize *prometheus.Desc + SkippedTimerTicks *prometheus.Desc + Value1Gdevicepages *prometheus.Desc + Value1GGPApages *prometheus.Desc + Value2Mdevicepages *prometheus.Desc + Value2MGPApages *prometheus.Desc + Value4Kdevicepages *prometheus.Desc + Value4KGPApages *prometheus.Desc + VirtualTLBFlushEntires *prometheus.Desc + VirtualTLBPages *prometheus.Desc + + // Win32_PerfRawData_HvStats_HyperVHypervisor + LogicalProcessors *prometheus.Desc + VirtualProcessors *prometheus.Desc + + // Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor + HostGuestRunTime *prometheus.Desc + HostHypervisorRunTime *prometheus.Desc + HostRemoteRunTime *prometheus.Desc + HostTotalRunTime *prometheus.Desc + + // Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor + VMGuestRunTime *prometheus.Desc + VMHypervisorRunTime *prometheus.Desc + VMRemoteRunTime *prometheus.Desc + VMTotalRunTime *prometheus.Desc + + // Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch + BroadcastPacketsReceived *prometheus.Desc + BroadcastPacketsSent *prometheus.Desc + Bytes *prometheus.Desc + BytesReceived *prometheus.Desc + BytesSent *prometheus.Desc + DirectedPacketsReceived *prometheus.Desc + DirectedPacketsSent *prometheus.Desc + DroppedPacketsIncoming *prometheus.Desc + DroppedPacketsOutgoing *prometheus.Desc + ExtensionsDroppedPacketsIncoming *prometheus.Desc + ExtensionsDroppedPacketsOutgoing *prometheus.Desc + LearnedMacAddresses *prometheus.Desc + MulticastPacketsReceived *prometheus.Desc + MulticastPacketsSent *prometheus.Desc + NumberofSendChannelMoves *prometheus.Desc + NumberofVMQMoves *prometheus.Desc + PacketsFlooded *prometheus.Desc + Packets *prometheus.Desc + PacketsReceived *prometheus.Desc + PacketsSent *prometheus.Desc + PurgedMacAddresses *prometheus.Desc + + // Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter + AdapterBytesDropped *prometheus.Desc + AdapterBytesReceived *prometheus.Desc + AdapterBytesSent *prometheus.Desc + AdapterFramesDropped *prometheus.Desc + AdapterFramesReceived *prometheus.Desc + AdapterFramesSent *prometheus.Desc + + // Win32_PerfRawData_Counters_HyperVVirtualStorageDevice + VMStorageErrorCount *prometheus.Desc + VMStorageQueueLength *prometheus.Desc + VMStorageReadBytes *prometheus.Desc + VMStorageReadOperations *prometheus.Desc + VMStorageWriteBytes *prometheus.Desc + VMStorageWriteOperations *prometheus.Desc + + // Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter + VMNetworkBytesReceived *prometheus.Desc + VMNetworkBytesSent *prometheus.Desc + VMNetworkDroppedPacketsIncoming *prometheus.Desc + VMNetworkDroppedPacketsOutgoing *prometheus.Desc + VMNetworkPacketsReceived *prometheus.Desc + VMNetworkPacketsSent *prometheus.Desc +} + +// NewHyperVCollector ... +func NewHyperVCollector() (Collector, error) { + buildSubsystemName := func(component string) string { return "hyperv_" + component } + return &HyperVCollector{ + HealthCritical: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("health"), "critical"), + "This counter represents the number of virtual machines with critical health", + nil, + nil, + ), + HealthOk: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("health"), "ok"), + "This counter represents the number of virtual machines with ok health", + nil, + nil, + ), + + // + + PhysicalPagesAllocated: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vid"), "physical_pages_allocated"), + "The number of physical pages allocated", + []string{"vm"}, + nil, + ), + PreferredNUMANodeIndex: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vid"), "preferred_numa_node_index"), + "The preferred NUMA node index associated with this partition", + []string{"vm"}, + nil, + ), + RemotePhysicalPages: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vid"), "remote_physical_pages"), + "The number of physical pages not allocated from the preferred NUMA node", + []string{"vm"}, + nil, + ), + + // + + AddressSpaces: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "address_spaces"), + "The number of address spaces in the virtual TLB of the partition", + nil, + nil, + ), + AttachedDevices: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "attached_devices"), + "The number of devices attached to the partition", + nil, + nil, + ), + DepositedPages: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "deposited_pages"), + "The number of pages deposited into the partition", + nil, + nil, + ), + DeviceDMAErrors: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "device_dma_errors"), + "An indicator of illegal DMA requests generated by all devices assigned to the partition", + nil, + nil, + ), + DeviceInterruptErrors: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "device_interrupt_errors"), + "An indicator of illegal interrupt requests generated by all devices assigned to the partition", + nil, + nil, + ), + DeviceInterruptMappings: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "device_interrupt_mappings"), + "The number of device interrupt mappings used by the partition", + nil, + nil, + ), + DeviceInterruptThrottleEvents: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "device_interrupt_throttle_events"), + "The number of times an interrupt from a device assigned to the partition was temporarily throttled because the device was generating too many interrupts", + nil, + nil, + ), + GPAPages: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "preferred_numa_node_index"), + "The number of pages present in the GPA space of the partition (zero for root partition)", + nil, + nil, + ), + GPASpaceModifications: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "gpa_space_modifications"), + "The rate of modifications to the GPA space of the partition", + nil, + nil, + ), + IOTLBFlushCost: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "io_tlb_flush_cost"), + "The average time (in nanoseconds) spent processing an I/O TLB flush", + nil, + nil, + ), + IOTLBFlushes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "io_tlb_flush"), + "The rate of flushes of I/O TLBs of the partition", + nil, + nil, + ), + RecommendedVirtualTLBSize: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "recommended_virtual_tlb_size"), + "The recommended number of pages to be deposited for the virtual TLB", + nil, + nil, + ), + SkippedTimerTicks: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "physical_pages_allocated"), + "The number of timer interrupts skipped for the partition", + nil, + nil, + ), + Value1Gdevicepages: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "1G_device_pages"), + "The number of 1G pages present in the device space of the partition", + nil, + nil, + ), + Value1GGPApages: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "1G_gpa_pages"), + "The number of 1G pages present in the GPA space of the partition", + nil, + nil, + ), + Value2Mdevicepages: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "2M_device_pages"), + "The number of 2M pages present in the device space of the partition", + nil, + nil, + ), + Value2MGPApages: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "2M_gpa_pages"), + "The number of 2M pages present in the GPA space of the partition", + nil, + nil, + ), + Value4Kdevicepages: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "4K_device_pages"), + "The number of 4K pages present in the device space of the partition", + nil, + nil, + ), + Value4KGPApages: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "4K_gpa_pages"), + "The number of 4K pages present in the GPA space of the partition", + nil, + nil, + ), + VirtualTLBFlushEntires: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "virtual_tlb_flush_entires"), + "The rate of flushes of the entire virtual TLB", + nil, + nil, + ), + VirtualTLBPages: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "virtual_tlb_pages"), + "The number of pages used by the virtual TLB of the partition", + nil, + nil, + ), + + // + + VirtualProcessors: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("hypervisor"), "virtual_processors"), + "The number of virtual processors present in the system", + nil, + nil, + ), + LogicalProcessors: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("hypervisor"), "logical_processors"), + "The number of logical processors present in the system", + nil, + nil, + ), + + // + + HostGuestRunTime: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("host_cpu"), "guest_run_time"), + "The time spent by the virtual processor in guest code", + []string{"core"}, + nil, + ), + HostHypervisorRunTime: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("host_cpu"), "hypervisor_run_time"), + "The time spent by the virtual processor in hypervisor code", + []string{"core"}, + nil, + ), + HostRemoteRunTime: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("host_cpu"), "remote_run_time"), + "The time spent by the virtual processor running on a remote node", + []string{"core"}, + nil, + ), + HostTotalRunTime: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("host_cpu"), "total_run_time"), + "The time spent by the virtual processor in guest and hypervisor code", + []string{"core"}, + nil, + ), + + // + + VMGuestRunTime: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vm_cpu"), "guest_run_time"), + "The time spent by the virtual processor in guest code", + []string{"vm", "core"}, + nil, + ), + VMHypervisorRunTime: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vm_cpu"), "hypervisor_run_time"), + "The time spent by the virtual processor in hypervisor code", + []string{"vm", "core"}, + nil, + ), + VMRemoteRunTime: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vm_cpu"), "remote_run_time"), + "The time spent by the virtual processor running on a remote node", + []string{"vm", "core"}, + nil, + ), + VMTotalRunTime: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vm_cpu"), "total_run_time"), + "The time spent by the virtual processor in guest and hypervisor code", + []string{"vm", "core"}, + nil, + ), + + // + BroadcastPacketsReceived: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "broadcast_packets_received_total"), + "This represents the total number of broadcast packets received per second by the virtual switch", + []string{"vswitch"}, + nil, + ), + BroadcastPacketsSent: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "broadcast_packets_sent_total"), + "This represents the total number of broadcast packets sent per second by the virtual switch", + []string{"vswitch"}, + nil, + ), + Bytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "bytes_total"), + "This represents the total number of bytes per second traversing the virtual switch", + []string{"vswitch"}, + nil, + ), + BytesReceived: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "bytes_received_total"), + "This represents the total number of bytes received per second by the virtual switch", + []string{"vswitch"}, + nil, + ), + BytesSent: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "bytes_sent_total"), + "This represents the total number of bytes sent per second by the virtual switch", + []string{"vswitch"}, + nil, + ), + DirectedPacketsReceived: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "directed_packets_received_total"), + "This represents the total number of directed packets received per second by the virtual switch", + []string{"vswitch"}, + nil, + ), + DirectedPacketsSent: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "directed_packets_send_total"), + "This represents the total number of directed packets sent per second by the virtual switch", + []string{"vswitch"}, + nil, + ), + DroppedPacketsIncoming: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "dropped_packets_incoming_total"), + "This represents the total number of packet dropped per second by the virtual switch in the incoming direction", + []string{"vswitch"}, + nil, + ), + DroppedPacketsOutgoing: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "dropped_packets_outcoming_total"), + "This represents the total number of packet dropped per second by the virtual switch in the outgoing direction", + []string{"vswitch"}, + nil, + ), + ExtensionsDroppedPacketsIncoming: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "extensions_dropped_packets_incoming_total"), + "This represents the total number of packet dropped per second by the virtual switch extensions in the incoming direction", + []string{"vswitch"}, + nil, + ), + ExtensionsDroppedPacketsOutgoing: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "extensions_dropped_packets_outcoming_total"), + "This represents the total number of packet dropped per second by the virtual switch extensions in the outgoing direction", + []string{"vswitch"}, + nil, + ), + LearnedMacAddresses: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "learned_mac_addresses_total"), + "This counter represents the total number of learned MAC addresses of the virtual switch", + []string{"vswitch"}, + nil, + ), + MulticastPacketsReceived: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "multicast_packets_received_total"), + "This represents the total number of multicast packets received per second by the virtual switch", + []string{"vswitch"}, + nil, + ), + MulticastPacketsSent: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "multicast_packets_sent_total"), + "This represents the total number of multicast packets sent per second by the virtual switch", + []string{"vswitch"}, + nil, + ), + NumberofSendChannelMoves: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "number_of_send_channel_moves_total"), + "This represents the total number of send channel moves per second on this virtual switch", + []string{"vswitch"}, + nil, + ), + NumberofVMQMoves: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "number_of_vmq_moves_total"), + "This represents the total number of VMQ moves per second on this virtual switch", + []string{"vswitch"}, + nil, + ), + PacketsFlooded: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "packets_flooded_total"), + "This counter represents the total number of packets flooded by the virtual switch", + []string{"vswitch"}, + nil, + ), + Packets: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "packets_total"), + "This represents the total number of packets per second traversing the virtual switch", + []string{"vswitch"}, + nil, + ), + PacketsReceived: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "packets_received_total"), + "This represents the total number of packets received per second by the virtual switch", + []string{"vswitch"}, + nil, + ), + PacketsSent: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "packets_sent_total"), + "This represents the total number of packets send per second by the virtual switch", + []string{"vswitch"}, + nil, + ), + PurgedMacAddresses: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "purged_mac_addresses_total"), + "This counter represents the total number of purged MAC addresses of the virtual switch", + []string{"vswitch"}, + nil, + ), + + // + + AdapterBytesDropped: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("ethernet"), "bytes_dropped"), + "Bytes Dropped is the number of bytes dropped on the network adapter", + []string{"adapter"}, + nil, + ), + AdapterBytesReceived: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("ethernet"), "bytes_received"), + "Bytes received is the number of bytes received on the network adapter", + []string{"adapter"}, + nil, + ), + AdapterBytesSent: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("ethernet"), "bytes_sent"), + "Bytes sent is the number of bytes sent over the network adapter", + []string{"adapter"}, + nil, + ), + AdapterFramesDropped: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("ethernet"), "frames_dropped"), + "Frames Dropped is the number of frames dropped on the network adapter", + []string{"adapter"}, + nil, + ), + AdapterFramesReceived: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("ethernet"), "frames_received"), + "Frames received is the number of frames received on the network adapter", + []string{"adapter"}, + nil, + ), + AdapterFramesSent: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("ethernet"), "frames_sent"), + "Frames sent is the number of frames sent over the network adapter", + []string{"adapter"}, + nil, + ), + + // + + VMStorageErrorCount: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vm_device"), "error_count"), + "This counter represents the total number of errors that have occurred on this virtual device", + []string{"vm_device"}, + nil, + ), + VMStorageQueueLength: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vm_device"), "queue_length"), + "This counter represents the current queue length on this virtual device", + []string{"vm_device"}, + nil, + ), + VMStorageReadBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vm_device"), "bytes_read"), + "This counter represents the total number of bytes that have been read per second on this virtual device", + []string{"vm_device"}, + nil, + ), + VMStorageReadOperations: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vm_device"), "operations_read"), + "This counter represents the number of read operations that have occurred per second on this virtual device", + []string{"vm_device"}, + nil, + ), + VMStorageWriteBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vm_device"), "bytes_written"), + "This counter represents the total number of bytes that have been written per second on this virtual device", + []string{"vm_device"}, + nil, + ), + VMStorageWriteOperations: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vm_device"), "operations_written"), + "This counter represents the number of write operations that have occurred per second on this virtual device", + []string{"vm_device"}, + nil, + ), + + // + + VMNetworkBytesReceived: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vm_interface"), "bytes_received"), + "This counter represents the total number of bytes received per second by the network adapter", + []string{"vm_interface"}, + nil, + ), + VMNetworkBytesSent: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vm_interface"), "bytes_sent"), + "This counter represents the total number of bytes sent per second by the network adapter", + []string{"vm_interface"}, + nil, + ), + VMNetworkDroppedPacketsIncoming: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vm_interface"), "packets_incoming_dropped"), + "This counter represents the total number of dropped packets per second in the incoming direction of the network adapter", + []string{"vm_interface"}, + nil, + ), + VMNetworkDroppedPacketsOutgoing: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vm_interface"), "packets_outgoing_dropped"), + "This counter represents the total number of dropped packets per second in the outgoing direction of the network adapter", + []string{"vm_interface"}, + nil, + ), + VMNetworkPacketsReceived: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vm_interface"), "packets_received"), + "This counter represents the total number of packets received per second by the network adapter", + []string{"vm_interface"}, + nil, + ), + VMNetworkPacketsSent: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, buildSubsystemName("vm_interface"), "packets_sent"), + "This counter represents the total number of packets sent per second by the network adapter", + []string{"vm_interface"}, + nil, + ), + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *HyperVCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collectVmHealth(ch); err != nil { + log.Error("failed collecting hyperV health status metrics:", desc, err) + return err + } + + if desc, err := c.collectVmVid(ch); err != nil { + log.Error("failed collecting hyperV pages metrics:", desc, err) + return err + } + + if desc, err := c.collectVmHv(ch); err != nil { + log.Error("failed collecting hyperV hv status metrics:", desc, err) + return err + } + + if desc, err := c.collectVmProcessor(ch); err != nil { + log.Error("failed collecting hyperV processor metrics:", desc, err) + return err + } + + if desc, err := c.collectHostCpuUsage(ch); err != nil { + log.Error("failed collecting hyperV host CPU metrics:", desc, err) + return err + } + + if desc, err := c.collectVmCpuUsage(ch); err != nil { + log.Error("failed collecting hyperV VM CPU metrics:", desc, err) + return err + } + + if desc, err := c.collectVmSwitch(ch); err != nil { + log.Error("failed collecting hyperV switch metrics:", desc, err) + return err + } + + if desc, err := c.collectVmEthernet(ch); err != nil { + log.Error("failed collecting hyperV ethernet metrics:", desc, err) + return err + } + + if desc, err := c.collectVmStorage(ch); err != nil { + log.Error("failed collecting hyperV virtual storage metrics:", desc, err) + return err + } + + if desc, err := c.collectVmNetwork(ch); err != nil { + log.Error("failed collecting hyperV virtual network metrics:", desc, err) + return err + } + + return nil +} + +// Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary vm health status +type Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary struct { + HealthCritical uint32 + HealthOk uint32 +} + +func (c *HyperVCollector) collectVmHealth(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, health := range dst { + ch <- prometheus.MustNewConstMetric( + c.HealthCritical, + prometheus.GaugeValue, + float64(health.HealthCritical), + ) + + ch <- prometheus.MustNewConstMetric( + c.HealthOk, + prometheus.GaugeValue, + float64(health.HealthOk), + ) + + } + + return nil, nil +} + +// Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition .., +type Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition struct { + Name string + PhysicalPagesAllocated uint64 + PreferredNUMANodeIndex uint64 + RemotePhysicalPages uint64 +} + +func (c *HyperVCollector) collectVmVid(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, page := range dst { + if strings.Contains(page.Name, "_Total") { + continue + } + + ch <- prometheus.MustNewConstMetric( + c.PhysicalPagesAllocated, + prometheus.GaugeValue, + float64(page.PhysicalPagesAllocated), + page.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.PreferredNUMANodeIndex, + prometheus.GaugeValue, + float64(page.PreferredNUMANodeIndex), + page.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.RemotePhysicalPages, + prometheus.GaugeValue, + float64(page.RemotePhysicalPages), + page.Name, + ) + + } + + return nil, nil +} + +// Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition ... +type Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition struct { + Name string + AddressSpaces uint64 + AttachedDevices uint64 + DepositedPages uint64 + DeviceDMAErrors uint64 + DeviceInterruptErrors uint64 + DeviceInterruptMappings uint64 + DeviceInterruptThrottleEvents uint64 + GPAPages uint64 + GPASpaceModificationsPersec uint64 + IOTLBFlushCost uint64 + IOTLBFlushesPersec uint64 + RecommendedVirtualTLBSize uint64 + SkippedTimerTicks uint64 + Value1Gdevicepages uint64 + Value1GGPApages uint64 + Value2Mdevicepages uint64 + Value2MGPApages uint64 + Value4Kdevicepages uint64 + Value4KGPApages uint64 + VirtualTLBFlushEntiresPersec uint64 + VirtualTLBPages uint64 +} + +func (c *HyperVCollector) collectVmHv(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, obj := range dst { + if strings.Contains(obj.Name, "_Total") { + continue + } + + ch <- prometheus.MustNewConstMetric( + c.AddressSpaces, + prometheus.GaugeValue, + float64(obj.AddressSpaces), + ) + + ch <- prometheus.MustNewConstMetric( + c.AttachedDevices, + prometheus.GaugeValue, + float64(obj.AttachedDevices), + ) + + ch <- prometheus.MustNewConstMetric( + c.DepositedPages, + prometheus.GaugeValue, + float64(obj.DepositedPages), + ) + + ch <- prometheus.MustNewConstMetric( + c.DeviceDMAErrors, + prometheus.GaugeValue, + float64(obj.DeviceDMAErrors), + ) + + ch <- prometheus.MustNewConstMetric( + c.DeviceInterruptErrors, + prometheus.GaugeValue, + float64(obj.DeviceInterruptErrors), + ) + + ch <- prometheus.MustNewConstMetric( + c.DeviceInterruptThrottleEvents, + prometheus.GaugeValue, + float64(obj.DeviceInterruptThrottleEvents), + ) + + ch <- prometheus.MustNewConstMetric( + c.GPAPages, + prometheus.GaugeValue, + float64(obj.GPAPages), + ) + + ch <- prometheus.MustNewConstMetric( + c.GPASpaceModifications, + prometheus.CounterValue, + float64(obj.GPASpaceModificationsPersec), + ) + + ch <- prometheus.MustNewConstMetric( + c.IOTLBFlushCost, + prometheus.GaugeValue, + float64(obj.IOTLBFlushCost), + ) + + ch <- prometheus.MustNewConstMetric( + c.IOTLBFlushes, + prometheus.CounterValue, + float64(obj.IOTLBFlushesPersec), + ) + + ch <- prometheus.MustNewConstMetric( + c.RecommendedVirtualTLBSize, + prometheus.GaugeValue, + float64(obj.RecommendedVirtualTLBSize), + ) + + ch <- prometheus.MustNewConstMetric( + c.SkippedTimerTicks, + prometheus.GaugeValue, + float64(obj.SkippedTimerTicks), + ) + + ch <- prometheus.MustNewConstMetric( + c.Value1Gdevicepages, + prometheus.GaugeValue, + float64(obj.Value1Gdevicepages), + ) + + ch <- prometheus.MustNewConstMetric( + c.Value1GGPApages, + prometheus.GaugeValue, + float64(obj.Value1GGPApages), + ) + + ch <- prometheus.MustNewConstMetric( + c.Value2Mdevicepages, + prometheus.GaugeValue, + float64(obj.Value2Mdevicepages), + ) + ch <- prometheus.MustNewConstMetric( + c.Value2MGPApages, + prometheus.GaugeValue, + float64(obj.Value2MGPApages), + ) + ch <- prometheus.MustNewConstMetric( + c.Value4Kdevicepages, + prometheus.GaugeValue, + float64(obj.Value4Kdevicepages), + ) + ch <- prometheus.MustNewConstMetric( + c.Value4KGPApages, + prometheus.GaugeValue, + float64(obj.Value4KGPApages), + ) + ch <- prometheus.MustNewConstMetric( + c.VirtualTLBFlushEntires, + prometheus.CounterValue, + float64(obj.VirtualTLBFlushEntiresPersec), + ) + ch <- prometheus.MustNewConstMetric( + c.VirtualTLBPages, + prometheus.GaugeValue, + float64(obj.VirtualTLBPages), + ) + + } + + return nil, nil +} + +// Win32_PerfRawData_HvStats_HyperVHypervisor ... +type Win32_PerfRawData_HvStats_HyperVHypervisor struct { + LogicalProcessors uint64 + VirtualProcessors uint64 +} + +func (c *HyperVCollector) collectVmProcessor(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_HvStats_HyperVHypervisor + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, obj := range dst { + + ch <- prometheus.MustNewConstMetric( + c.LogicalProcessors, + prometheus.GaugeValue, + float64(obj.LogicalProcessors), + ) + + ch <- prometheus.MustNewConstMetric( + c.VirtualProcessors, + prometheus.GaugeValue, + float64(obj.VirtualProcessors), + ) + + } + + return nil, nil +} + +// Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor ... +type Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor struct { + Name string + PercentGuestRunTime uint64 + PercentHypervisorRunTime uint64 + PercentRemoteRunTime uint64 + PercentTotalRunTime uint64 +} + +func (c *HyperVCollector) collectHostCpuUsage(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, obj := range dst { + if strings.Contains(obj.Name, "_Total") { + continue + } + // The name format is Root VP + parts := strings.Split(obj.Name, " ") + if len(parts) != 3 { + log.Warnf("Unexpected format of Name in collectHostCpuUsage: %q", obj.Name) + continue + } + coreId := parts[2] + + ch <- prometheus.MustNewConstMetric( + c.HostGuestRunTime, + prometheus.GaugeValue, + float64(obj.PercentGuestRunTime), + coreId, + ) + + ch <- prometheus.MustNewConstMetric( + c.HostHypervisorRunTime, + prometheus.GaugeValue, + float64(obj.PercentHypervisorRunTime), + coreId, + ) + + ch <- prometheus.MustNewConstMetric( + c.HostRemoteRunTime, + prometheus.GaugeValue, + float64(obj.PercentRemoteRunTime), + coreId, + ) + + ch <- prometheus.MustNewConstMetric( + c.HostTotalRunTime, + prometheus.GaugeValue, + float64(obj.PercentTotalRunTime), + coreId, + ) + + } + + return nil, nil +} + +// Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor ... +type Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor struct { + Name string + PercentGuestRunTime uint64 + PercentHypervisorRunTime uint64 + PercentRemoteRunTime uint64 + PercentTotalRunTime uint64 +} + +func (c *HyperVCollector) collectVmCpuUsage(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, obj := range dst { + if strings.Contains(obj.Name, "_Total") { + continue + } + // The name format is :Hv VP + parts := strings.Split(obj.Name, ":") + if len(parts) != 2 { + log.Warnf("Unexpected format of Name in collectVmCpuUsage: %q, expected %q. Skipping.", obj.Name, ":Hv VP ") + continue + } + coreParts := strings.Split(parts[1], " ") + if len(coreParts) != 3 { + log.Warnf("Unexpected format of core identifier in collectVmCpuUsage: %q, expected %q. Skipping.", parts[1], "Hv VP ") + continue + } + vmName := parts[0] + coreId := coreParts[2] + + ch <- prometheus.MustNewConstMetric( + c.VMGuestRunTime, + prometheus.GaugeValue, + float64(obj.PercentGuestRunTime), + vmName, coreId, + ) + + ch <- prometheus.MustNewConstMetric( + c.VMHypervisorRunTime, + prometheus.GaugeValue, + float64(obj.PercentHypervisorRunTime), + vmName, coreId, + ) + + ch <- prometheus.MustNewConstMetric( + c.VMRemoteRunTime, + prometheus.GaugeValue, + float64(obj.PercentRemoteRunTime), + vmName, coreId, + ) + + ch <- prometheus.MustNewConstMetric( + c.VMTotalRunTime, + prometheus.GaugeValue, + float64(obj.PercentTotalRunTime), + vmName, coreId, + ) + + } + + return nil, nil +} + +// Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch ... +type Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch struct { + Name string + BroadcastPacketsReceivedPersec uint64 + BroadcastPacketsSentPersec uint64 + BytesPersec uint64 + BytesReceivedPersec uint64 + BytesSentPersec uint64 + DirectedPacketsReceivedPersec uint64 + DirectedPacketsSentPersec uint64 + DroppedPacketsIncomingPersec uint64 + DroppedPacketsOutgoingPersec uint64 + ExtensionsDroppedPacketsIncomingPersec uint64 + ExtensionsDroppedPacketsOutgoingPersec uint64 + LearnedMacAddresses uint64 + LearnedMacAddressesPersec uint64 + MulticastPacketsReceivedPersec uint64 + MulticastPacketsSentPersec uint64 + NumberofSendChannelMovesPersec uint64 + NumberofVMQMovesPersec uint64 + PacketsFlooded uint64 + PacketsFloodedPersec uint64 + PacketsPersec uint64 + PacketsReceivedPersec uint64 + PacketsSentPersec uint64 + PurgedMacAddresses uint64 + PurgedMacAddressesPersec uint64 +} + +func (c *HyperVCollector) collectVmSwitch(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, obj := range dst { + if strings.Contains(obj.Name, "_Total") { + continue + } + + ch <- prometheus.MustNewConstMetric( + c.BroadcastPacketsReceived, + prometheus.CounterValue, + float64(obj.BroadcastPacketsReceivedPersec), + obj.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.BroadcastPacketsSent, + prometheus.CounterValue, + float64(obj.BroadcastPacketsSentPersec), + obj.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.Bytes, + prometheus.CounterValue, + float64(obj.BytesPersec), + obj.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.BytesReceived, + prometheus.CounterValue, + float64(obj.BytesReceivedPersec), + obj.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.BytesSent, + prometheus.CounterValue, + float64(obj.BytesSentPersec), + obj.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.DirectedPacketsReceived, + prometheus.CounterValue, + float64(obj.DirectedPacketsReceivedPersec), + obj.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.DirectedPacketsSent, + prometheus.CounterValue, + float64(obj.DirectedPacketsSentPersec), + obj.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.DroppedPacketsIncoming, + prometheus.CounterValue, + float64(obj.DroppedPacketsIncomingPersec), + obj.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.DroppedPacketsOutgoing, + prometheus.CounterValue, + float64(obj.DroppedPacketsOutgoingPersec), + obj.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.ExtensionsDroppedPacketsIncoming, + prometheus.CounterValue, + float64(obj.ExtensionsDroppedPacketsIncomingPersec), + obj.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.ExtensionsDroppedPacketsOutgoing, + prometheus.CounterValue, + float64(obj.ExtensionsDroppedPacketsOutgoingPersec), + obj.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.LearnedMacAddresses, + prometheus.CounterValue, + float64(obj.LearnedMacAddresses), + obj.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.MulticastPacketsReceived, + prometheus.CounterValue, + float64(obj.MulticastPacketsReceivedPersec), + obj.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.MulticastPacketsSent, + prometheus.CounterValue, + float64(obj.MulticastPacketsSentPersec), + obj.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.NumberofSendChannelMoves, + prometheus.CounterValue, + float64(obj.NumberofSendChannelMovesPersec), + obj.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.NumberofVMQMoves, + prometheus.CounterValue, + float64(obj.NumberofVMQMovesPersec), + obj.Name, + ) + + // ... + ch <- prometheus.MustNewConstMetric( + c.PacketsFlooded, + prometheus.CounterValue, + float64(obj.PacketsFlooded), + obj.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.Packets, + prometheus.CounterValue, + float64(obj.PacketsPersec), + obj.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.PacketsReceived, + prometheus.CounterValue, + float64(obj.PacketsReceivedPersec), + obj.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.PurgedMacAddresses, + prometheus.CounterValue, + float64(obj.PurgedMacAddresses), + obj.Name, + ) + } + + return nil, nil +} + +// Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter ... +type Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter struct { + Name string + BytesDropped uint64 + BytesReceivedPersec uint64 + BytesSentPersec uint64 + FramesDropped uint64 + FramesReceivedPersec uint64 + FramesSentPersec uint64 +} + +func (c *HyperVCollector) collectVmEthernet(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, obj := range dst { + if strings.Contains(obj.Name, "_Total") { + continue + } + + ch <- prometheus.MustNewConstMetric( + c.AdapterBytesDropped, + prometheus.GaugeValue, + float64(obj.BytesDropped), + obj.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.AdapterBytesReceived, + prometheus.CounterValue, + float64(obj.BytesReceivedPersec), + obj.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.AdapterBytesSent, + prometheus.CounterValue, + float64(obj.BytesSentPersec), + obj.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.AdapterFramesReceived, + prometheus.CounterValue, + float64(obj.FramesReceivedPersec), + obj.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.AdapterFramesDropped, + prometheus.CounterValue, + float64(obj.FramesDropped), + obj.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.AdapterFramesSent, + prometheus.CounterValue, + float64(obj.FramesSentPersec), + obj.Name, + ) + + } + + return nil, nil +} + +// Win32_PerfRawData_Counters_HyperVVirtualStorageDevice ... +type Win32_PerfRawData_Counters_HyperVVirtualStorageDevice struct { + Name string + ErrorCount uint64 + QueueLength uint32 + ReadBytesPersec uint64 + ReadOperationsPerSec uint64 + WriteBytesPersec uint64 + WriteOperationsPerSec uint64 +} + +func (c *HyperVCollector) collectVmStorage(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_Counters_HyperVVirtualStorageDevice + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, obj := range dst { + if strings.Contains(obj.Name, "_Total") { + continue + } + + ch <- prometheus.MustNewConstMetric( + c.VMStorageErrorCount, + prometheus.CounterValue, + float64(obj.ErrorCount), + obj.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.VMStorageQueueLength, + prometheus.CounterValue, + float64(obj.QueueLength), + obj.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.VMStorageReadBytes, + prometheus.CounterValue, + float64(obj.ReadBytesPersec), + obj.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.VMStorageReadOperations, + prometheus.CounterValue, + float64(obj.ReadOperationsPerSec), + obj.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.VMStorageWriteBytes, + prometheus.CounterValue, + float64(obj.WriteBytesPersec), + obj.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.VMStorageWriteOperations, + prometheus.CounterValue, + float64(obj.WriteOperationsPerSec), + obj.Name, + ) + } + + return nil, nil +} + +// Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter ... +type Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter struct { + Name string + BytesReceivedPersec uint64 + BytesSentPersec uint64 + DroppedPacketsIncomingPersec uint64 + DroppedPacketsOutgoingPersec uint64 + PacketsReceivedPersec uint64 + PacketsSentPersec uint64 +} + +func (c *HyperVCollector) collectVmNetwork(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, obj := range dst { + if strings.Contains(obj.Name, "_Total") { + continue + } + + ch <- prometheus.MustNewConstMetric( + c.VMNetworkBytesReceived, + prometheus.CounterValue, + float64(obj.BytesReceivedPersec), + obj.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.VMNetworkBytesSent, + prometheus.CounterValue, + float64(obj.BytesSentPersec), + obj.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.VMNetworkDroppedPacketsIncoming, + prometheus.CounterValue, + float64(obj.DroppedPacketsIncomingPersec), + obj.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.VMNetworkDroppedPacketsOutgoing, + prometheus.CounterValue, + float64(obj.DroppedPacketsOutgoingPersec), + obj.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.VMNetworkPacketsReceived, + prometheus.CounterValue, + float64(obj.PacketsReceivedPersec), + obj.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.VMNetworkPacketsSent, + prometheus.CounterValue, + float64(obj.PacketsSentPersec), + obj.Name, + ) + } + + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/iis.go b/vendor/github.com/prometheus-community/windows_exporter/collector/iis.go new file mode 100644 index 000000000000..948758227552 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/iis.go @@ -0,0 +1,1965 @@ +// +build windows + +package collector + +import ( + "errors" + "fmt" + "regexp" + + "gopkg.in/alecthomas/kingpin.v2" + + "golang.org/x/sys/windows/registry" + + "github.com/StackExchange/wmi" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +func init() { + registerCollectorWithConfig("iis", func() Config { return &IISConfig{} }) +} + +type IISConfig struct { + SiteWhiteList string + SiteBlackList string + AppWhiteList string + AppBlackList string +} + +func (c *IISConfig) RegisterKingpin(ka *kingpin.Application) { + ka.Flag("collector.iis.site-whitelist", "Regexp of sites to whitelist. Site name must both match whitelist and not match blacklist to be included.").Default(".+").StringVar(&c.SiteWhiteList) + ka.Flag("collector.iis.site-blacklist", "Regexp of sites to blacklist. Site name must both match whitelist and not match blacklist to be included.").StringVar(&c.SiteBlackList) + ka.Flag("collector.iis.app-whitelist", "Regexp of apps to whitelist. App name must both match whitelist and not match blacklist to be included.").Default(".+").StringVar(&c.AppWhiteList) + ka.Flag("collector.iis.app-blacklist", "Regexp of apps to blacklist. App name must both match whitelist and not match blacklist to be included.").StringVar(&c.AppBlackList) +} + +func (c *IISConfig) Build() (Collector, error) { return NewIISCollector(c) } + +type simple_version struct { + major uint64 + minor uint64 +} + +func getIISVersion() simple_version { + k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\InetStp\`, registry.QUERY_VALUE) + if err != nil { + log.Warn("Couldn't open registry to determine IIS version:", err) + return simple_version{} + } + defer func() { + err = k.Close() + if err != nil { + log.Warnf("Failed to close registry key: %v", err) + } + }() + + major, _, err := k.GetIntegerValue("MajorVersion") + if err != nil { + log.Warn("Couldn't open registry to determine IIS version:", err) + return simple_version{} + } + minor, _, err := k.GetIntegerValue("MinorVersion") + if err != nil { + log.Warn("Couldn't open registry to determine IIS version:", err) + return simple_version{} + } + + log.Debugf("Detected IIS %d.%d\n", major, minor) + + return simple_version{ + major: major, + minor: minor, + } +} + +type IISCollector struct { + CurrentAnonymousUsers *prometheus.Desc + CurrentBlockedAsyncIORequests *prometheus.Desc + CurrentCGIRequests *prometheus.Desc + CurrentConnections *prometheus.Desc + CurrentISAPIExtensionRequests *prometheus.Desc + CurrentNonAnonymousUsers *prometheus.Desc + + TotalBytesReceived *prometheus.Desc + TotalBytesSent *prometheus.Desc + TotalAnonymousUsers *prometheus.Desc + TotalBlockedAsyncIORequests *prometheus.Desc + TotalCGIRequests *prometheus.Desc + TotalConnectionAttemptsAllInstances *prometheus.Desc + TotalRequests *prometheus.Desc + TotalFilesReceived *prometheus.Desc + TotalFilesSent *prometheus.Desc + TotalISAPIExtensionRequests *prometheus.Desc + TotalLockedErrors *prometheus.Desc + TotalLogonAttempts *prometheus.Desc + TotalNonAnonymousUsers *prometheus.Desc + TotalNotFoundErrors *prometheus.Desc + TotalRejectedAsyncIORequests *prometheus.Desc + + siteWhitelistPattern *regexp.Regexp + siteBlacklistPattern *regexp.Regexp + + CurrentApplicationPoolState *prometheus.Desc + CurrentApplicationPoolUptime *prometheus.Desc + CurrentWorkerProcesses *prometheus.Desc + MaximumWorkerProcesses *prometheus.Desc + RecentWorkerProcessFailures *prometheus.Desc + TimeSinceLastWorkerProcessFailure *prometheus.Desc + TotalApplicationPoolRecycles *prometheus.Desc + TotalApplicationPoolUptime *prometheus.Desc + TotalWorkerProcessesCreated *prometheus.Desc + TotalWorkerProcessFailures *prometheus.Desc + TotalWorkerProcessPingFailures *prometheus.Desc + TotalWorkerProcessShutdownFailures *prometheus.Desc + TotalWorkerProcessStartupFailures *prometheus.Desc + + // Worker process metrics (Win32_PerfRawData_W3SVCW3WPCounterProvider_W3SVCW3WP) + ActiveFlushedEntries *prometheus.Desc + + FileCacheMemoryUsage *prometheus.Desc + MaximumFileCacheMemoryUsage *prometheus.Desc + FileCacheFlushesTotal *prometheus.Desc + FileCacheQueriesTotal *prometheus.Desc + FileCacheHitsTotal *prometheus.Desc + FilesCached *prometheus.Desc + FilesCachedTotal *prometheus.Desc + FilesFlushedTotal *prometheus.Desc + + URICacheFlushesTotal *prometheus.Desc + URICacheQueriesTotal *prometheus.Desc + URICacheHitsTotal *prometheus.Desc + URIsCached *prometheus.Desc + URIsCachedTotal *prometheus.Desc + URIsFlushedTotal *prometheus.Desc + + MetadataCached *prometheus.Desc + MetadataCacheFlushes *prometheus.Desc + MetadataCacheQueriesTotal *prometheus.Desc + MetadataCacheHitsTotal *prometheus.Desc + MetadataCachedTotal *prometheus.Desc + MetadataFlushedTotal *prometheus.Desc + + OutputCacheActiveFlushedItems *prometheus.Desc + OutputCacheItems *prometheus.Desc + OutputCacheMemoryUsage *prometheus.Desc + OutputCacheQueriesTotal *prometheus.Desc + OutputCacheHitsTotal *prometheus.Desc + OutputCacheFlushedItemsTotal *prometheus.Desc + OutputCacheFlushesTotal *prometheus.Desc + + Threads *prometheus.Desc + MaximumThreads *prometheus.Desc + + RequestsTotal *prometheus.Desc + RequestsActive *prometheus.Desc + RequestErrorsTotal *prometheus.Desc + + WebSocketRequestsActive *prometheus.Desc + WebSocketConnectionAttempts *prometheus.Desc + WebSocketConnectionsAccepted *prometheus.Desc + WebSocketConnectionsRejected *prometheus.Desc + + // Server cache metrics (Win32_PerfRawData_W3SVC_WebServiceCache) + // Ugly names, but they collide with the Worker process cache names... + ServiceCache_ActiveFlushedEntries *prometheus.Desc + + ServiceCache_FileCacheMemoryUsage *prometheus.Desc + ServiceCache_MaximumFileCacheMemoryUsage *prometheus.Desc + ServiceCache_FileCacheFlushesTotal *prometheus.Desc + ServiceCache_FileCacheQueriesTotal *prometheus.Desc + ServiceCache_FileCacheHitsTotal *prometheus.Desc + ServiceCache_FilesCached *prometheus.Desc + ServiceCache_FilesCachedTotal *prometheus.Desc + ServiceCache_FilesFlushedTotal *prometheus.Desc + + ServiceCache_URICacheFlushesTotal *prometheus.Desc + ServiceCache_URICacheQueriesTotal *prometheus.Desc + ServiceCache_URICacheHitsTotal *prometheus.Desc + ServiceCache_URIsCached *prometheus.Desc + ServiceCache_URIsCachedTotal *prometheus.Desc + ServiceCache_URIsFlushedTotal *prometheus.Desc + + ServiceCache_MetadataCached *prometheus.Desc + ServiceCache_MetadataCacheFlushes *prometheus.Desc + ServiceCache_MetadataCacheQueriesTotal *prometheus.Desc + ServiceCache_MetadataCacheHitsTotal *prometheus.Desc + ServiceCache_MetadataCachedTotal *prometheus.Desc + ServiceCache_MetadataFlushedTotal *prometheus.Desc + + ServiceCache_OutputCacheActiveFlushedItems *prometheus.Desc + ServiceCache_OutputCacheItems *prometheus.Desc + ServiceCache_OutputCacheMemoryUsage *prometheus.Desc + ServiceCache_OutputCacheQueriesTotal *prometheus.Desc + ServiceCache_OutputCacheHitsTotal *prometheus.Desc + ServiceCache_OutputCacheFlushedItemsTotal *prometheus.Desc + ServiceCache_OutputCacheFlushesTotal *prometheus.Desc + + appWhitelistPattern *regexp.Regexp + appBlacklistPattern *regexp.Regexp + + iis_version simple_version +} + +// NewIISCollector ... +func NewIISCollector(c *IISConfig) (Collector, error) { + const subsystem = "iis" + + buildIIS := &IISCollector{ + // Websites + // Gauges + CurrentAnonymousUsers: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "current_anonymous_users"), + "Number of users who currently have an anonymous connection using the Web service (WebService.CurrentAnonymousUsers)", + []string{"site"}, + nil, + ), + CurrentBlockedAsyncIORequests: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "current_blocked_async_io_requests"), + "Current requests temporarily blocked due to bandwidth throttling settings (WebService.CurrentBlockedAsyncIORequests)", + []string{"site"}, + nil, + ), + CurrentCGIRequests: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "current_cgi_requests"), + "Current number of CGI requests being simultaneously processed by the Web service (WebService.CurrentCGIRequests)", + []string{"site"}, + nil, + ), + CurrentConnections: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "current_connections"), + "Current number of connections established with the Web service (WebService.CurrentConnections)", + []string{"site"}, + nil, + ), + CurrentISAPIExtensionRequests: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "current_isapi_extension_requests"), + "Current number of ISAPI requests being simultaneously processed by the Web service (WebService.CurrentISAPIExtensionRequests)", + []string{"site"}, + nil, + ), + CurrentNonAnonymousUsers: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "current_non_anonymous_users"), + "Number of users who currently have a non-anonymous connection using the Web service (WebService.CurrentNonAnonymousUsers)", + []string{"site"}, + nil, + ), + + // Counters + TotalBytesReceived: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "received_bytes_total"), + "Number of data bytes that have been received by the Web service (WebService.TotalBytesReceived)", + []string{"site"}, + nil, + ), + TotalBytesSent: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "sent_bytes_total"), + "Number of data bytes that have been sent by the Web service (WebService.TotalBytesSent)", + []string{"site"}, + nil, + ), + TotalAnonymousUsers: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "anonymous_users_total"), + "Total number of users who established an anonymous connection with the Web service (WebService.TotalAnonymousUsers)", + []string{"site"}, + nil, + ), + TotalBlockedAsyncIORequests: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "blocked_async_io_requests_total"), + "Total requests temporarily blocked due to bandwidth throttling settings (WebService.TotalBlockedAsyncIORequests)", + []string{"site"}, + nil, + ), + TotalCGIRequests: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "cgi_requests_total"), + "Total CGI requests is the total number of CGI requests (WebService.TotalCGIRequests)", + []string{"site"}, + nil, + ), + TotalConnectionAttemptsAllInstances: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "connection_attempts_all_instances_total"), + "Number of connections that have been attempted using the Web service (WebService.TotalConnectionAttemptsAllInstances)", + []string{"site"}, + nil, + ), + TotalRequests: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "requests_total"), + "Number of HTTP requests (WebService.TotalRequests)", + []string{"site", "method"}, + nil, + ), + TotalFilesReceived: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "files_received_total"), + "Number of files received by the Web service (WebService.TotalFilesReceived)", + []string{"site"}, + nil, + ), + TotalFilesSent: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "files_sent_total"), + "Number of files sent by the Web service (WebService.TotalFilesSent)", + []string{"site"}, + nil, + ), + TotalISAPIExtensionRequests: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "ipapi_extension_requests_total"), + "ISAPI Extension Requests received (WebService.TotalISAPIExtensionRequests)", + []string{"site"}, + nil, + ), + TotalLockedErrors: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "locked_errors_total"), + "Number of requests that couldn't be satisfied by the server because the requested resource was locked (WebService.TotalLockedErrors)", + []string{"site"}, + nil, + ), + TotalLogonAttempts: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "logon_attempts_total"), + "Number of logons attempts to the Web Service (WebService.TotalLogonAttempts)", + []string{"site"}, + nil, + ), + TotalNonAnonymousUsers: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "non_anonymous_users_total"), + "Number of users who established a non-anonymous connection with the Web service (WebService.TotalNonAnonymousUsers)", + []string{"site"}, + nil, + ), + TotalNotFoundErrors: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "not_found_errors_total"), + "Number of requests that couldn't be satisfied by the server because the requested document could not be found (WebService.TotalNotFoundErrors)", + []string{"site"}, + nil, + ), + TotalRejectedAsyncIORequests: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "rejected_async_io_requests_total"), + "Requests rejected due to bandwidth throttling settings (WebService.TotalRejectedAsyncIORequests)", + []string{"site"}, + nil, + ), + + // App Pools + // Guages + CurrentApplicationPoolState: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "current_application_pool_state"), + "The current status of the application pool (1 - Uninitialized, 2 - Initialized, 3 - Running, 4 - Disabling, 5 - Disabled, 6 - Shutdown Pending, 7 - Delete Pending) (CurrentApplicationPoolState)", + []string{"app", "state"}, + nil, + ), + CurrentApplicationPoolUptime: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "current_application_pool_start_time"), + "The unix timestamp for the application pool start time (CurrentApplicationPoolUptime)", + []string{"app"}, + nil, + ), + CurrentWorkerProcesses: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "current_worker_processes"), + "The current number of worker processes that are running in the application pool (CurrentWorkerProcesses)", + []string{"app"}, + nil, + ), + MaximumWorkerProcesses: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "maximum_worker_processes"), + "The maximum number of worker processes that have been created for the application pool since Windows Process Activation Service (WAS) started (MaximumWorkerProcesses)", + []string{"app"}, + nil, + ), + RecentWorkerProcessFailures: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "recent_worker_process_failures"), + "The number of times that worker processes for the application pool failed during the rapid-fail protection interval (RecentWorkerProcessFailures)", + []string{"app"}, + nil, + ), + + // Counters + TimeSinceLastWorkerProcessFailure: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "time_since_last_worker_process_failure"), + "The length of time, in seconds, since the last worker process failure occurred for the application pool (TimeSinceLastWorkerProcessFailure)", + []string{"app"}, + nil, + ), + TotalApplicationPoolRecycles: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "total_application_pool_recycles"), + "The number of times that the application pool has been recycled since Windows Process Activation Service (WAS) started (TotalApplicationPoolRecycles)", + []string{"app"}, + nil, + ), + TotalApplicationPoolUptime: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "total_application_pool_start_time"), + "The unix timestamp for the application pool of when the Windows Process Activation Service (WAS) started (TotalApplicationPoolUptime)", + []string{"app"}, + nil, + ), + TotalWorkerProcessesCreated: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "total_worker_processes_created"), + "The number of worker processes created for the application pool since Windows Process Activation Service (WAS) started (TotalWorkerProcessesCreated)", + []string{"app"}, + nil, + ), + TotalWorkerProcessFailures: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "total_worker_process_failures"), + "The number of times that worker processes have crashed since the application pool was started (TotalWorkerProcessFailures)", + []string{"app"}, + nil, + ), + TotalWorkerProcessPingFailures: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "total_worker_process_ping_failures"), + "The number of times that Windows Process Activation Service (WAS) did not receive a response to ping messages sent to a worker process (TotalWorkerProcessPingFailures)", + []string{"app"}, + nil, + ), + TotalWorkerProcessShutdownFailures: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "total_worker_process_shutdown_failures"), + "The number of times that Windows Process Activation Service (WAS) failed to shut down a worker process (TotalWorkerProcessShutdownFailures)", + []string{"app"}, + nil, + ), + TotalWorkerProcessStartupFailures: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "total_worker_process_startup_failures"), + "The number of times that Windows Process Activation Service (WAS) failed to start a worker process (TotalWorkerProcessStartupFailures)", + []string{"app"}, + nil, + ), + + ActiveFlushedEntries: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_cache_active_flushed_entries"), + "Number of file handles cached in user-mode that will be closed when all current transfers complete.", + []string{"app", "pid"}, + nil, + ), + FileCacheMemoryUsage: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_file_cache_memory_bytes"), + "", + []string{"app", "pid"}, + nil, + ), + MaximumFileCacheMemoryUsage: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_file_cache_max_memory_bytes"), + "", + []string{"app", "pid"}, + nil, + ), + FileCacheFlushesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_file_cache_flushes_total"), + "", + []string{"app", "pid"}, + nil, + ), + FileCacheQueriesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_file_cache_queries_total"), + "", + []string{"app", "pid"}, + nil, + ), + FileCacheHitsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_file_cache_hits_total"), + "", + []string{"app", "pid"}, + nil, + ), + FilesCached: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_file_cache_items"), + "", + []string{"app", "pid"}, + nil, + ), + FilesCachedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_file_cache_items_total"), + "", + []string{"app", "pid"}, + nil, + ), + FilesFlushedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_file_cache_items_flushed_total"), + "", + []string{"app", "pid"}, + nil, + ), + URICacheFlushesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_uri_cache_flushes_total"), + "", + []string{"app", "pid"}, + nil, + ), + URICacheQueriesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_uri_cache_queries_total"), + "", + []string{"app", "pid"}, + nil, + ), + URICacheHitsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_uri_cache_hits_total"), + "", + []string{"app", "pid"}, + nil, + ), + URIsCached: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_uri_cache_items"), + "", + []string{"app", "pid"}, + nil, + ), + URIsCachedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_uri_cache_items_total"), + "", + []string{"app", "pid"}, + nil, + ), + URIsFlushedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_uri_cache_items_flushed_total"), + "", + []string{"app", "pid"}, + nil, + ), + MetadataCached: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_metadata_cache_items"), + "", + []string{"app", "pid"}, + nil, + ), + MetadataCacheFlushes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_metadata_cache_flushes_total"), + "", + []string{"app", "pid"}, + nil, + ), + MetadataCacheQueriesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_metadata_cache_queries_total"), + "", + []string{"app", "pid"}, + nil, + ), + MetadataCacheHitsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_metadata_cache_hits_total"), + "", + []string{"app", "pid"}, + nil, + ), + MetadataCachedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_metadata_cache_items_cached_total"), + "", + []string{"app", "pid"}, + nil, + ), + MetadataFlushedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_metadata_cache_items_flushed_total"), + "", + []string{"app", "pid"}, + nil, + ), + OutputCacheActiveFlushedItems: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_output_cache_active_flushed_items"), + "", + []string{"app", "pid"}, + nil, + ), + OutputCacheItems: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_output_cache_items"), + "", + []string{"app", "pid"}, + nil, + ), + OutputCacheMemoryUsage: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_output_cache_memory_bytes"), + "", + []string{"app", "pid"}, + nil, + ), + OutputCacheQueriesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_output_queries_total"), + "", + []string{"app", "pid"}, + nil, + ), + OutputCacheHitsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_output_cache_hits_total"), + "", + []string{"app", "pid"}, + nil, + ), + OutputCacheFlushedItemsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_output_cache_items_flushed_total"), + "", + []string{"app", "pid"}, + nil, + ), + OutputCacheFlushesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_output_cache_flushes_total"), + "", + []string{"app", "pid"}, + nil, + ), + Threads: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_threads"), + "", + []string{"app", "pid", "state"}, + nil, + ), + MaximumThreads: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_max_threads"), + "", + []string{"app", "pid"}, + nil, + ), + RequestsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_requests_total"), + "", + []string{"app", "pid"}, + nil, + ), + RequestsActive: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_current_requests"), + "", + []string{"app", "pid"}, + nil, + ), + RequestErrorsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_request_errors_total"), + "", + []string{"app", "pid", "status_code"}, + nil, + ), + WebSocketRequestsActive: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_current_websocket_requests"), + "", + []string{"app", "pid"}, + nil, + ), + WebSocketConnectionAttempts: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_websocket_connection_attempts_total"), + "", + []string{"app", "pid"}, + nil, + ), + WebSocketConnectionsAccepted: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_websocket_connection_accepted_total"), + "", + []string{"app", "pid"}, + nil, + ), + WebSocketConnectionsRejected: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "worker_websocket_connection_rejected_total"), + "", + []string{"app", "pid"}, + nil, + ), + + /////////// + + ServiceCache_ActiveFlushedEntries: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "server_cache_active_flushed_entries"), + "Number of file handles cached in user-mode that will be closed when all current transfers complete.", + nil, + nil, + ), + ServiceCache_FileCacheMemoryUsage: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "server_file_cache_memory_bytes"), + "", + nil, + nil, + ), + ServiceCache_MaximumFileCacheMemoryUsage: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "server_file_cache_max_memory_bytes"), + "", + nil, + nil, + ), + ServiceCache_FileCacheFlushesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "server_file_cache_flushes_total"), + "", + nil, + nil, + ), + ServiceCache_FileCacheQueriesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "server_file_cache_queries_total"), + "", + nil, + nil, + ), + ServiceCache_FileCacheHitsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "server_file_cache_hits_total"), + "", + nil, + nil, + ), + ServiceCache_FilesCached: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "server_file_cache_items"), + "", + nil, + nil, + ), + ServiceCache_FilesCachedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "server_file_cache_items_total"), + "", + nil, + nil, + ), + ServiceCache_FilesFlushedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "server_file_cache_items_flushed_total"), + "", + nil, + nil, + ), + ServiceCache_URICacheFlushesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "server_uri_cache_flushes_total"), + "", + []string{"mode"}, + nil, + ), + ServiceCache_URICacheQueriesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "server_uri_cache_queries_total"), + "", + []string{"mode"}, + nil, + ), + ServiceCache_URICacheHitsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "server_uri_cache_hits_total"), + "", + []string{"mode"}, + nil, + ), + ServiceCache_URIsCached: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "server_uri_cache_items"), + "", + []string{"mode"}, + nil, + ), + ServiceCache_URIsCachedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "server_uri_cache_items_total"), + "", + []string{"mode"}, + nil, + ), + ServiceCache_URIsFlushedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "server_uri_cache_items_flushed_total"), + "", + []string{"mode"}, + nil, + ), + ServiceCache_MetadataCached: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "server_metadata_cache_items"), + "", + nil, + nil, + ), + ServiceCache_MetadataCacheFlushes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "server_metadata_cache_flushes_total"), + "", + nil, + nil, + ), + ServiceCache_MetadataCacheQueriesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "server_metadata_cache_queries_total"), + "", + nil, + nil, + ), + ServiceCache_MetadataCacheHitsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "server_metadata_cache_hits_total"), + "", + nil, + nil, + ), + ServiceCache_MetadataCachedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "server_metadata_cache_items_cached_total"), + "", + nil, + nil, + ), + ServiceCache_MetadataFlushedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "server_metadata_cache_items_flushed_total"), + "", + nil, + nil, + ), + ServiceCache_OutputCacheActiveFlushedItems: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "server_output_cache_active_flushed_items"), + "", + nil, + nil, + ), + ServiceCache_OutputCacheItems: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "server_output_cache_items"), + "", + nil, + nil, + ), + ServiceCache_OutputCacheMemoryUsage: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "server_output_cache_memory_bytes"), + "", + nil, + nil, + ), + ServiceCache_OutputCacheQueriesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "server_output_cache_queries_total"), + "", + nil, + nil, + ), + ServiceCache_OutputCacheHitsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "server_output_cache_hits_total"), + "", + nil, + nil, + ), + ServiceCache_OutputCacheFlushedItemsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "server_output_cache_items_flushed_total"), + "", + nil, + nil, + ), + ServiceCache_OutputCacheFlushesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "server_output_cache_flushes_total"), + "", + nil, + nil, + ), + } + buildIIS.siteWhitelistPattern = regexp.MustCompile(fmt.Sprintf("^(?:%s)$", c.SiteWhiteList)) + buildIIS.siteBlacklistPattern = regexp.MustCompile(fmt.Sprintf("^(?:%s)$", c.SiteBlackList)) + + buildIIS.appWhitelistPattern = regexp.MustCompile(fmt.Sprintf("^(?:%s)$", c.AppWhiteList)) + buildIIS.appBlacklistPattern = regexp.MustCompile(fmt.Sprintf("^(?:%s)$", c.AppBlackList)) + buildIIS.iis_version = getIISVersion() + + return buildIIS, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *IISCollector) Collect(_ *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + log.Error("failed collecting iis metrics:", desc, err) + return err + } + return nil +} + +type Win32_PerfRawData_W3SVC_WebService struct { + Name string + + CurrentAnonymousUsers uint32 + CurrentBlockedAsyncIORequests uint32 + CurrentCGIRequests uint32 + CurrentConnections uint32 + CurrentISAPIExtensionRequests uint32 + CurrentNonAnonymousUsers uint32 + + TotalBytesSent uint64 + TotalBytesReceived uint64 + TotalAnonymousUsers uint32 + TotalBlockedAsyncIORequests uint32 + TotalCGIRequests uint32 + TotalConnectionAttemptsAllInstances uint32 + TotalCopyRequests uint32 + TotalDeleteRequests uint32 + TotalFilesReceived uint32 + TotalFilesSent uint32 + TotalGetRequests uint32 + TotalHeadRequests uint32 + TotalISAPIExtensionRequests uint32 + TotalLockedErrors uint32 + TotalLockRequests uint32 + TotalLogonAttempts uint32 + TotalMethodRequests uint32 + TotalMethodRequestsPerSec uint32 + TotalMkcolRequests uint32 + TotalMoveRequests uint32 + TotalNonAnonymousUsers uint32 + TotalNotFoundErrors uint32 + TotalOptionsRequests uint32 + TotalOtherRequestMethods uint32 + TotalPostRequests uint32 + TotalPropfindRequests uint32 + TotalProppatchRequests uint32 + TotalPutRequests uint32 + TotalRejectedAsyncIORequests uint32 + TotalSearchRequests uint32 + TotalTraceRequests uint32 + TotalUnlockRequests uint32 +} + +type Win32_PerfRawData_APPPOOLCountersProvider_APPPOOLWAS struct { + Name string + Frequency_Object uint64 + Timestamp_Object uint64 + + CurrentApplicationPoolState uint32 + CurrentApplicationPoolUptime uint64 + CurrentWorkerProcesses uint32 + MaximumWorkerProcesses uint32 + RecentWorkerProcessFailures uint32 + TimeSinceLastWorkerProcessFailure uint64 + TotalApplicationPoolRecycles uint32 + TotalApplicationPoolUptime uint64 + TotalWorkerProcessesCreated uint32 + TotalWorkerProcessFailures uint32 + TotalWorkerProcessPingFailures uint32 + TotalWorkerProcessShutdownFailures uint32 + TotalWorkerProcessStartupFailures uint32 +} + +type Win32_PerfRawData_W3SVCW3WPCounterProvider_W3SVCW3WP struct { + Name string + + ActiveFlushedEntries uint64 + CurrentFileCacheMemoryUsage uint64 + CurrentFilesCached uint64 + CurrentMetadataCached uint64 + CurrentURIsCached uint64 + FileCacheFlushes uint64 + FileCacheHits uint64 + FileCacheMisses uint64 + MaximumFileCacheMemoryUsage uint64 + MetadataCacheFlushes uint64 + MetadataCacheHits uint64 + MetadataCacheMisses uint64 + OutputCacheCurrentFlushedItems uint64 + OutputCacheCurrentItems uint64 + OutputCacheCurrentMemoryUsage uint64 + OutputCacheHitsPersec uint64 + OutputCacheMissesPersec uint64 + OutputCacheTotalFlushedItems uint64 + OutputCacheTotalFlushes uint64 + OutputCacheTotalHits uint64 + OutputCacheTotalMisses uint64 + TotalFilesCached uint64 + TotalFlushedFiles uint64 + TotalFlushedMetadata uint64 + TotalFlushedURIs uint64 + TotalMetadataCached uint64 + TotalURIsCached uint64 + URICacheFlushes uint64 + URICacheHits uint64 + URICacheMisses uint64 + ActiveThreadsCount uint64 + TotalThreads uint64 + MaximumThreadsCount uint64 + TotalHTTPRequestsServed uint64 + ActiveRequests uint64 +} +type Win32_PerfRawData_W3SVCW3WPCounterProvider_W3SVCW3WP_IIS8 struct { + Name string + + Percent401HTTPResponseSent uint64 + Percent403HTTPResponseSent uint64 + Percent404HTTPResponseSent uint64 + Percent500HTTPResponseSent uint64 + WebSocketActiveRequests uint64 + WebSocketConnectionAttemptsPerSec uint64 + WebSocketConnectionsAcceptedPerSec uint64 + WebSocketConnectionsRejectedPerSec uint64 +} + +type Win32_PerfRawData_W3SVC_WebServiceCache struct { + ActiveFlushedEntries uint32 + CurrentFileCacheMemoryUsage uint64 + CurrentFilesCached uint32 + CurrentMetadataCached uint32 + CurrentURIsCached uint32 + FileCacheFlushes uint32 + FileCacheHits uint32 + FileCacheHitsPercent uint32 + FileCacheMisses uint32 + KernelCurrentURIsCached uint32 + KernelTotalFlushedURIs uint32 + KernelTotalURIsCached uint32 + KernelURICacheFlushes uint32 + KernelURICacheHits uint32 + KernelURICacheHitsPercent uint32 + KernelUriCacheHitsPersec uint32 + KernelURICacheMisses uint32 + MaximumFileCacheMemoryUsage uint64 + MetadataCacheFlushes uint32 + MetadataCacheHits uint32 + MetadataCacheHitsPercent uint32 + MetadataCacheMisses uint32 + OutputCacheCurrentFlushedItems uint32 + OutputCacheCurrentHitsPercent uint32 + OutputCacheCurrentItems uint32 + OutputCacheCurrentMemoryUsage uint64 + OutputCacheTotalFlushedItems uint32 + OutputCacheTotalFlushes uint32 + OutputCacheTotalHits uint32 + OutputCacheTotalMisses uint32 + TotalFilesCached uint32 + TotalFlushedFiles uint32 + TotalFlushedMetadata uint32 + TotalFlushedURIs uint32 + TotalMetadataCached uint32 + TotalURIsCached uint32 + URICacheFlushes uint32 + URICacheHits uint32 + URICacheHitsPercent uint32 + URICacheMisses uint32 +} + +var applicationStates = map[uint32]string{ + 1: "Uninitialized", + 2: "Initialized", + 3: "Running", + 4: "Disabling", + 5: "Disabled", + 6: "Shutdown Pending", + 7: "Delete Pending", +} + +// W3SVCW3WPCounterProvider_W3SVCW3WP returns names prefixed with pid +var workerProcessNameExtractor = regexp.MustCompile(`^(\d+)_(.+)$`) + +func (c *IISCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_W3SVC_WebService + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, site := range dst { + if site.Name == "_Total" || + c.siteBlacklistPattern.MatchString(site.Name) || + !c.siteWhitelistPattern.MatchString(site.Name) { + continue + } + + // Gauges + ch <- prometheus.MustNewConstMetric( + c.CurrentAnonymousUsers, + prometheus.GaugeValue, + float64(site.CurrentAnonymousUsers), + site.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.CurrentBlockedAsyncIORequests, + prometheus.GaugeValue, + float64(site.CurrentBlockedAsyncIORequests), + site.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.CurrentCGIRequests, + prometheus.GaugeValue, + float64(site.CurrentCGIRequests), + site.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.CurrentConnections, + prometheus.GaugeValue, + float64(site.CurrentConnections), + site.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.CurrentISAPIExtensionRequests, + prometheus.GaugeValue, + float64(site.CurrentISAPIExtensionRequests), + site.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.CurrentNonAnonymousUsers, + prometheus.GaugeValue, + float64(site.CurrentNonAnonymousUsers), + site.Name, + ) + + // Counters + ch <- prometheus.MustNewConstMetric( + c.TotalBytesReceived, + prometheus.CounterValue, + float64(site.TotalBytesReceived), + site.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.TotalBytesSent, + prometheus.CounterValue, + float64(site.TotalBytesSent), + site.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.TotalAnonymousUsers, + prometheus.CounterValue, + float64(site.TotalAnonymousUsers), + site.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.TotalBlockedAsyncIORequests, + prometheus.CounterValue, + float64(site.TotalBlockedAsyncIORequests), + site.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.TotalRejectedAsyncIORequests, + prometheus.CounterValue, + float64(site.TotalRejectedAsyncIORequests), + site.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.TotalCGIRequests, + prometheus.CounterValue, + float64(site.TotalCGIRequests), + site.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.TotalConnectionAttemptsAllInstances, + prometheus.CounterValue, + float64(site.TotalConnectionAttemptsAllInstances), + site.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TotalFilesReceived, + prometheus.CounterValue, + float64(site.TotalFilesReceived), + site.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.TotalFilesSent, + prometheus.CounterValue, + float64(site.TotalFilesSent), + site.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.TotalLockedErrors, + prometheus.CounterValue, + float64(site.TotalLockedErrors), + site.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.TotalLogonAttempts, + prometheus.CounterValue, + float64(site.TotalLogonAttempts), + site.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.TotalNonAnonymousUsers, + prometheus.CounterValue, + float64(site.TotalNonAnonymousUsers), + site.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.TotalNotFoundErrors, + prometheus.CounterValue, + float64(site.TotalNotFoundErrors), + site.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.TotalISAPIExtensionRequests, + prometheus.CounterValue, + float64(site.TotalISAPIExtensionRequests), + site.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TotalRequests, + prometheus.CounterValue, + float64(site.TotalOtherRequestMethods), + site.Name, + "other", + ) + ch <- prometheus.MustNewConstMetric( + c.TotalRequests, + prometheus.CounterValue, + float64(site.TotalCopyRequests), + site.Name, + "COPY", + ) + ch <- prometheus.MustNewConstMetric( + c.TotalRequests, + prometheus.CounterValue, + float64(site.TotalDeleteRequests), + site.Name, + "DELETE", + ) + ch <- prometheus.MustNewConstMetric( + c.TotalRequests, + prometheus.CounterValue, + float64(site.TotalGetRequests), + site.Name, + "GET", + ) + ch <- prometheus.MustNewConstMetric( + c.TotalRequests, + prometheus.CounterValue, + float64(site.TotalHeadRequests), + site.Name, + "HEAD", + ) + ch <- prometheus.MustNewConstMetric( + c.TotalRequests, + prometheus.CounterValue, + float64(site.TotalLockRequests), + site.Name, + "LOCK", + ) + ch <- prometheus.MustNewConstMetric( + c.TotalRequests, + prometheus.CounterValue, + float64(site.TotalMkcolRequests), + site.Name, + "MKCOL", + ) + ch <- prometheus.MustNewConstMetric( + c.TotalRequests, + prometheus.CounterValue, + float64(site.TotalMoveRequests), + site.Name, + "MOVE", + ) + ch <- prometheus.MustNewConstMetric( + c.TotalRequests, + prometheus.CounterValue, + float64(site.TotalOptionsRequests), + site.Name, + "OPTIONS", + ) + ch <- prometheus.MustNewConstMetric( + c.TotalRequests, + prometheus.CounterValue, + float64(site.TotalPostRequests), + site.Name, + "POST", + ) + ch <- prometheus.MustNewConstMetric( + c.TotalRequests, + prometheus.CounterValue, + float64(site.TotalPropfindRequests), + site.Name, + "PROPFIND", + ) + ch <- prometheus.MustNewConstMetric( + c.TotalRequests, + prometheus.CounterValue, + float64(site.TotalProppatchRequests), + site.Name, + "PROPPATCH", + ) + ch <- prometheus.MustNewConstMetric( + c.TotalRequests, + prometheus.CounterValue, + float64(site.TotalPutRequests), + site.Name, + "PUT", + ) + ch <- prometheus.MustNewConstMetric( + c.TotalRequests, + prometheus.CounterValue, + float64(site.TotalSearchRequests), + site.Name, + "SEARCH", + ) + ch <- prometheus.MustNewConstMetric( + c.TotalRequests, + prometheus.CounterValue, + float64(site.TotalTraceRequests), + site.Name, + "TRACE", + ) + ch <- prometheus.MustNewConstMetric( + c.TotalRequests, + prometheus.CounterValue, + float64(site.TotalUnlockRequests), + site.Name, + "UNLOCK", + ) + + } + + var dst2 []Win32_PerfRawData_APPPOOLCountersProvider_APPPOOLWAS + q2 := queryAll(&dst2) + if err := wmi.Query(q2, &dst2); err != nil { + return nil, err + } + + for _, app := range dst2 { + if app.Name == "_Total" || + c.appBlacklistPattern.MatchString(app.Name) || + !c.appWhitelistPattern.MatchString(app.Name) { + continue + } + + // Guages + for key, label := range applicationStates { + isCurrentState := 0.0 + if key == app.CurrentApplicationPoolState { + isCurrentState = 1.0 + } + ch <- prometheus.MustNewConstMetric( + c.CurrentApplicationPoolState, + prometheus.GaugeValue, + isCurrentState, + app.Name, + label, + ) + } + + ch <- prometheus.MustNewConstMetric( + c.CurrentApplicationPoolUptime, + prometheus.GaugeValue, + // convert from Windows timestamp (1 jan 1601) to unix timestamp (1 jan 1970) + float64(app.CurrentApplicationPoolUptime-116444736000000000)/float64(app.Frequency_Object), + app.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.CurrentWorkerProcesses, + prometheus.GaugeValue, + float64(app.CurrentWorkerProcesses), + app.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.MaximumWorkerProcesses, + prometheus.GaugeValue, + float64(app.MaximumWorkerProcesses), + app.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.RecentWorkerProcessFailures, + prometheus.GaugeValue, + float64(app.RecentWorkerProcessFailures), + app.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TimeSinceLastWorkerProcessFailure, + prometheus.GaugeValue, + float64(app.TimeSinceLastWorkerProcessFailure), + app.Name, + ) + + // Counters + ch <- prometheus.MustNewConstMetric( + c.TotalApplicationPoolRecycles, + prometheus.CounterValue, + float64(app.TotalApplicationPoolRecycles), + app.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TotalApplicationPoolUptime, + prometheus.CounterValue, + // convert from Windows timestamp (1 jan 1601) to unix timestamp (1 jan 1970) + float64(app.TotalApplicationPoolUptime-116444736000000000)/float64(app.Frequency_Object), + app.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TotalWorkerProcessesCreated, + prometheus.CounterValue, + float64(app.TotalWorkerProcessesCreated), + app.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TotalWorkerProcessFailures, + prometheus.CounterValue, + float64(app.TotalWorkerProcessFailures), + app.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TotalWorkerProcessPingFailures, + prometheus.CounterValue, + float64(app.TotalWorkerProcessPingFailures), + app.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TotalWorkerProcessShutdownFailures, + prometheus.CounterValue, + float64(app.TotalWorkerProcessShutdownFailures), + app.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TotalWorkerProcessStartupFailures, + prometheus.CounterValue, + float64(app.TotalWorkerProcessStartupFailures), + app.Name, + ) + + } + + var dst_worker []Win32_PerfRawData_W3SVCW3WPCounterProvider_W3SVCW3WP + q = queryAll(&dst_worker) + if err := wmi.Query(q, &dst_worker); err != nil { + return nil, err + } + for _, app := range dst_worker { + // Extract the apppool name from the format _ + name := workerProcessNameExtractor.ReplaceAllString(app.Name, "$2") + if name == "_Total" || + c.appBlacklistPattern.MatchString(name) || + !c.appWhitelistPattern.MatchString(name) { + continue + } + + pid := workerProcessNameExtractor.ReplaceAllString(app.Name, "$1") + + ch <- prometheus.MustNewConstMetric( + c.ActiveFlushedEntries, + prometheus.GaugeValue, + float64(app.ActiveFlushedEntries), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.FileCacheMemoryUsage, + prometheus.GaugeValue, + float64(app.CurrentFileCacheMemoryUsage), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.MaximumFileCacheMemoryUsage, + prometheus.CounterValue, + float64(app.MaximumFileCacheMemoryUsage), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.FileCacheFlushesTotal, + prometheus.CounterValue, + float64(app.TotalFlushedFiles), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.FileCacheQueriesTotal, + prometheus.CounterValue, + float64(app.FileCacheHits+app.FileCacheMisses), + name, + pid, + ) + ch <- prometheus.MustNewConstMetric( + c.FileCacheHitsTotal, + prometheus.CounterValue, + float64(app.FileCacheHits), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.FilesCached, + prometheus.GaugeValue, + float64(app.CurrentFilesCached), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.FilesCachedTotal, + prometheus.CounterValue, + float64(app.TotalFilesCached), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.FilesFlushedTotal, + prometheus.CounterValue, + float64(app.TotalFlushedFiles), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.URICacheFlushesTotal, + prometheus.CounterValue, + float64(app.TotalFlushedURIs), + name, + pid, + ) + ch <- prometheus.MustNewConstMetric( + c.URICacheQueriesTotal, + prometheus.CounterValue, + float64(app.URICacheHits+app.URICacheMisses), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.URICacheHitsTotal, + prometheus.CounterValue, + float64(app.URICacheHits), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.URIsCached, + prometheus.GaugeValue, + float64(app.CurrentURIsCached), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.URIsCachedTotal, + prometheus.CounterValue, + float64(app.TotalURIsCached), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.URIsFlushedTotal, + prometheus.CounterValue, + float64(app.TotalFlushedURIs), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.MetadataCached, + prometheus.GaugeValue, + float64(app.CurrentMetadataCached), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.MetadataCacheFlushes, + prometheus.CounterValue, + float64(app.TotalFlushedMetadata), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.MetadataCacheQueriesTotal, + prometheus.CounterValue, + float64(app.MetadataCacheHits+app.MetadataCacheMisses), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.MetadataCacheHitsTotal, + prometheus.CounterValue, + float64(app.MetadataCacheHits), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.MetadataCachedTotal, + prometheus.CounterValue, + float64(app.TotalMetadataCached), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.MetadataFlushedTotal, + prometheus.CounterValue, + float64(app.TotalFlushedMetadata), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.OutputCacheActiveFlushedItems, + prometheus.CounterValue, + float64(app.OutputCacheCurrentFlushedItems), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.OutputCacheItems, + prometheus.CounterValue, + float64(app.OutputCacheCurrentItems), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.OutputCacheMemoryUsage, + prometheus.CounterValue, + float64(app.OutputCacheCurrentMemoryUsage), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.OutputCacheQueriesTotal, + prometheus.CounterValue, + float64(app.OutputCacheTotalHits+app.OutputCacheTotalMisses), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.OutputCacheHitsTotal, + prometheus.CounterValue, + float64(app.OutputCacheTotalHits), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.OutputCacheFlushedItemsTotal, + prometheus.CounterValue, + float64(app.OutputCacheTotalFlushedItems), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.OutputCacheFlushesTotal, + prometheus.CounterValue, + float64(app.OutputCacheTotalFlushes), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.Threads, + prometheus.GaugeValue, + float64(app.ActiveThreadsCount), + name, + pid, + "busy", + ) + + ch <- prometheus.MustNewConstMetric( + c.Threads, + prometheus.GaugeValue, + float64(app.TotalThreads), + name, + pid, + "idle", + ) + + ch <- prometheus.MustNewConstMetric( + c.MaximumThreads, + prometheus.CounterValue, + float64(app.MaximumThreadsCount), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.RequestsTotal, + prometheus.CounterValue, + float64(app.TotalHTTPRequestsServed), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.RequestsActive, + prometheus.CounterValue, + float64(app.ActiveRequests), + name, + pid, + ) + } + + if c.iis_version.major >= 8 { + var dst_worker_iis8 []Win32_PerfRawData_W3SVCW3WPCounterProvider_W3SVCW3WP_IIS8 + q = queryAllForClass(&dst_worker_iis8, "Win32_PerfRawData_W3SVCW3WPCounterProvider_W3SVCW3WP") + if err := wmi.Query(q, &dst_worker_iis8); err != nil { + return nil, err + } + for _, app := range dst_worker_iis8 { + // Extract the apppool name from the format _ + name := workerProcessNameExtractor.ReplaceAllString(app.Name, "$2") + if name == "_Total" || + c.appBlacklistPattern.MatchString(name) || + !c.appWhitelistPattern.MatchString(name) { + continue + } + + pid := workerProcessNameExtractor.ReplaceAllString(app.Name, "$1") + + ch <- prometheus.MustNewConstMetric( + c.RequestErrorsTotal, + prometheus.CounterValue, + float64(app.Percent401HTTPResponseSent), + name, + pid, + "401", + ) + ch <- prometheus.MustNewConstMetric( + c.RequestErrorsTotal, + prometheus.CounterValue, + float64(app.Percent403HTTPResponseSent), + name, + pid, + "403", + ) + ch <- prometheus.MustNewConstMetric( + c.RequestErrorsTotal, + prometheus.CounterValue, + float64(app.Percent404HTTPResponseSent), + name, + pid, + "404", + ) + ch <- prometheus.MustNewConstMetric( + c.RequestErrorsTotal, + prometheus.CounterValue, + float64(app.Percent500HTTPResponseSent), + name, + pid, + "500", + ) + + ch <- prometheus.MustNewConstMetric( + c.WebSocketRequestsActive, + prometheus.CounterValue, + float64(app.WebSocketActiveRequests), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.WebSocketConnectionAttempts, + prometheus.CounterValue, + float64(app.WebSocketConnectionAttemptsPerSec), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.WebSocketConnectionsAccepted, + prometheus.CounterValue, + float64(app.WebSocketConnectionsAcceptedPerSec), + name, + pid, + ) + + ch <- prometheus.MustNewConstMetric( + c.WebSocketConnectionsRejected, + prometheus.CounterValue, + float64(app.WebSocketConnectionsRejectedPerSec), + name, + pid, + ) + } + } + + var dst_cache []Win32_PerfRawData_W3SVC_WebServiceCache + q = queryAll(&dst_cache) + if err := wmi.Query(q, &dst_cache); err != nil { + return nil, err + } + + if len(dst_cache) == 0 { + return nil, errors.New("WMI query returned empty result set") + } + + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_ActiveFlushedEntries, + prometheus.GaugeValue, + float64(dst_cache[0].ActiveFlushedEntries), + ) + + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_FileCacheMemoryUsage, + prometheus.GaugeValue, + float64(dst_cache[0].CurrentFileCacheMemoryUsage), + ) + + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_MaximumFileCacheMemoryUsage, + prometheus.CounterValue, + float64(dst_cache[0].MaximumFileCacheMemoryUsage), + ) + + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_FileCacheFlushesTotal, + prometheus.CounterValue, + float64(dst_cache[0].TotalFlushedFiles), + ) + + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_FileCacheQueriesTotal, + prometheus.CounterValue, + float64(dst_cache[0].FileCacheHits+dst_cache[0].FileCacheMisses), + ) + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_FileCacheHitsTotal, + prometheus.CounterValue, + float64(dst_cache[0].FileCacheHits), + ) + + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_FilesCached, + prometheus.GaugeValue, + float64(dst_cache[0].CurrentFilesCached), + ) + + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_FilesCachedTotal, + prometheus.CounterValue, + float64(dst_cache[0].TotalFilesCached), + ) + + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_FilesFlushedTotal, + prometheus.CounterValue, + float64(dst_cache[0].TotalFlushedFiles), + ) + + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_URICacheFlushesTotal, + prometheus.CounterValue, + float64(dst_cache[0].TotalFlushedURIs), + "user", + ) + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_URICacheFlushesTotal, + prometheus.CounterValue, + float64(dst_cache[0].KernelTotalFlushedURIs), + "kernel", + ) + + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_URICacheQueriesTotal, + prometheus.CounterValue, + float64(dst_cache[0].URICacheHits+dst_cache[0].URICacheMisses), + "user", + ) + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_URICacheQueriesTotal, + prometheus.CounterValue, + float64(dst_cache[0].KernelURICacheHits+dst_cache[0].KernelURICacheMisses), + "kernel", + ) + + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_URICacheHitsTotal, + prometheus.CounterValue, + float64(dst_cache[0].URICacheHits), + "user", + ) + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_URICacheHitsTotal, + prometheus.CounterValue, + float64(dst_cache[0].KernelURICacheHits), + "kernel", + ) + + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_URIsCached, + prometheus.GaugeValue, + float64(dst_cache[0].CurrentURIsCached), + "user", + ) + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_URIsCached, + prometheus.GaugeValue, + float64(dst_cache[0].KernelCurrentURIsCached), + "kernel", + ) + + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_URIsCachedTotal, + prometheus.CounterValue, + float64(dst_cache[0].TotalURIsCached), + "user", + ) + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_URIsCachedTotal, + prometheus.CounterValue, + float64(dst_cache[0].KernelTotalURIsCached), + "kernel", + ) + + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_URIsFlushedTotal, + prometheus.CounterValue, + float64(dst_cache[0].TotalFlushedURIs), + "user", + ) + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_URIsFlushedTotal, + prometheus.CounterValue, + float64(dst_cache[0].KernelTotalFlushedURIs), + "kernel", + ) + + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_MetadataCached, + prometheus.GaugeValue, + float64(dst_cache[0].CurrentMetadataCached), + ) + + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_MetadataCacheFlushes, + prometheus.CounterValue, + float64(dst_cache[0].TotalFlushedMetadata), + ) + + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_MetadataCacheQueriesTotal, + prometheus.CounterValue, + float64(dst_cache[0].MetadataCacheHits+dst_cache[0].MetadataCacheMisses), + ) + + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_MetadataCacheHitsTotal, + prometheus.CounterValue, + float64(dst_cache[0].MetadataCacheHits), + ) + + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_MetadataCachedTotal, + prometheus.CounterValue, + float64(dst_cache[0].TotalMetadataCached), + ) + + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_MetadataFlushedTotal, + prometheus.CounterValue, + float64(dst_cache[0].TotalFlushedMetadata), + ) + + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_OutputCacheActiveFlushedItems, + prometheus.CounterValue, + float64(dst_cache[0].OutputCacheCurrentFlushedItems), + ) + + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_OutputCacheItems, + prometheus.CounterValue, + float64(dst_cache[0].OutputCacheCurrentItems), + ) + + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_OutputCacheMemoryUsage, + prometheus.CounterValue, + float64(dst_cache[0].OutputCacheCurrentMemoryUsage), + ) + + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_OutputCacheQueriesTotal, + prometheus.CounterValue, + float64(dst_cache[0].OutputCacheTotalHits+dst_cache[0].OutputCacheTotalMisses), + ) + + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_OutputCacheHitsTotal, + prometheus.CounterValue, + float64(dst_cache[0].OutputCacheTotalHits), + ) + + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_OutputCacheFlushedItemsTotal, + prometheus.CounterValue, + float64(dst_cache[0].OutputCacheTotalFlushedItems), + ) + + ch <- prometheus.MustNewConstMetric( + c.ServiceCache_OutputCacheFlushesTotal, + prometheus.CounterValue, + float64(dst_cache[0].OutputCacheTotalFlushes), + ) + + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/logical_disk.go b/vendor/github.com/prometheus-community/windows_exporter/collector/logical_disk.go new file mode 100644 index 000000000000..c3a35cdede62 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/logical_disk.go @@ -0,0 +1,311 @@ +// +build windows + +package collector + +import ( + "fmt" + "regexp" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" + "gopkg.in/alecthomas/kingpin.v2" +) + +func init() { + registerCollectorWithConfig("logical_disk", func() Config { return &LogicalDiskConfig{} }, "LogicalDisk") +} + +type LogicalDiskConfig struct { + VolumeWhiteList string + VolumeBlackList string +} + +func (l *LogicalDiskConfig) RegisterKingpin(ka *kingpin.Application) { + ka.Flag( + "collector.logical_disk.volume-whitelist", + "Regexp of volumes to whitelist. Volume name must both match whitelist and not match blacklist to be included.", + ).Default(".+").StringVar(&l.VolumeWhiteList) + ka.Flag( + "collector.logical_disk.volume-blacklist", + "Regexp of volumes to blacklist. Volume name must both match whitelist and not match blacklist to be included.", + ).Default("").StringVar(&l.VolumeBlackList) +} + +func (l *LogicalDiskConfig) Build() (Collector, error) { + return NewLogicalDiskCollector(l) +} + +// A LogicalDiskCollector is a Prometheus collector for perflib logicalDisk metrics +type LogicalDiskCollector struct { + RequestsQueued *prometheus.Desc + ReadBytesTotal *prometheus.Desc + ReadsTotal *prometheus.Desc + WriteBytesTotal *prometheus.Desc + WritesTotal *prometheus.Desc + ReadTime *prometheus.Desc + WriteTime *prometheus.Desc + TotalSpace *prometheus.Desc + FreeSpace *prometheus.Desc + IdleTime *prometheus.Desc + SplitIOs *prometheus.Desc + ReadLatency *prometheus.Desc + WriteLatency *prometheus.Desc + ReadWriteLatency *prometheus.Desc + + volumeWhitelistPattern *regexp.Regexp + volumeBlacklistPattern *regexp.Regexp +} + +// NewLogicalDiskCollector ... +func NewLogicalDiskCollector(l *LogicalDiskConfig) (Collector, error) { + const subsystem = "logical_disk" + + return &LogicalDiskCollector{ + RequestsQueued: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "requests_queued"), + "The number of requests queued to the disk (LogicalDisk.CurrentDiskQueueLength)", + []string{"volume"}, + nil, + ), + + ReadBytesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "read_bytes_total"), + "The number of bytes transferred from the disk during read operations (LogicalDisk.DiskReadBytesPerSec)", + []string{"volume"}, + nil, + ), + + ReadsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "reads_total"), + "The number of read operations on the disk (LogicalDisk.DiskReadsPerSec)", + []string{"volume"}, + nil, + ), + + WriteBytesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "write_bytes_total"), + "The number of bytes transferred to the disk during write operations (LogicalDisk.DiskWriteBytesPerSec)", + []string{"volume"}, + nil, + ), + + WritesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "writes_total"), + "The number of write operations on the disk (LogicalDisk.DiskWritesPerSec)", + []string{"volume"}, + nil, + ), + + ReadTime: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "read_seconds_total"), + "Seconds that the disk was busy servicing read requests (LogicalDisk.PercentDiskReadTime)", + []string{"volume"}, + nil, + ), + + WriteTime: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "write_seconds_total"), + "Seconds that the disk was busy servicing write requests (LogicalDisk.PercentDiskWriteTime)", + []string{"volume"}, + nil, + ), + + FreeSpace: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "free_bytes"), + "Free space in bytes (LogicalDisk.PercentFreeSpace)", + []string{"volume"}, + nil, + ), + + TotalSpace: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "size_bytes"), + "Total space in bytes (LogicalDisk.PercentFreeSpace_Base)", + []string{"volume"}, + nil, + ), + + IdleTime: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "idle_seconds_total"), + "Seconds that the disk was idle (LogicalDisk.PercentIdleTime)", + []string{"volume"}, + nil, + ), + + SplitIOs: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "split_ios_total"), + "The number of I/Os to the disk were split into multiple I/Os (LogicalDisk.SplitIOPerSec)", + []string{"volume"}, + nil, + ), + + ReadLatency: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "read_latency_seconds_total"), + "Shows the average time, in seconds, of a read operation from the disk (LogicalDisk.AvgDiskSecPerRead)", + []string{"volume"}, + nil, + ), + + WriteLatency: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "write_latency_seconds_total"), + "Shows the average time, in seconds, of a write operation to the disk (LogicalDisk.AvgDiskSecPerWrite)", + []string{"volume"}, + nil, + ), + + ReadWriteLatency: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "read_write_latency_seconds_total"), + "Shows the time, in seconds, of the average disk transfer (LogicalDisk.AvgDiskSecPerTransfer)", + []string{"volume"}, + nil, + ), + + volumeWhitelistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", l.VolumeWhiteList)), + volumeBlacklistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", l.VolumeBlackList)), + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *LogicalDiskCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ctx, ch); err != nil { + log.Error("failed collecting logical_disk metrics:", desc, err) + return err + } + return nil +} + +// Win32_PerfRawData_PerfDisk_LogicalDisk docs: +// - https://msdn.microsoft.com/en-us/windows/hardware/aa394307(v=vs.71) - Win32_PerfRawData_PerfDisk_LogicalDisk class +// - https://msdn.microsoft.com/en-us/library/ms803973.aspx - LogicalDisk object reference +type logicalDisk struct { + Name string + CurrentDiskQueueLength float64 `perflib:"Current Disk Queue Length"` + DiskReadBytesPerSec float64 `perflib:"Disk Read Bytes/sec"` + DiskReadsPerSec float64 `perflib:"Disk Reads/sec"` + DiskWriteBytesPerSec float64 `perflib:"Disk Write Bytes/sec"` + DiskWritesPerSec float64 `perflib:"Disk Writes/sec"` + PercentDiskReadTime float64 `perflib:"% Disk Read Time"` + PercentDiskWriteTime float64 `perflib:"% Disk Write Time"` + PercentFreeSpace float64 `perflib:"% Free Space_Base"` + PercentFreeSpace_Base float64 `perflib:"Free Megabytes"` + PercentIdleTime float64 `perflib:"% Idle Time"` + SplitIOPerSec float64 `perflib:"Split IO/Sec"` + AvgDiskSecPerRead float64 `perflib:"Avg. Disk sec/Read"` + AvgDiskSecPerWrite float64 `perflib:"Avg. Disk sec/Write"` + AvgDiskSecPerTransfer float64 `perflib:"Avg. Disk sec/Transfer"` +} + +func (c *LogicalDiskCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []logicalDisk + if err := unmarshalObject(ctx.perfObjects["LogicalDisk"], &dst); err != nil { + return nil, err + } + + for _, volume := range dst { + if volume.Name == "_Total" || + c.volumeBlacklistPattern.MatchString(volume.Name) || + !c.volumeWhitelistPattern.MatchString(volume.Name) { + continue + } + + ch <- prometheus.MustNewConstMetric( + c.RequestsQueued, + prometheus.GaugeValue, + volume.CurrentDiskQueueLength, + volume.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.ReadBytesTotal, + prometheus.CounterValue, + volume.DiskReadBytesPerSec, + volume.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.ReadsTotal, + prometheus.CounterValue, + volume.DiskReadsPerSec, + volume.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.WriteBytesTotal, + prometheus.CounterValue, + volume.DiskWriteBytesPerSec, + volume.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.WritesTotal, + prometheus.CounterValue, + volume.DiskWritesPerSec, + volume.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.ReadTime, + prometheus.CounterValue, + volume.PercentDiskReadTime, + volume.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.WriteTime, + prometheus.CounterValue, + volume.PercentDiskWriteTime, + volume.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.FreeSpace, + prometheus.GaugeValue, + volume.PercentFreeSpace_Base*1024*1024, + volume.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TotalSpace, + prometheus.GaugeValue, + volume.PercentFreeSpace*1024*1024, + volume.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.IdleTime, + prometheus.CounterValue, + volume.PercentIdleTime, + volume.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.SplitIOs, + prometheus.CounterValue, + volume.SplitIOPerSec, + volume.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.ReadLatency, + prometheus.CounterValue, + volume.AvgDiskSecPerRead*ticksToSecondsScaleFactor, + volume.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.WriteLatency, + prometheus.CounterValue, + volume.AvgDiskSecPerWrite*ticksToSecondsScaleFactor, + volume.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.ReadWriteLatency, + prometheus.CounterValue, + volume.AvgDiskSecPerTransfer*ticksToSecondsScaleFactor, + volume.Name, + ) + } + + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/logon.go b/vendor/github.com/prometheus-community/windows_exporter/collector/logon.go new file mode 100644 index 000000000000..d6a4919af639 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/logon.go @@ -0,0 +1,199 @@ +// +build windows + +package collector + +import ( + "errors" + + "github.com/StackExchange/wmi" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +func init() { + registerCollector("logon", NewLogonCollector) +} + +// A LogonCollector is a Prometheus collector for WMI metrics +type LogonCollector struct { + LogonType *prometheus.Desc +} + +// NewLogonCollector ... +func NewLogonCollector() (Collector, error) { + const subsystem = "logon" + + return &LogonCollector{ + LogonType: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "logon_type"), + "Number of active logon sessions (LogonSession.LogonType)", + []string{"status"}, + nil, + ), + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *LogonCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + log.Error("failed collecting user metrics:", desc, err) + return err + } + return nil +} + +// Win32_LogonSession docs: +// - https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-logonsession +type Win32_LogonSession struct { + LogonType uint32 +} + +func (c *LogonCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_LogonSession + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + if len(dst) == 0 { + return nil, errors.New("WMI query returned empty result set") + } + + // Init counters + system := 0 + interactive := 0 + network := 0 + batch := 0 + service := 0 + proxy := 0 + unlock := 0 + networkcleartext := 0 + newcredentials := 0 + remoteinteractive := 0 + cachedinteractive := 0 + cachedremoteinteractive := 0 + cachedunlock := 0 + + for _, entry := range dst { + switch entry.LogonType { + case 0: + system++ + case 2: + interactive++ + case 3: + network++ + case 4: + batch++ + case 5: + service++ + case 6: + proxy++ + case 7: + unlock++ + case 8: + networkcleartext++ + case 9: + newcredentials++ + case 10: + remoteinteractive++ + case 11: + cachedinteractive++ + case 12: + cachedremoteinteractive++ + case 13: + cachedunlock++ + } + } + + ch <- prometheus.MustNewConstMetric( + c.LogonType, + prometheus.GaugeValue, + float64(system), + "system", + ) + + ch <- prometheus.MustNewConstMetric( + c.LogonType, + prometheus.GaugeValue, + float64(interactive), + "interactive", + ) + + ch <- prometheus.MustNewConstMetric( + c.LogonType, + prometheus.GaugeValue, + float64(network), + "network", + ) + + ch <- prometheus.MustNewConstMetric( + c.LogonType, + prometheus.GaugeValue, + float64(batch), + "batch", + ) + + ch <- prometheus.MustNewConstMetric( + c.LogonType, + prometheus.GaugeValue, + float64(service), + "service", + ) + + ch <- prometheus.MustNewConstMetric( + c.LogonType, + prometheus.GaugeValue, + float64(proxy), + "proxy", + ) + + ch <- prometheus.MustNewConstMetric( + c.LogonType, + prometheus.GaugeValue, + float64(unlock), + "unlock", + ) + + ch <- prometheus.MustNewConstMetric( + c.LogonType, + prometheus.GaugeValue, + float64(networkcleartext), + "network_clear_text", + ) + + ch <- prometheus.MustNewConstMetric( + c.LogonType, + prometheus.GaugeValue, + float64(newcredentials), + "new_credentials", + ) + + ch <- prometheus.MustNewConstMetric( + c.LogonType, + prometheus.GaugeValue, + float64(remoteinteractive), + "remote_interactive", + ) + + ch <- prometheus.MustNewConstMetric( + c.LogonType, + prometheus.GaugeValue, + float64(cachedinteractive), + "cached_interactive", + ) + + ch <- prometheus.MustNewConstMetric( + c.LogonType, + prometheus.GaugeValue, + float64(remoteinteractive), + "cached_remote_interactive", + ) + + ch <- prometheus.MustNewConstMetric( + c.LogonType, + prometheus.GaugeValue, + float64(cachedunlock), + "cached_unlock", + ) + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/memory.go b/vendor/github.com/prometheus-community/windows_exporter/collector/memory.go new file mode 100644 index 000000000000..29aecf7f272d --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/memory.go @@ -0,0 +1,502 @@ +// returns data points from Win32_PerfRawData_PerfOS_Memory +// - Win32_PerfRawData_PerfOS_Memory class + +// +build windows + +package collector + +import ( + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +func init() { + registerCollector("memory", NewMemoryCollector, "Memory") +} + +// A MemoryCollector is a Prometheus collector for perflib Memory metrics +type MemoryCollector struct { + AvailableBytes *prometheus.Desc + CacheBytes *prometheus.Desc + CacheBytesPeak *prometheus.Desc + CacheFaultsTotal *prometheus.Desc + CommitLimit *prometheus.Desc + CommittedBytes *prometheus.Desc + DemandZeroFaultsTotal *prometheus.Desc + FreeAndZeroPageListBytes *prometheus.Desc + FreeSystemPageTableEntries *prometheus.Desc + ModifiedPageListBytes *prometheus.Desc + PageFaultsTotal *prometheus.Desc + SwapPageReadsTotal *prometheus.Desc + SwapPagesReadTotal *prometheus.Desc + SwapPagesWrittenTotal *prometheus.Desc + SwapPageOperationsTotal *prometheus.Desc + SwapPageWritesTotal *prometheus.Desc + PoolNonpagedAllocsTotal *prometheus.Desc + PoolNonpagedBytes *prometheus.Desc + PoolPagedAllocsTotal *prometheus.Desc + PoolPagedBytes *prometheus.Desc + PoolPagedResidentBytes *prometheus.Desc + StandbyCacheCoreBytes *prometheus.Desc + StandbyCacheNormalPriorityBytes *prometheus.Desc + StandbyCacheReserveBytes *prometheus.Desc + SystemCacheResidentBytes *prometheus.Desc + SystemCodeResidentBytes *prometheus.Desc + SystemCodeTotalBytes *prometheus.Desc + SystemDriverResidentBytes *prometheus.Desc + SystemDriverTotalBytes *prometheus.Desc + TransitionFaultsTotal *prometheus.Desc + TransitionPagesRepurposedTotal *prometheus.Desc + WriteCopiesTotal *prometheus.Desc +} + +// NewMemoryCollector ... +func NewMemoryCollector() (Collector, error) { + const subsystem = "memory" + + return &MemoryCollector{ + AvailableBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "available_bytes"), + "The amount of physical memory immediately available for allocation to a process or for system use. It is equal to the sum of memory assigned to"+ + " the standby (cached), free and zero page lists (AvailableBytes)", + nil, + nil, + ), + CacheBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "cache_bytes"), + "(CacheBytes)", + nil, + nil, + ), + CacheBytesPeak: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "cache_bytes_peak"), + "(CacheBytesPeak)", + nil, + nil, + ), + CacheFaultsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "cache_faults_total"), + "(CacheFaultsPersec)", + nil, + nil, + ), + CommitLimit: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "commit_limit"), + "(CommitLimit)", + nil, + nil, + ), + CommittedBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "committed_bytes"), + "(CommittedBytes)", + nil, + nil, + ), + DemandZeroFaultsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "demand_zero_faults_total"), + "The number of zeroed pages required to satisfy faults. Zeroed pages, pages emptied of previously stored data and filled with zeros, are a security"+ + " feature of Windows that prevent processes from seeing data stored by earlier processes that used the memory space (DemandZeroFaults)", + nil, + nil, + ), + FreeAndZeroPageListBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "free_and_zero_page_list_bytes"), + "(FreeAndZeroPageListBytes)", + nil, + nil, + ), + FreeSystemPageTableEntries: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "free_system_page_table_entries"), + "(FreeSystemPageTableEntries)", + nil, + nil, + ), + ModifiedPageListBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "modified_page_list_bytes"), + "(ModifiedPageListBytes)", + nil, + nil, + ), + PageFaultsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "page_faults_total"), + "(PageFaultsPersec)", + nil, + nil, + ), + SwapPageReadsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "swap_page_reads_total"), + "Number of disk page reads (a single read operation reading several pages is still only counted once) (PageReadsPersec)", + nil, + nil, + ), + SwapPagesReadTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "swap_pages_read_total"), + "Number of pages read across all page reads (ie counting all pages read even if they are read in a single operation) (PagesInputPersec)", + nil, + nil, + ), + SwapPagesWrittenTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "swap_pages_written_total"), + "Number of pages written across all page writes (ie counting all pages written even if they are written in a single operation) (PagesOutputPersec)", + nil, + nil, + ), + SwapPageOperationsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "swap_page_operations_total"), + "Total number of swap page read and writes (PagesPersec)", + nil, + nil, + ), + SwapPageWritesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "swap_page_writes_total"), + "Number of disk page writes (a single write operation writing several pages is still only counted once) (PageWritesPersec)", + nil, + nil, + ), + PoolNonpagedAllocsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "pool_nonpaged_allocs_total"), + "The number of calls to allocate space in the nonpaged pool. The nonpaged pool is an area of system memory area for objects that cannot be written"+ + " to disk, and must remain in physical memory as long as they are allocated (PoolNonpagedAllocs)", + nil, + nil, + ), + PoolNonpagedBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "pool_nonpaged_bytes_total"), + "(PoolNonpagedBytes)", + nil, + nil, + ), + PoolPagedAllocsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "pool_paged_allocs_total"), + "(PoolPagedAllocs)", + nil, + nil, + ), + PoolPagedBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "pool_paged_bytes"), + "(PoolPagedBytes)", + nil, + nil, + ), + PoolPagedResidentBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "pool_paged_resident_bytes"), + "(PoolPagedResidentBytes)", + nil, + nil, + ), + StandbyCacheCoreBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "standby_cache_core_bytes"), + "(StandbyCacheCoreBytes)", + nil, + nil, + ), + StandbyCacheNormalPriorityBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "standby_cache_normal_priority_bytes"), + "(StandbyCacheNormalPriorityBytes)", + nil, + nil, + ), + StandbyCacheReserveBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "standby_cache_reserve_bytes"), + "(StandbyCacheReserveBytes)", + nil, + nil, + ), + SystemCacheResidentBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "system_cache_resident_bytes"), + "(SystemCacheResidentBytes)", + nil, + nil, + ), + SystemCodeResidentBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "system_code_resident_bytes"), + "(SystemCodeResidentBytes)", + nil, + nil, + ), + SystemCodeTotalBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "system_code_total_bytes"), + "(SystemCodeTotalBytes)", + nil, + nil, + ), + SystemDriverResidentBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "system_driver_resident_bytes"), + "(SystemDriverResidentBytes)", + nil, + nil, + ), + SystemDriverTotalBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "system_driver_total_bytes"), + "(SystemDriverTotalBytes)", + nil, + nil, + ), + TransitionFaultsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "transition_faults_total"), + "(TransitionFaultsPersec)", + nil, + nil, + ), + TransitionPagesRepurposedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "transition_pages_repurposed_total"), + "(TransitionPagesRePurposedPersec)", + nil, + nil, + ), + WriteCopiesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "write_copies_total"), + "The number of page faults caused by attempting to write that were satisfied by copying the page from elsewhere in physical memory (WriteCopiesPersec)", + nil, + nil, + ), + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *MemoryCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ctx, ch); err != nil { + log.Error("failed collecting memory metrics:", desc, err) + return err + } + return nil +} + +type memory struct { + AvailableBytes float64 `perflib:"Available Bytes"` + AvailableKBytes float64 `perflib:"Available KBytes"` + AvailableMBytes float64 `perflib:"Available MBytes"` + CacheBytes float64 `perflib:"Cache Bytes"` + CacheBytesPeak float64 `perflib:"Cache Bytes Peak"` + CacheFaultsPersec float64 `perflib:"Cache Faults/sec"` + CommitLimit float64 `perflib:"Commit Limit"` + CommittedBytes float64 `perflib:"Committed Bytes"` + DemandZeroFaultsPersec float64 `perflib:"Demand Zero Faults/sec"` + FreeAndZeroPageListBytes float64 `perflib:"Free & Zero Page List Bytes"` + FreeSystemPageTableEntries float64 `perflib:"Free System Page Table Entries"` + ModifiedPageListBytes float64 `perflib:"Modified Page List Bytes"` + PageFaultsPersec float64 `perflib:"Page Faults/sec"` + PageReadsPersec float64 `perflib:"Page Reads/sec"` + PagesInputPersec float64 `perflib:"Pages Input/sec"` + PagesOutputPersec float64 `perflib:"Pages Output/sec"` + PagesPersec float64 `perflib:"Pages/sec"` + PageWritesPersec float64 `perflib:"Page Writes/sec"` + PoolNonpagedAllocs float64 `perflib:"Pool Nonpaged Allocs"` + PoolNonpagedBytes float64 `perflib:"Pool Nonpaged Bytes"` + PoolPagedAllocs float64 `perflib:"Pool Paged Allocs"` + PoolPagedBytes float64 `perflib:"Pool Paged Bytes"` + PoolPagedResidentBytes float64 `perflib:"Pool Paged Resident Bytes"` + StandbyCacheCoreBytes float64 `perflib:"Standby Cache Core Bytes"` + StandbyCacheNormalPriorityBytes float64 `perflib:"Standby Cache Normal Priority Bytes"` + StandbyCacheReserveBytes float64 `perflib:"Standby Cache Reserve Bytes"` + SystemCacheResidentBytes float64 `perflib:"System Cache Resident Bytes"` + SystemCodeResidentBytes float64 `perflib:"System Code Resident Bytes"` + SystemCodeTotalBytes float64 `perflib:"System Code Total Bytes"` + SystemDriverResidentBytes float64 `perflib:"System Driver Resident Bytes"` + SystemDriverTotalBytes float64 `perflib:"System Driver Total Bytes"` + TransitionFaultsPersec float64 `perflib:"Transition Faults/sec"` + TransitionPagesRePurposedPersec float64 `perflib:"Transition Pages RePurposed/sec"` + WriteCopiesPersec float64 `perflib:"Write Copies/sec"` +} + +func (c *MemoryCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []memory + if err := unmarshalObject(ctx.perfObjects["Memory"], &dst); err != nil { + return nil, err + } + + ch <- prometheus.MustNewConstMetric( + c.AvailableBytes, + prometheus.GaugeValue, + dst[0].AvailableBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.CacheBytes, + prometheus.GaugeValue, + dst[0].CacheBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.CacheBytesPeak, + prometheus.GaugeValue, + dst[0].CacheBytesPeak, + ) + + ch <- prometheus.MustNewConstMetric( + c.CacheFaultsTotal, + prometheus.GaugeValue, + dst[0].CacheFaultsPersec, + ) + + ch <- prometheus.MustNewConstMetric( + c.CommitLimit, + prometheus.GaugeValue, + dst[0].CommitLimit, + ) + + ch <- prometheus.MustNewConstMetric( + c.CommittedBytes, + prometheus.GaugeValue, + dst[0].CommittedBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.DemandZeroFaultsTotal, + prometheus.GaugeValue, + dst[0].DemandZeroFaultsPersec, + ) + + ch <- prometheus.MustNewConstMetric( + c.FreeAndZeroPageListBytes, + prometheus.GaugeValue, + dst[0].FreeAndZeroPageListBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.FreeSystemPageTableEntries, + prometheus.GaugeValue, + dst[0].FreeSystemPageTableEntries, + ) + + ch <- prometheus.MustNewConstMetric( + c.ModifiedPageListBytes, + prometheus.GaugeValue, + dst[0].ModifiedPageListBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.PageFaultsTotal, + prometheus.GaugeValue, + dst[0].PageFaultsPersec, + ) + + ch <- prometheus.MustNewConstMetric( + c.SwapPageReadsTotal, + prometheus.GaugeValue, + dst[0].PageReadsPersec, + ) + + ch <- prometheus.MustNewConstMetric( + c.SwapPagesReadTotal, + prometheus.GaugeValue, + dst[0].PagesInputPersec, + ) + + ch <- prometheus.MustNewConstMetric( + c.SwapPagesWrittenTotal, + prometheus.GaugeValue, + dst[0].PagesOutputPersec, + ) + + ch <- prometheus.MustNewConstMetric( + c.SwapPageOperationsTotal, + prometheus.GaugeValue, + dst[0].PagesPersec, + ) + + ch <- prometheus.MustNewConstMetric( + c.SwapPageWritesTotal, + prometheus.GaugeValue, + dst[0].PageWritesPersec, + ) + + ch <- prometheus.MustNewConstMetric( + c.PoolNonpagedAllocsTotal, + prometheus.GaugeValue, + dst[0].PoolNonpagedAllocs, + ) + + ch <- prometheus.MustNewConstMetric( + c.PoolNonpagedBytes, + prometheus.GaugeValue, + dst[0].PoolNonpagedBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.PoolPagedAllocsTotal, + prometheus.GaugeValue, + dst[0].PoolPagedAllocs, + ) + + ch <- prometheus.MustNewConstMetric( + c.PoolPagedBytes, + prometheus.GaugeValue, + dst[0].PoolPagedBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.PoolPagedResidentBytes, + prometheus.GaugeValue, + dst[0].PoolPagedResidentBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.StandbyCacheCoreBytes, + prometheus.GaugeValue, + dst[0].StandbyCacheCoreBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.StandbyCacheNormalPriorityBytes, + prometheus.GaugeValue, + dst[0].StandbyCacheNormalPriorityBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.StandbyCacheReserveBytes, + prometheus.GaugeValue, + dst[0].StandbyCacheReserveBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.SystemCacheResidentBytes, + prometheus.GaugeValue, + dst[0].SystemCacheResidentBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.SystemCodeResidentBytes, + prometheus.GaugeValue, + dst[0].SystemCodeResidentBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.SystemCodeTotalBytes, + prometheus.GaugeValue, + dst[0].SystemCodeTotalBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.SystemDriverResidentBytes, + prometheus.GaugeValue, + dst[0].SystemDriverResidentBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.SystemDriverTotalBytes, + prometheus.GaugeValue, + dst[0].SystemDriverTotalBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.TransitionFaultsTotal, + prometheus.GaugeValue, + dst[0].TransitionFaultsPersec, + ) + + ch <- prometheus.MustNewConstMetric( + c.TransitionPagesRepurposedTotal, + prometheus.GaugeValue, + dst[0].TransitionPagesRePurposedPersec, + ) + + ch <- prometheus.MustNewConstMetric( + c.WriteCopiesTotal, + prometheus.GaugeValue, + dst[0].WriteCopiesPersec, + ) + + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/msmq.go b/vendor/github.com/prometheus-community/windows_exporter/collector/msmq.go new file mode 100644 index 000000000000..601fd2d58804 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/msmq.go @@ -0,0 +1,138 @@ +// +build windows + +package collector + +import ( + "strings" + + "github.com/StackExchange/wmi" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" + "gopkg.in/alecthomas/kingpin.v2" +) + +func init() { + registerCollectorWithConfig("msmq", func() Config { return &MSMQConfig{} }) +} + +type MSMQConfig struct { + MSMQWhereClause string +} + +func (m *MSMQConfig) RegisterKingpin(ka *kingpin.Application) { + ka.Flag( + "collector.msmq.msmq-where", + "WQL 'where' clause to use in WMI metrics query. Limits the response to the msmqs you specify and reduces the size of the response.", + ).StringVar(&m.MSMQWhereClause) +} + +func (m *MSMQConfig) Build() (Collector, error) { + return NewMSMQCollector(m) +} + +// A Win32_PerfRawData_MSMQ_MSMQQueueCollector is a Prometheus collector for WMI Win32_PerfRawData_MSMQ_MSMQQueue metrics +type Win32_PerfRawData_MSMQ_MSMQQueueCollector struct { + BytesinJournalQueue *prometheus.Desc + BytesinQueue *prometheus.Desc + MessagesinJournalQueue *prometheus.Desc + MessagesinQueue *prometheus.Desc + + queryWhereClause string +} + +// NewWin32_PerfRawData_MSMQ_MSMQQueueCollector ... +func NewMSMQCollector(m *MSMQConfig) (Collector, error) { + const subsystem = "msmq" + + if m.MSMQWhereClause == "" { + log.Warn("No where-clause specified for msmq collector. This will generate a very large number of metrics!") + } + + return &Win32_PerfRawData_MSMQ_MSMQQueueCollector{ + BytesinJournalQueue: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bytes_in_journal_queue"), + "Size of queue journal in bytes", + []string{"name"}, + nil, + ), + BytesinQueue: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bytes_in_queue"), + "Size of queue in bytes", + []string{"name"}, + nil, + ), + MessagesinJournalQueue: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "messages_in_journal_queue"), + "Count messages in queue journal", + []string{"name"}, + nil, + ), + MessagesinQueue: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "messages_in_queue"), + "Count messages in queue", + []string{"name"}, + nil, + ), + queryWhereClause: m.MSMQWhereClause, + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *Win32_PerfRawData_MSMQ_MSMQQueueCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + log.Error("failed collecting msmq metrics:", desc, err) + return err + } + return nil +} + +type Win32_PerfRawData_MSMQ_MSMQQueue struct { + Name string + + BytesinJournalQueue uint64 + BytesinQueue uint64 + MessagesinJournalQueue uint64 + MessagesinQueue uint64 +} + +func (c *Win32_PerfRawData_MSMQ_MSMQQueueCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_MSMQ_MSMQQueue + q := queryAllWhere(&dst, c.queryWhereClause) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, msmq := range dst { + + if msmq.Name == "Computer Queues" { + continue + } + + ch <- prometheus.MustNewConstMetric( + c.BytesinJournalQueue, + prometheus.GaugeValue, + float64(msmq.BytesinJournalQueue), + strings.ToLower(msmq.Name), + ) + ch <- prometheus.MustNewConstMetric( + c.BytesinQueue, + prometheus.GaugeValue, + float64(msmq.BytesinQueue), + strings.ToLower(msmq.Name), + ) + ch <- prometheus.MustNewConstMetric( + c.MessagesinJournalQueue, + prometheus.GaugeValue, + float64(msmq.MessagesinJournalQueue), + strings.ToLower(msmq.Name), + ) + ch <- prometheus.MustNewConstMetric( + c.MessagesinQueue, + prometheus.GaugeValue, + float64(msmq.MessagesinQueue), + strings.ToLower(msmq.Name), + ) + } + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/mssql.go b/vendor/github.com/prometheus-community/windows_exporter/collector/mssql.go new file mode 100644 index 000000000000..961d5c514e0a --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/mssql.go @@ -0,0 +1,3898 @@ +// +build windows + +package collector + +import ( + "errors" + "fmt" + "os" + "strings" + "sync" + "time" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" + "golang.org/x/sys/windows/registry" + "gopkg.in/alecthomas/kingpin.v2" +) + +type mssqlInstancesType map[string]string + +func getMSSQLInstances() mssqlInstancesType { + sqlInstances := make(mssqlInstancesType) + + // in case querying the registry fails, return the default instance + sqlDefaultInstance := make(mssqlInstancesType) + sqlDefaultInstance["MSSQLSERVER"] = "" + + regkey := `Software\Microsoft\Microsoft SQL Server\Instance Names\SQL` + k, err := registry.OpenKey(registry.LOCAL_MACHINE, regkey, registry.QUERY_VALUE) + if err != nil { + log.Warn("Couldn't open registry to determine SQL instances:", err) + return sqlDefaultInstance + } + defer func() { + err = k.Close() + if err != nil { + log.Warnf("Failed to close registry key: %v", err) + } + }() + + instanceNames, err := k.ReadValueNames(0) + if err != nil { + log.Warnf("Can't ReadSubKeyNames %#v", err) + return sqlDefaultInstance + } + + for _, instanceName := range instanceNames { + if instanceVersion, _, err := k.GetStringValue(instanceName); err == nil { + sqlInstances[instanceName] = instanceVersion + } + } + + log.Debugf("Detected MSSQL Instances: %#v\n", sqlInstances) + + return sqlInstances +} + +type mssqlCollectorsMap map[string]mssqlCollectorFunc + +func mssqlAvailableClassCollectors() string { + return "accessmethods,availreplica,bufman,databases,dbreplica,genstats,locks,memmgr,sqlstats,sqlerrors,transactions" +} + +func (c *MSSQLCollector) getMSSQLCollectors() mssqlCollectorsMap { + mssqlCollectors := make(mssqlCollectorsMap) + mssqlCollectors["accessmethods"] = c.collectAccessMethods + mssqlCollectors["availreplica"] = c.collectAvailabilityReplica + mssqlCollectors["bufman"] = c.collectBufferManager + mssqlCollectors["databases"] = c.collectDatabases + mssqlCollectors["dbreplica"] = c.collectDatabaseReplica + mssqlCollectors["genstats"] = c.collectGeneralStatistics + mssqlCollectors["locks"] = c.collectLocks + mssqlCollectors["memmgr"] = c.collectMemoryManager + mssqlCollectors["sqlstats"] = c.collectSQLStats + mssqlCollectors["sqlerrors"] = c.collectSQLErrors + mssqlCollectors["transactions"] = c.collectTransactions + + return mssqlCollectors +} + +// mssqlGetPerfObjectName - Returns the name of the Windows Performance +// Counter object for the given SQL instance and collector. +func mssqlGetPerfObjectName(sqlInstance string, collector string) string { + prefix := "SQLServer:" + if sqlInstance != "MSSQLSERVER" { + prefix = "MSSQL$" + sqlInstance + ":" + } + suffix := "" + switch collector { + case "accessmethods": + suffix = "Access Methods" + case "availreplica": + suffix = "Availability Replica" + case "bufman": + suffix = "Buffer Manager" + case "databases": + suffix = "Databases" + case "dbreplica": + suffix = "Database Replica" + case "genstats": + suffix = "General Statistics" + case "locks": + suffix = "Locks" + case "memmgr": + suffix = "Memory Manager" + case "sqlerrors": + suffix = "SQL Errors" + case "sqlstats": + suffix = "SQL Statistics" + case "transactions": + suffix = "Transactions" + } + return (prefix + suffix) +} + +func init() { + registerCollectorWithConfig("mssql", func() Config { + return &MSSQLConfig{} + }) +} + +type MSSQLConfig struct { + MSSQLEnabledCollectors string + MSSQLPrintCollectors bool +} + +func (m *MSSQLConfig) RegisterKingpin(ka *kingpin.Application) { + ka.Flag( + "collectors.mssql.classes-enabled", + "Comma-separated list of mssql WMI classes to use."). + Default(mssqlAvailableClassCollectors()).StringVar(&m.MSSQLEnabledCollectors) + + ka.Flag( + "collectors.mssql.class-print", + "If true, print available mssql WMI classes and exit. Only displays if the mssql collector is enabled.", + ).BoolVar(&m.MSSQLPrintCollectors) +} + +func (m *MSSQLConfig) Build() (Collector, error) { + return NewMSSQLCollector(m) +} + +// A MSSQLCollector is a Prometheus collector for various WMI Win32_PerfRawData_MSSQLSERVER_* metrics +type MSSQLCollector struct { + enabled []string + // meta + mssqlScrapeDurationDesc *prometheus.Desc + mssqlScrapeSuccessDesc *prometheus.Desc + + // Win32_PerfRawData_{instance}_SQLServerAccessMethods + AccessMethodsAUcleanupbatches *prometheus.Desc + AccessMethodsAUcleanups *prometheus.Desc + AccessMethodsByreferenceLobCreateCount *prometheus.Desc + AccessMethodsByreferenceLobUseCount *prometheus.Desc + AccessMethodsCountLobReadahead *prometheus.Desc + AccessMethodsCountPullInRow *prometheus.Desc + AccessMethodsCountPushOffRow *prometheus.Desc + AccessMethodsDeferreddroppedAUs *prometheus.Desc + AccessMethodsDeferredDroppedrowsets *prometheus.Desc + AccessMethodsDroppedrowsetcleanups *prometheus.Desc + AccessMethodsDroppedrowsetsskipped *prometheus.Desc + AccessMethodsExtentDeallocations *prometheus.Desc + AccessMethodsExtentsAllocated *prometheus.Desc + AccessMethodsFailedAUcleanupbatches *prometheus.Desc + AccessMethodsFailedleafpagecookie *prometheus.Desc + AccessMethodsFailedtreepagecookie *prometheus.Desc + AccessMethodsForwardedRecords *prometheus.Desc + AccessMethodsFreeSpacePageFetches *prometheus.Desc + AccessMethodsFreeSpaceScans *prometheus.Desc + AccessMethodsFullScans *prometheus.Desc + AccessMethodsIndexSearches *prometheus.Desc + AccessMethodsInSysXactwaits *prometheus.Desc + AccessMethodsLobHandleCreateCount *prometheus.Desc + AccessMethodsLobHandleDestroyCount *prometheus.Desc + AccessMethodsLobSSProviderCreateCount *prometheus.Desc + AccessMethodsLobSSProviderDestroyCount *prometheus.Desc + AccessMethodsLobSSProviderTruncationCount *prometheus.Desc + AccessMethodsMixedpageallocations *prometheus.Desc + AccessMethodsPagecompressionattempts *prometheus.Desc + AccessMethodsPageDeallocations *prometheus.Desc + AccessMethodsPagesAllocated *prometheus.Desc + AccessMethodsPagescompressed *prometheus.Desc + AccessMethodsPageSplits *prometheus.Desc + AccessMethodsProbeScans *prometheus.Desc + AccessMethodsRangeScans *prometheus.Desc + AccessMethodsScanPointRevalidations *prometheus.Desc + AccessMethodsSkippedGhostedRecords *prometheus.Desc + AccessMethodsTableLockEscalations *prometheus.Desc + AccessMethodsUsedleafpagecookie *prometheus.Desc + AccessMethodsUsedtreepagecookie *prometheus.Desc + AccessMethodsWorkfilesCreated *prometheus.Desc + AccessMethodsWorktablesCreated *prometheus.Desc + AccessMethodsWorktablesFromCacheHits *prometheus.Desc + AccessMethodsWorktablesFromCacheLookups *prometheus.Desc + + // Win32_PerfRawData_{instance}_SQLServerAvailabilityReplica + AvailReplicaBytesReceivedfromReplica *prometheus.Desc + AvailReplicaBytesSenttoReplica *prometheus.Desc + AvailReplicaBytesSenttoTransport *prometheus.Desc + AvailReplicaFlowControl *prometheus.Desc + AvailReplicaFlowControlTimems *prometheus.Desc + AvailReplicaReceivesfromReplica *prometheus.Desc + AvailReplicaResentMessages *prometheus.Desc + AvailReplicaSendstoReplica *prometheus.Desc + AvailReplicaSendstoTransport *prometheus.Desc + + // Win32_PerfRawData_{instance}_SQLServerBufferManager + BufManBackgroundwriterpages *prometheus.Desc + BufManBuffercachehits *prometheus.Desc + BufManBuffercachelookups *prometheus.Desc + BufManCheckpointpages *prometheus.Desc + BufManDatabasepages *prometheus.Desc + BufManExtensionallocatedpages *prometheus.Desc + BufManExtensionfreepages *prometheus.Desc + BufManExtensioninuseaspercentage *prometheus.Desc + BufManExtensionoutstandingIOcounter *prometheus.Desc + BufManExtensionpageevictions *prometheus.Desc + BufManExtensionpagereads *prometheus.Desc + BufManExtensionpageunreferencedtime *prometheus.Desc + BufManExtensionpagewrites *prometheus.Desc + BufManFreeliststalls *prometheus.Desc + BufManIntegralControllerSlope *prometheus.Desc + BufManLazywrites *prometheus.Desc + BufManPagelifeexpectancy *prometheus.Desc + BufManPagelookups *prometheus.Desc + BufManPagereads *prometheus.Desc + BufManPagewrites *prometheus.Desc + BufManReadaheadpages *prometheus.Desc + BufManReadaheadtime *prometheus.Desc + BufManTargetpages *prometheus.Desc + + // Win32_PerfRawData_{instance}_SQLServerDatabaseReplica + DBReplicaDatabaseFlowControlDelay *prometheus.Desc + DBReplicaDatabaseFlowControls *prometheus.Desc + DBReplicaFileBytesReceived *prometheus.Desc + DBReplicaGroupCommits *prometheus.Desc + DBReplicaGroupCommitTime *prometheus.Desc + DBReplicaLogApplyPendingQueue *prometheus.Desc + DBReplicaLogApplyReadyQueue *prometheus.Desc + DBReplicaLogBytesCompressed *prometheus.Desc + DBReplicaLogBytesDecompressed *prometheus.Desc + DBReplicaLogBytesReceived *prometheus.Desc + DBReplicaLogCompressionCachehits *prometheus.Desc + DBReplicaLogCompressionCachemisses *prometheus.Desc + DBReplicaLogCompressions *prometheus.Desc + DBReplicaLogDecompressions *prometheus.Desc + DBReplicaLogremainingforundo *prometheus.Desc + DBReplicaLogSendQueue *prometheus.Desc + DBReplicaMirroredWriteTransactions *prometheus.Desc + DBReplicaRecoveryQueue *prometheus.Desc + DBReplicaRedoblocked *prometheus.Desc + DBReplicaRedoBytesRemaining *prometheus.Desc + DBReplicaRedoneBytes *prometheus.Desc + DBReplicaRedones *prometheus.Desc + DBReplicaTotalLogrequiringundo *prometheus.Desc + DBReplicaTransactionDelay *prometheus.Desc + + // Win32_PerfRawData_{instance}_SQLServerDatabases + DatabasesActiveParallelredothreads *prometheus.Desc + DatabasesActiveTransactions *prometheus.Desc + DatabasesBackupPerRestoreThroughput *prometheus.Desc + DatabasesBulkCopyRows *prometheus.Desc + DatabasesBulkCopyThroughput *prometheus.Desc + DatabasesCommittableentries *prometheus.Desc + DatabasesDataFilesSizeKB *prometheus.Desc + DatabasesDBCCLogicalScanBytes *prometheus.Desc + DatabasesGroupCommitTime *prometheus.Desc + DatabasesLogBytesFlushed *prometheus.Desc + DatabasesLogCacheHits *prometheus.Desc + DatabasesLogCacheLookups *prometheus.Desc + DatabasesLogCacheReads *prometheus.Desc + DatabasesLogFilesSizeKB *prometheus.Desc + DatabasesLogFilesUsedSizeKB *prometheus.Desc + DatabasesLogFlushes *prometheus.Desc + DatabasesLogFlushWaits *prometheus.Desc + DatabasesLogFlushWaitTime *prometheus.Desc + DatabasesLogFlushWriteTimems *prometheus.Desc + DatabasesLogGrowths *prometheus.Desc + DatabasesLogPoolCacheMisses *prometheus.Desc + DatabasesLogPoolDiskReads *prometheus.Desc + DatabasesLogPoolHashDeletes *prometheus.Desc + DatabasesLogPoolHashInserts *prometheus.Desc + DatabasesLogPoolInvalidHashEntry *prometheus.Desc + DatabasesLogPoolLogScanPushes *prometheus.Desc + DatabasesLogPoolLogWriterPushes *prometheus.Desc + DatabasesLogPoolPushEmptyFreePool *prometheus.Desc + DatabasesLogPoolPushLowMemory *prometheus.Desc + DatabasesLogPoolPushNoFreeBuffer *prometheus.Desc + DatabasesLogPoolReqBehindTrunc *prometheus.Desc + DatabasesLogPoolRequestsOldVLF *prometheus.Desc + DatabasesLogPoolRequests *prometheus.Desc + DatabasesLogPoolTotalActiveLogSize *prometheus.Desc + DatabasesLogPoolTotalSharedPoolSize *prometheus.Desc + DatabasesLogShrinks *prometheus.Desc + DatabasesLogTruncations *prometheus.Desc + DatabasesPercentLogUsed *prometheus.Desc + DatabasesReplPendingXacts *prometheus.Desc + DatabasesReplTransRate *prometheus.Desc + DatabasesShrinkDataMovementBytes *prometheus.Desc + DatabasesTrackedtransactions *prometheus.Desc + DatabasesTransactions *prometheus.Desc + DatabasesWriteTransactions *prometheus.Desc + DatabasesXTPControllerDLCLatencyPerFetch *prometheus.Desc + DatabasesXTPControllerDLCPeakLatency *prometheus.Desc + DatabasesXTPControllerLogProcessed *prometheus.Desc + DatabasesXTPMemoryUsedKB *prometheus.Desc + + // Win32_PerfRawData_{instance}_SQLServerGeneralStatistics + GenStatsActiveTempTables *prometheus.Desc + GenStatsConnectionReset *prometheus.Desc + GenStatsEventNotificationsDelayedDrop *prometheus.Desc + GenStatsHTTPAuthenticatedRequests *prometheus.Desc + GenStatsLogicalConnections *prometheus.Desc + GenStatsLogins *prometheus.Desc + GenStatsLogouts *prometheus.Desc + GenStatsMarsDeadlocks *prometheus.Desc + GenStatsNonatomicyieldrate *prometheus.Desc + GenStatsProcessesblocked *prometheus.Desc + GenStatsSOAPEmptyRequests *prometheus.Desc + GenStatsSOAPMethodInvocations *prometheus.Desc + GenStatsSOAPSessionInitiateRequests *prometheus.Desc + GenStatsSOAPSessionTerminateRequests *prometheus.Desc + GenStatsSOAPSQLRequests *prometheus.Desc + GenStatsSOAPWSDLRequests *prometheus.Desc + GenStatsSQLTraceIOProviderLockWaits *prometheus.Desc + GenStatsTempdbrecoveryunitid *prometheus.Desc + GenStatsTempdbrowsetid *prometheus.Desc + GenStatsTempTablesCreationRate *prometheus.Desc + GenStatsTempTablesForDestruction *prometheus.Desc + GenStatsTraceEventNotificationQueue *prometheus.Desc + GenStatsTransactions *prometheus.Desc + GenStatsUserConnections *prometheus.Desc + + // Win32_PerfRawData_{instance}_SQLServerLocks + LocksWaitTime *prometheus.Desc + LocksCount *prometheus.Desc + LocksLockRequests *prometheus.Desc + LocksLockTimeouts *prometheus.Desc + LocksLockTimeoutstimeout0 *prometheus.Desc + LocksLockWaits *prometheus.Desc + LocksLockWaitTimems *prometheus.Desc + LocksNumberofDeadlocks *prometheus.Desc + + // Win32_PerfRawData_{instance}_SQLServerMemoryManager + MemMgrConnectionMemoryKB *prometheus.Desc + MemMgrDatabaseCacheMemoryKB *prometheus.Desc + MemMgrExternalbenefitofmemory *prometheus.Desc + MemMgrFreeMemoryKB *prometheus.Desc + MemMgrGrantedWorkspaceMemoryKB *prometheus.Desc + MemMgrLockBlocks *prometheus.Desc + MemMgrLockBlocksAllocated *prometheus.Desc + MemMgrLockMemoryKB *prometheus.Desc + MemMgrLockOwnerBlocks *prometheus.Desc + MemMgrLockOwnerBlocksAllocated *prometheus.Desc + MemMgrLogPoolMemoryKB *prometheus.Desc + MemMgrMaximumWorkspaceMemoryKB *prometheus.Desc + MemMgrMemoryGrantsOutstanding *prometheus.Desc + MemMgrMemoryGrantsPending *prometheus.Desc + MemMgrOptimizerMemoryKB *prometheus.Desc + MemMgrReservedServerMemoryKB *prometheus.Desc + MemMgrSQLCacheMemoryKB *prometheus.Desc + MemMgrStolenServerMemoryKB *prometheus.Desc + MemMgrTargetServerMemoryKB *prometheus.Desc + MemMgrTotalServerMemoryKB *prometheus.Desc + + // Win32_PerfRawData_{instance}_SQLServerSQLStatistics + SQLStatsAutoParamAttempts *prometheus.Desc + SQLStatsBatchRequests *prometheus.Desc + SQLStatsFailedAutoParams *prometheus.Desc + SQLStatsForcedParameterizations *prometheus.Desc + SQLStatsGuidedplanexecutions *prometheus.Desc + SQLStatsMisguidedplanexecutions *prometheus.Desc + SQLStatsSafeAutoParams *prometheus.Desc + SQLStatsSQLAttentionrate *prometheus.Desc + SQLStatsSQLCompilations *prometheus.Desc + SQLStatsSQLReCompilations *prometheus.Desc + SQLStatsUnsafeAutoParams *prometheus.Desc + + // Win32_PerfRawData_{instance}_SQLServerSQLErrors + SQLErrorsTotal *prometheus.Desc + + // Win32_PerfRawData_{instance}_SQLServerTransactions + TransactionsTempDbFreeSpaceBytes *prometheus.Desc + TransactionsLongestTransactionRunningSeconds *prometheus.Desc + TransactionsNonSnapshotVersionActiveTotal *prometheus.Desc + TransactionsSnapshotActiveTotal *prometheus.Desc + TransactionsActive *prometheus.Desc + TransactionsUpdateConflictsTotal *prometheus.Desc + TransactionsUpdateSnapshotActiveTotal *prometheus.Desc + TransactionsVersionCleanupRateBytes *prometheus.Desc + TransactionsVersionGenerationRateBytes *prometheus.Desc + TransactionsVersionStoreSizeBytes *prometheus.Desc + TransactionsVersionStoreUnits *prometheus.Desc + TransactionsVersionStoreCreationUnits *prometheus.Desc + TransactionsVersionStoreTruncationUnits *prometheus.Desc + + mssqlInstances mssqlInstancesType + mssqlCollectors mssqlCollectorsMap + mssqlChildCollectorFailure int +} + +// NewMSSQLCollector ... +func NewMSSQLCollector(c *MSSQLConfig) (Collector, error) { + + const subsystem = "mssql" + + enabled := expandEnabledChildCollectors(c.MSSQLEnabledCollectors) + mssqlInstances := getMSSQLInstances() + perfCounters := make([]string, 0, len(mssqlInstances)*len(enabled)) + for instance := range mssqlInstances { + for _, c := range enabled { + perfCounters = append(perfCounters, mssqlGetPerfObjectName(instance, c)) + } + } + addPerfCounterDependencies(subsystem, perfCounters) + + mssqlCollector := MSSQLCollector{ + // meta + mssqlScrapeDurationDesc: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "collector_duration_seconds"), + "windows_exporter: Duration of an mssql child collection.", + []string{"collector", "mssql_instance"}, + nil, + ), + mssqlScrapeSuccessDesc: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "collector_success"), + "windows_exporter: Whether a mssql child collector was successful.", + []string{"collector", "mssql_instance"}, + nil, + ), + + // Win32_PerfRawData_{instance}_SQLServerAccessMethods + AccessMethodsAUcleanupbatches: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_au_batch_cleanups"), + "(AccessMethods.AUcleanupbatches)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsAUcleanups: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_au_cleanups"), + "(AccessMethods.AUcleanups)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsByreferenceLobCreateCount: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_by_reference_lob_creates"), + "(AccessMethods.ByreferenceLobCreateCount)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsByreferenceLobUseCount: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_by_reference_lob_uses"), + "(AccessMethods.ByreferenceLobUseCount)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsCountLobReadahead: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_lob_read_aheads"), + "(AccessMethods.CountLobReadahead)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsCountPullInRow: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_column_value_pulls"), + "(AccessMethods.CountPullInRow)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsCountPushOffRow: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_column_value_pushes"), + "(AccessMethods.CountPushOffRow)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsDeferreddroppedAUs: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_deferred_dropped_aus"), + "(AccessMethods.DeferreddroppedAUs)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsDeferredDroppedrowsets: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_deferred_dropped_rowsets"), + "(AccessMethods.DeferredDroppedrowsets)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsDroppedrowsetcleanups: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_dropped_rowset_cleanups"), + "(AccessMethods.Droppedrowsetcleanups)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsDroppedrowsetsskipped: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_dropped_rowset_skips"), + "(AccessMethods.Droppedrowsetsskipped)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsExtentDeallocations: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_extent_deallocations"), + "(AccessMethods.ExtentDeallocations)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsExtentsAllocated: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_extent_allocations"), + "(AccessMethods.ExtentsAllocated)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsFailedAUcleanupbatches: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_au_batch_cleanup_failures"), + "(AccessMethods.FailedAUcleanupbatches)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsFailedleafpagecookie: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_leaf_page_cookie_failures"), + "(AccessMethods.Failedleafpagecookie)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsFailedtreepagecookie: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_tree_page_cookie_failures"), + "(AccessMethods.Failedtreepagecookie)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsForwardedRecords: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_forwarded_records"), + "(AccessMethods.ForwardedRecords)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsFreeSpacePageFetches: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_free_space_page_fetches"), + "(AccessMethods.FreeSpacePageFetches)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsFreeSpaceScans: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_free_space_scans"), + "(AccessMethods.FreeSpaceScans)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsFullScans: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_full_scans"), + "(AccessMethods.FullScans)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsIndexSearches: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_index_searches"), + "(AccessMethods.IndexSearches)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsInSysXactwaits: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_insysxact_waits"), + "(AccessMethods.InSysXactwaits)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsLobHandleCreateCount: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_lob_handle_creates"), + "(AccessMethods.LobHandleCreateCount)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsLobHandleDestroyCount: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_lob_handle_destroys"), + "(AccessMethods.LobHandleDestroyCount)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsLobSSProviderCreateCount: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_lob_ss_provider_creates"), + "(AccessMethods.LobSSProviderCreateCount)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsLobSSProviderDestroyCount: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_lob_ss_provider_destroys"), + "(AccessMethods.LobSSProviderDestroyCount)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsLobSSProviderTruncationCount: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_lob_ss_provider_truncations"), + "(AccessMethods.LobSSProviderTruncationCount)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsMixedpageallocations: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_mixed_page_allocations"), + "(AccessMethods.MixedpageallocationsPersec)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsPagecompressionattempts: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_page_compression_attempts"), + "(AccessMethods.PagecompressionattemptsPersec)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsPageDeallocations: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_page_deallocations"), + "(AccessMethods.PageDeallocationsPersec)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsPagesAllocated: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_page_allocations"), + "(AccessMethods.PagesAllocatedPersec)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsPagescompressed: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_page_compressions"), + "(AccessMethods.PagescompressedPersec)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsPageSplits: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_page_splits"), + "(AccessMethods.PageSplitsPersec)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsProbeScans: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_probe_scans"), + "(AccessMethods.ProbeScansPersec)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsRangeScans: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_range_scans"), + "(AccessMethods.RangeScansPersec)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsScanPointRevalidations: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_scan_point_revalidations"), + "(AccessMethods.ScanPointRevalidationsPersec)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsSkippedGhostedRecords: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_ghost_record_skips"), + "(AccessMethods.SkippedGhostedRecordsPersec)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsTableLockEscalations: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_table_lock_escalations"), + "(AccessMethods.TableLockEscalationsPersec)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsUsedleafpagecookie: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_leaf_page_cookie_uses"), + "(AccessMethods.Usedleafpagecookie)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsUsedtreepagecookie: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_tree_page_cookie_uses"), + "(AccessMethods.Usedtreepagecookie)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsWorkfilesCreated: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_workfile_creates"), + "(AccessMethods.WorkfilesCreatedPersec)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsWorktablesCreated: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_worktables_creates"), + "(AccessMethods.WorktablesCreatedPersec)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsWorktablesFromCacheHits: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_worktables_from_cache_hits"), + "(AccessMethods.WorktablesFromCacheRatio)", + []string{"mssql_instance"}, + nil, + ), + AccessMethodsWorktablesFromCacheLookups: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "accessmethods_worktables_from_cache_lookups"), + "(AccessMethods.WorktablesFromCacheRatio_Base)", + []string{"mssql_instance"}, + nil, + ), + + // Win32_PerfRawData_{instance}_SQLServerAvailabilityReplica + AvailReplicaBytesReceivedfromReplica: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "availreplica_received_from_replica_bytes"), + "(AvailabilityReplica.BytesReceivedfromReplica)", + []string{"mssql_instance", "replica"}, + nil, + ), + AvailReplicaBytesSenttoReplica: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "availreplica_sent_to_replica_bytes"), + "(AvailabilityReplica.BytesSenttoReplica)", + []string{"mssql_instance", "replica"}, + nil, + ), + AvailReplicaBytesSenttoTransport: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "availreplica_sent_to_transport_bytes"), + "(AvailabilityReplica.BytesSenttoTransport)", + []string{"mssql_instance", "replica"}, + nil, + ), + AvailReplicaFlowControl: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "availreplica_initiated_flow_controls"), + "(AvailabilityReplica.FlowControl)", + []string{"mssql_instance", "replica"}, + nil, + ), + AvailReplicaFlowControlTimems: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "availreplica_flow_control_wait_seconds"), + "(AvailabilityReplica.FlowControlTimems)", + []string{"mssql_instance", "replica"}, + nil, + ), + AvailReplicaReceivesfromReplica: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "availreplica_receives_from_replica"), + "(AvailabilityReplica.ReceivesfromReplica)", + []string{"mssql_instance", "replica"}, + nil, + ), + AvailReplicaResentMessages: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "availreplica_resent_messages"), + "(AvailabilityReplica.ResentMessages)", + []string{"mssql_instance", "replica"}, + nil, + ), + AvailReplicaSendstoReplica: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "availreplica_sends_to_replica"), + "(AvailabilityReplica.SendstoReplica)", + []string{"mssql_instance", "replica"}, + nil, + ), + AvailReplicaSendstoTransport: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "availreplica_sends_to_transport"), + "(AvailabilityReplica.SendstoTransport)", + []string{"mssql_instance", "replica"}, + nil, + ), + + // Win32_PerfRawData_{instance}_SQLServerBufferManager + BufManBackgroundwriterpages: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bufman_background_writer_pages"), + "(BufferManager.Backgroundwriterpages)", + []string{"mssql_instance"}, + nil, + ), + BufManBuffercachehits: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bufman_buffer_cache_hits"), + "(BufferManager.Buffercachehitratio)", + []string{"mssql_instance"}, + nil, + ), + BufManBuffercachelookups: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bufman_buffer_cache_lookups"), + "(BufferManager.Buffercachehitratio_Base)", + []string{"mssql_instance"}, + nil, + ), + BufManCheckpointpages: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bufman_checkpoint_pages"), + "(BufferManager.Checkpointpages)", + []string{"mssql_instance"}, + nil, + ), + BufManDatabasepages: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bufman_database_pages"), + "(BufferManager.Databasepages)", + []string{"mssql_instance"}, + nil, + ), + BufManExtensionallocatedpages: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bufman_extension_allocated_pages"), + "(BufferManager.Extensionallocatedpages)", + []string{"mssql_instance"}, + nil, + ), + BufManExtensionfreepages: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bufman_extension_free_pages"), + "(BufferManager.Extensionfreepages)", + []string{"mssql_instance"}, + nil, + ), + BufManExtensioninuseaspercentage: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bufman_extension_in_use_as_percentage"), + "(BufferManager.Extensioninuseaspercentage)", + []string{"mssql_instance"}, + nil, + ), + BufManExtensionoutstandingIOcounter: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bufman_extension_outstanding_io"), + "(BufferManager.ExtensionoutstandingIOcounter)", + []string{"mssql_instance"}, + nil, + ), + BufManExtensionpageevictions: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bufman_extension_page_evictions"), + "(BufferManager.Extensionpageevictions)", + []string{"mssql_instance"}, + nil, + ), + BufManExtensionpagereads: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bufman_extension_page_reads"), + "(BufferManager.Extensionpagereads)", + []string{"mssql_instance"}, + nil, + ), + BufManExtensionpageunreferencedtime: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bufman_extension_page_unreferenced_seconds"), + "(BufferManager.Extensionpageunreferencedtime)", + []string{"mssql_instance"}, + nil, + ), + BufManExtensionpagewrites: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bufman_extension_page_writes"), + "(BufferManager.Extensionpagewrites)", + []string{"mssql_instance"}, + nil, + ), + BufManFreeliststalls: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bufman_free_list_stalls"), + "(BufferManager.Freeliststalls)", + []string{"mssql_instance"}, + nil, + ), + BufManIntegralControllerSlope: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bufman_integral_controller_slope"), + "(BufferManager.IntegralControllerSlope)", + []string{"mssql_instance"}, + nil, + ), + BufManLazywrites: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bufman_lazywrites"), + "(BufferManager.Lazywrites)", + []string{"mssql_instance"}, + nil, + ), + BufManPagelifeexpectancy: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bufman_page_life_expectancy_seconds"), + "(BufferManager.Pagelifeexpectancy)", + []string{"mssql_instance"}, + nil, + ), + BufManPagelookups: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bufman_page_lookups"), + "(BufferManager.Pagelookups)", + []string{"mssql_instance"}, + nil, + ), + BufManPagereads: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bufman_page_reads"), + "(BufferManager.Pagereads)", + []string{"mssql_instance"}, + nil, + ), + BufManPagewrites: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bufman_page_writes"), + "(BufferManager.Pagewrites)", + []string{"mssql_instance"}, + nil, + ), + BufManReadaheadpages: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bufman_read_ahead_pages"), + "(BufferManager.Readaheadpages)", + []string{"mssql_instance"}, + nil, + ), + BufManReadaheadtime: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bufman_read_ahead_issuing_seconds"), + "(BufferManager.Readaheadtime)", + []string{"mssql_instance"}, + nil, + ), + BufManTargetpages: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bufman_target_pages"), + "(BufferManager.Targetpages)", + []string{"mssql_instance"}, + nil, + ), + + // Win32_PerfRawData_{instance}_SQLServerDatabaseReplica + DBReplicaDatabaseFlowControlDelay: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dbreplica_database_flow_control_wait_seconds"), + "(DatabaseReplica.DatabaseFlowControlDelay)", + []string{"mssql_instance", "replica"}, + nil, + ), + DBReplicaDatabaseFlowControls: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dbreplica_database_initiated_flow_controls"), + "(DatabaseReplica.DatabaseFlowControls)", + []string{"mssql_instance", "replica"}, + nil, + ), + DBReplicaFileBytesReceived: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dbreplica_received_file_bytes"), + "(DatabaseReplica.FileBytesReceived)", + []string{"mssql_instance", "replica"}, + nil, + ), + DBReplicaGroupCommits: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dbreplica_group_commits"), + "(DatabaseReplica.GroupCommits)", + []string{"mssql_instance", "replica"}, + nil, + ), + DBReplicaGroupCommitTime: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dbreplica_group_commit_stall_seconds"), + "(DatabaseReplica.GroupCommitTime)", + []string{"mssql_instance", "replica"}, + nil, + ), + DBReplicaLogApplyPendingQueue: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dbreplica_log_apply_pending_queue"), + "(DatabaseReplica.LogApplyPendingQueue)", + []string{"mssql_instance", "replica"}, + nil, + ), + DBReplicaLogApplyReadyQueue: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dbreplica_log_apply_ready_queue"), + "(DatabaseReplica.LogApplyReadyQueue)", + []string{"mssql_instance", "replica"}, + nil, + ), + DBReplicaLogBytesCompressed: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dbreplica_log_compressed_bytes"), + "(DatabaseReplica.LogBytesCompressed)", + []string{"mssql_instance", "replica"}, + nil, + ), + DBReplicaLogBytesDecompressed: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dbreplica_log_decompressed_bytes"), + "(DatabaseReplica.LogBytesDecompressed)", + []string{"mssql_instance", "replica"}, + nil, + ), + DBReplicaLogBytesReceived: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dbreplica_log_received_bytes"), + "(DatabaseReplica.LogBytesReceived)", + []string{"mssql_instance", "replica"}, + nil, + ), + DBReplicaLogCompressionCachehits: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dbreplica_log_compression_cachehits"), + "(DatabaseReplica.LogCompressionCachehits)", + []string{"mssql_instance", "replica"}, + nil, + ), + DBReplicaLogCompressionCachemisses: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dbreplica_log_compression_cachemisses"), + "(DatabaseReplica.LogCompressionCachemisses)", + []string{"mssql_instance", "replica"}, + nil, + ), + DBReplicaLogCompressions: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dbreplica_log_compressions"), + "(DatabaseReplica.LogCompressions)", + []string{"mssql_instance", "replica"}, + nil, + ), + DBReplicaLogDecompressions: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dbreplica_log_decompressions"), + "(DatabaseReplica.LogDecompressions)", + []string{"mssql_instance", "replica"}, + nil, + ), + DBReplicaLogremainingforundo: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dbreplica_log_remaining_for_undo"), + "(DatabaseReplica.Logremainingforundo)", + []string{"mssql_instance", "replica"}, + nil, + ), + DBReplicaLogSendQueue: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dbreplica_log_send_queue"), + "(DatabaseReplica.LogSendQueue)", + []string{"mssql_instance", "replica"}, + nil, + ), + DBReplicaMirroredWriteTransactions: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dbreplica_mirrored_write_transactions"), + "(DatabaseReplica.MirroredWriteTransactions)", + []string{"mssql_instance", "replica"}, + nil, + ), + DBReplicaRecoveryQueue: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dbreplica_recovery_queue_records"), + "(DatabaseReplica.RecoveryQueue)", + []string{"mssql_instance", "replica"}, + nil, + ), + DBReplicaRedoblocked: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dbreplica_redo_blocks"), + "(DatabaseReplica.Redoblocked)", + []string{"mssql_instance", "replica"}, + nil, + ), + DBReplicaRedoBytesRemaining: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dbreplica_redo_remaining_bytes"), + "(DatabaseReplica.RedoBytesRemaining)", + []string{"mssql_instance", "replica"}, + nil, + ), + DBReplicaRedoneBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dbreplica_redone_bytes"), + "(DatabaseReplica.RedoneBytes)", + []string{"mssql_instance", "replica"}, + nil, + ), + DBReplicaRedones: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dbreplica_redones"), + "(DatabaseReplica.Redones)", + []string{"mssql_instance", "replica"}, + nil, + ), + DBReplicaTotalLogrequiringundo: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dbreplica_total_log_requiring_undo"), + "(DatabaseReplica.TotalLogrequiringundo)", + []string{"mssql_instance", "replica"}, + nil, + ), + DBReplicaTransactionDelay: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dbreplica_transaction_delay_seconds"), + "(DatabaseReplica.TransactionDelay)", + []string{"mssql_instance", "replica"}, + nil, + ), + + // Win32_PerfRawData_{instance}_SQLServerDatabases + DatabasesActiveParallelredothreads: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_active_parallel_redo_threads"), + "(Databases.ActiveParallelredothreads)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesActiveTransactions: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_active_transactions"), + "(Databases.ActiveTransactions)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesBackupPerRestoreThroughput: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_backup_restore_operations"), + "(Databases.BackupPerRestoreThroughput)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesBulkCopyRows: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_bulk_copy_rows"), + "(Databases.BulkCopyRows)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesBulkCopyThroughput: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_bulk_copy_bytes"), + "(Databases.BulkCopyThroughput)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesCommittableentries: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_commit_table_entries"), + "(Databases.Committableentries)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesDataFilesSizeKB: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_data_files_size_bytes"), + "(Databases.DataFilesSizeKB)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesDBCCLogicalScanBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_dbcc_logical_scan_bytes"), + "(Databases.DBCCLogicalScanBytes)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesGroupCommitTime: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_group_commit_stall_seconds"), + "(Databases.GroupCommitTime)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesLogBytesFlushed: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_flushed_bytes"), + "(Databases.LogBytesFlushed)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesLogCacheHits: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_cache_hits"), + "(Databases.LogCacheHitRatio)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesLogCacheLookups: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_cache_lookups"), + "(Databases.LogCacheHitRatio_Base)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesLogCacheReads: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_cache_reads"), + "(Databases.LogCacheReads)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesLogFilesSizeKB: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_files_size_bytes"), + "(Databases.LogFilesSizeKB)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesLogFilesUsedSizeKB: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_files_used_size_bytes"), + "(Databases.LogFilesUsedSizeKB)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesLogFlushes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_flushes"), + "(Databases.LogFlushes)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesLogFlushWaits: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_flush_waits"), + "(Databases.LogFlushWaits)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesLogFlushWaitTime: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_flush_wait_seconds"), + "(Databases.LogFlushWaitTime)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesLogFlushWriteTimems: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_flush_write_seconds"), + "(Databases.LogFlushWriteTimems)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesLogGrowths: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_growths"), + "(Databases.LogGrowths)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesLogPoolCacheMisses: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_cache_misses"), + "(Databases.LogPoolCacheMisses)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesLogPoolDiskReads: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_disk_reads"), + "(Databases.LogPoolDiskReads)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesLogPoolHashDeletes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_hash_deletes"), + "(Databases.LogPoolHashDeletes)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesLogPoolHashInserts: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_hash_inserts"), + "(Databases.LogPoolHashInserts)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesLogPoolInvalidHashEntry: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_invalid_hash_entries"), + "(Databases.LogPoolInvalidHashEntry)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesLogPoolLogScanPushes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_log_scan_pushes"), + "(Databases.LogPoolLogScanPushes)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesLogPoolLogWriterPushes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_log_writer_pushes"), + "(Databases.LogPoolLogWriterPushes)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesLogPoolPushEmptyFreePool: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_empty_free_pool_pushes"), + "(Databases.LogPoolPushEmptyFreePool)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesLogPoolPushLowMemory: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_low_memory_pushes"), + "(Databases.LogPoolPushLowMemory)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesLogPoolPushNoFreeBuffer: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_no_free_buffer_pushes"), + "(Databases.LogPoolPushNoFreeBuffer)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesLogPoolReqBehindTrunc: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_req_behind_trunc"), + "(Databases.LogPoolReqBehindTrunc)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesLogPoolRequestsOldVLF: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_requests_old_vlf"), + "(Databases.LogPoolRequestsOldVLF)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesLogPoolRequests: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_requests"), + "(Databases.LogPoolRequests)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesLogPoolTotalActiveLogSize: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_total_active_log_bytes"), + "(Databases.LogPoolTotalActiveLogSize)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesLogPoolTotalSharedPoolSize: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_total_shared_pool_bytes"), + "(Databases.LogPoolTotalSharedPoolSize)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesLogShrinks: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_shrinks"), + "(Databases.LogShrinks)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesLogTruncations: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_truncations"), + "(Databases.LogTruncations)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesPercentLogUsed: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_log_used_percent"), + "(Databases.PercentLogUsed)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesReplPendingXacts: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_pending_repl_transactions"), + "(Databases.ReplPendingTransactions)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesReplTransRate: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_repl_transactions"), + "(Databases.ReplTranactions)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesShrinkDataMovementBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_shrink_data_movement_bytes"), + "(Databases.ShrinkDataMovementBytes)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesTrackedtransactions: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_tracked_transactions"), + "(Databases.Trackedtransactions)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesTransactions: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_transactions"), + "(Databases.Transactions)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesWriteTransactions: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_write_transactions"), + "(Databases.WriteTransactions)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesXTPControllerDLCLatencyPerFetch: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_xtp_controller_dlc_fetch_latency_seconds"), + "(Databases.XTPControllerDLCLatencyPerFetch)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesXTPControllerDLCPeakLatency: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_xtp_controller_dlc_peak_latency_seconds"), + "(Databases.XTPControllerDLCPeakLatency)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesXTPControllerLogProcessed: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_xtp_controller_log_processed_bytes"), + "(Databases.XTPControllerLogProcessed)", + []string{"mssql_instance", "database"}, + nil, + ), + DatabasesXTPMemoryUsedKB: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "databases_xtp_memory_used_bytes"), + "(Databases.XTPMemoryUsedKB)", + []string{"mssql_instance", "database"}, + nil, + ), + + // Win32_PerfRawData_{instance}_SQLServerGeneralStatistics + GenStatsActiveTempTables: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "genstats_active_temp_tables"), + "(GeneralStatistics.ActiveTempTables)", + []string{"mssql_instance"}, + nil, + ), + GenStatsConnectionReset: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "genstats_connection_resets"), + "(GeneralStatistics.ConnectionReset)", + []string{"mssql_instance"}, + nil, + ), + GenStatsEventNotificationsDelayedDrop: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "genstats_event_notifications_delayed_drop"), + "(GeneralStatistics.EventNotificationsDelayedDrop)", + []string{"mssql_instance"}, + nil, + ), + GenStatsHTTPAuthenticatedRequests: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "genstats_http_authenticated_requests"), + "(GeneralStatistics.HTTPAuthenticatedRequests)", + []string{"mssql_instance"}, + nil, + ), + GenStatsLogicalConnections: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "genstats_logical_connections"), + "(GeneralStatistics.LogicalConnections)", + []string{"mssql_instance"}, + nil, + ), + GenStatsLogins: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "genstats_logins"), + "(GeneralStatistics.Logins)", + []string{"mssql_instance"}, + nil, + ), + GenStatsLogouts: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "genstats_logouts"), + "(GeneralStatistics.Logouts)", + []string{"mssql_instance"}, + nil, + ), + GenStatsMarsDeadlocks: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "genstats_mars_deadlocks"), + "(GeneralStatistics.MarsDeadlocks)", + []string{"mssql_instance"}, + nil, + ), + GenStatsNonatomicyieldrate: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "genstats_non_atomic_yields"), + "(GeneralStatistics.Nonatomicyields)", + []string{"mssql_instance"}, + nil, + ), + GenStatsProcessesblocked: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "genstats_blocked_processes"), + "(GeneralStatistics.Processesblocked)", + []string{"mssql_instance"}, + nil, + ), + GenStatsSOAPEmptyRequests: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "genstats_soap_empty_requests"), + "(GeneralStatistics.SOAPEmptyRequests)", + []string{"mssql_instance"}, + nil, + ), + GenStatsSOAPMethodInvocations: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "genstats_soap_method_invocations"), + "(GeneralStatistics.SOAPMethodInvocations)", + []string{"mssql_instance"}, + nil, + ), + GenStatsSOAPSessionInitiateRequests: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "genstats_soap_session_initiate_requests"), + "(GeneralStatistics.SOAPSessionInitiateRequests)", + []string{"mssql_instance"}, + nil, + ), + GenStatsSOAPSessionTerminateRequests: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "genstats_soap_session_terminate_requests"), + "(GeneralStatistics.SOAPSessionTerminateRequests)", + []string{"mssql_instance"}, + nil, + ), + GenStatsSOAPSQLRequests: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "genstats_soapsql_requests"), + "(GeneralStatistics.SOAPSQLRequests)", + []string{"mssql_instance"}, + nil, + ), + GenStatsSOAPWSDLRequests: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "genstats_soapwsdl_requests"), + "(GeneralStatistics.SOAPWSDLRequests)", + []string{"mssql_instance"}, + nil, + ), + GenStatsSQLTraceIOProviderLockWaits: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "genstats_sql_trace_io_provider_lock_waits"), + "(GeneralStatistics.SQLTraceIOProviderLockWaits)", + []string{"mssql_instance"}, + nil, + ), + GenStatsTempdbrecoveryunitid: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "genstats_tempdb_recovery_unit_ids_generated"), + "(GeneralStatistics.Tempdbrecoveryunitid)", + []string{"mssql_instance"}, + nil, + ), + GenStatsTempdbrowsetid: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "genstats_tempdb_rowset_ids_generated"), + "(GeneralStatistics.Tempdbrowsetid)", + []string{"mssql_instance"}, + nil, + ), + GenStatsTempTablesCreationRate: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "genstats_temp_tables_creations"), + "(GeneralStatistics.TempTablesCreations)", + []string{"mssql_instance"}, + nil, + ), + GenStatsTempTablesForDestruction: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "genstats_temp_tables_awaiting_destruction"), + "(GeneralStatistics.TempTablesForDestruction)", + []string{"mssql_instance"}, + nil, + ), + GenStatsTraceEventNotificationQueue: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "genstats_trace_event_notification_queue_size"), + "(GeneralStatistics.TraceEventNotificationQueue)", + []string{"mssql_instance"}, + nil, + ), + GenStatsTransactions: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "genstats_transactions"), + "(GeneralStatistics.Transactions)", + []string{"mssql_instance"}, + nil, + ), + GenStatsUserConnections: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "genstats_user_connections"), + "(GeneralStatistics.UserConnections)", + []string{"mssql_instance"}, + nil, + ), + + // Win32_PerfRawData_{instance}_SQLServerLocks + LocksWaitTime: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "locks_wait_time_seconds"), + "(Locks.AverageWaitTimems Total time in seconds which locks have been holding resources)", + []string{"mssql_instance", "resource"}, + nil, + ), + LocksCount: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "locks_count"), + "(Locks.AverageWaitTimems_Base count of how often requests have run into locks)", + []string{"mssql_instance", "resource"}, + nil, + ), + LocksLockRequests: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "locks_lock_requests"), + "(Locks.LockRequests)", + []string{"mssql_instance", "resource"}, + nil, + ), + LocksLockTimeouts: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "locks_lock_timeouts"), + "(Locks.LockTimeouts)", + []string{"mssql_instance", "resource"}, + nil, + ), + LocksLockTimeoutstimeout0: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "locks_lock_timeouts_excluding_NOWAIT"), + "(Locks.LockTimeoutstimeout0)", + []string{"mssql_instance", "resource"}, + nil, + ), + LocksLockWaits: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "locks_lock_waits"), + "(Locks.LockWaits)", + []string{"mssql_instance", "resource"}, + nil, + ), + LocksLockWaitTimems: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "locks_lock_wait_seconds"), + "(Locks.LockWaitTimems)", + []string{"mssql_instance", "resource"}, + nil, + ), + LocksNumberofDeadlocks: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "locks_deadlocks"), + "(Locks.NumberofDeadlocks)", + []string{"mssql_instance", "resource"}, + nil, + ), + + // Win32_PerfRawData_{instance}_SQLServerMemoryManager + MemMgrConnectionMemoryKB: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "memmgr_connection_memory_bytes"), + "(MemoryManager.ConnectionMemoryKB)", + []string{"mssql_instance"}, + nil, + ), + MemMgrDatabaseCacheMemoryKB: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "memmgr_database_cache_memory_bytes"), + "(MemoryManager.DatabaseCacheMemoryKB)", + []string{"mssql_instance"}, + nil, + ), + MemMgrExternalbenefitofmemory: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "memmgr_external_benefit_of_memory"), + "(MemoryManager.Externalbenefitofmemory)", + []string{"mssql_instance"}, + nil, + ), + MemMgrFreeMemoryKB: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "memmgr_free_memory_bytes"), + "(MemoryManager.FreeMemoryKB)", + []string{"mssql_instance"}, + nil, + ), + MemMgrGrantedWorkspaceMemoryKB: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "memmgr_granted_workspace_memory_bytes"), + "(MemoryManager.GrantedWorkspaceMemoryKB)", + []string{"mssql_instance"}, + nil, + ), + MemMgrLockBlocks: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "memmgr_lock_blocks"), + "(MemoryManager.LockBlocks)", + []string{"mssql_instance"}, + nil, + ), + MemMgrLockBlocksAllocated: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "memmgr_allocated_lock_blocks"), + "(MemoryManager.LockBlocksAllocated)", + []string{"mssql_instance"}, + nil, + ), + MemMgrLockMemoryKB: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "memmgr_lock_memory_bytes"), + "(MemoryManager.LockMemoryKB)", + []string{"mssql_instance"}, + nil, + ), + MemMgrLockOwnerBlocks: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "memmgr_lock_owner_blocks"), + "(MemoryManager.LockOwnerBlocks)", + []string{"mssql_instance"}, + nil, + ), + MemMgrLockOwnerBlocksAllocated: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "memmgr_allocated_lock_owner_blocks"), + "(MemoryManager.LockOwnerBlocksAllocated)", + []string{"mssql_instance"}, + nil, + ), + MemMgrLogPoolMemoryKB: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "memmgr_log_pool_memory_bytes"), + "(MemoryManager.LogPoolMemoryKB)", + []string{"mssql_instance"}, + nil, + ), + MemMgrMaximumWorkspaceMemoryKB: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "memmgr_maximum_workspace_memory_bytes"), + "(MemoryManager.MaximumWorkspaceMemoryKB)", + []string{"mssql_instance"}, + nil, + ), + MemMgrMemoryGrantsOutstanding: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "memmgr_outstanding_memory_grants"), + "(MemoryManager.MemoryGrantsOutstanding)", + []string{"mssql_instance"}, + nil, + ), + MemMgrMemoryGrantsPending: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "memmgr_pending_memory_grants"), + "(MemoryManager.MemoryGrantsPending)", + []string{"mssql_instance"}, + nil, + ), + MemMgrOptimizerMemoryKB: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "memmgr_optimizer_memory_bytes"), + "(MemoryManager.OptimizerMemoryKB)", + []string{"mssql_instance"}, + nil, + ), + MemMgrReservedServerMemoryKB: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "memmgr_reserved_server_memory_bytes"), + "(MemoryManager.ReservedServerMemoryKB)", + []string{"mssql_instance"}, + nil, + ), + MemMgrSQLCacheMemoryKB: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "memmgr_sql_cache_memory_bytes"), + "(MemoryManager.SQLCacheMemoryKB)", + []string{"mssql_instance"}, + nil, + ), + MemMgrStolenServerMemoryKB: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "memmgr_stolen_server_memory_bytes"), + "(MemoryManager.StolenServerMemoryKB)", + []string{"mssql_instance"}, + nil, + ), + MemMgrTargetServerMemoryKB: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "memmgr_target_server_memory_bytes"), + "(MemoryManager.TargetServerMemoryKB)", + []string{"mssql_instance"}, + nil, + ), + MemMgrTotalServerMemoryKB: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "memmgr_total_server_memory_bytes"), + "(MemoryManager.TotalServerMemoryKB)", + []string{"mssql_instance"}, + nil, + ), + + // Win32_PerfRawData_{instance}_SQLServerSQLStatistics + SQLStatsAutoParamAttempts: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "sqlstats_auto_parameterization_attempts"), + "(SQLStatistics.AutoParamAttempts)", + []string{"mssql_instance"}, + nil, + ), + SQLStatsBatchRequests: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "sqlstats_batch_requests"), + "(SQLStatistics.BatchRequests)", + []string{"mssql_instance"}, + nil, + ), + SQLStatsFailedAutoParams: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "sqlstats_failed_auto_parameterization_attempts"), + "(SQLStatistics.FailedAutoParams)", + []string{"mssql_instance"}, + nil, + ), + SQLStatsForcedParameterizations: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "sqlstats_forced_parameterizations"), + "(SQLStatistics.ForcedParameterizations)", + []string{"mssql_instance"}, + nil, + ), + SQLStatsGuidedplanexecutions: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "sqlstats_guided_plan_executions"), + "(SQLStatistics.Guidedplanexecutions)", + []string{"mssql_instance"}, + nil, + ), + SQLStatsMisguidedplanexecutions: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "sqlstats_misguided_plan_executions"), + "(SQLStatistics.Misguidedplanexecutions)", + []string{"mssql_instance"}, + nil, + ), + SQLStatsSafeAutoParams: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "sqlstats_safe_auto_parameterization_attempts"), + "(SQLStatistics.SafeAutoParams)", + []string{"mssql_instance"}, + nil, + ), + SQLStatsSQLAttentionrate: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "sqlstats_sql_attentions"), + "(SQLStatistics.SQLAttentions)", + []string{"mssql_instance"}, + nil, + ), + SQLStatsSQLCompilations: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "sqlstats_sql_compilations"), + "(SQLStatistics.SQLCompilations)", + []string{"mssql_instance"}, + nil, + ), + SQLStatsSQLReCompilations: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "sqlstats_sql_recompilations"), + "(SQLStatistics.SQLReCompilations)", + []string{"mssql_instance"}, + nil, + ), + SQLStatsUnsafeAutoParams: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "sqlstats_unsafe_auto_parameterization_attempts"), + "(SQLStatistics.UnsafeAutoParams)", + []string{"mssql_instance"}, + nil, + ), + + // Win32_PerfRawData_{instance}_SQLServerSQLErrors + SQLErrorsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "sql_errors_total"), + "(SQLErrors.Total)", + []string{"mssql_instance", "resource"}, + nil, + ), + + // Win32_PerfRawData_{instance}_SQLServerTransactions + TransactionsTempDbFreeSpaceBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "transactions_tempdb_free_space_bytes"), + "(Transactions.FreeSpaceInTempDbKB)", + []string{"mssql_instance"}, + nil, + ), + TransactionsLongestTransactionRunningSeconds: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "transactions_longest_transaction_running_seconds"), + "(Transactions.LongestTransactionRunningTime)", + []string{"mssql_instance"}, + nil, + ), + TransactionsNonSnapshotVersionActiveTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "transactions_nonsnapshot_version_active_total"), + "(Transactions.NonSnapshotVersionTransactions)", + []string{"mssql_instance"}, + nil, + ), + TransactionsSnapshotActiveTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "transactions_snapshot_active_total"), + "(Transactions.SnapshotTransactions)", + []string{"mssql_instance"}, + nil, + ), + TransactionsActive: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "transactions_active"), + "(Transactions.Transactions)", + []string{"mssql_instance"}, + nil, + ), + TransactionsUpdateConflictsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "transactions_update_conflicts_total"), + "(Transactions.UpdateConflictRatio)", + []string{"mssql_instance"}, + nil, + ), + TransactionsUpdateSnapshotActiveTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "transactions_update_snapshot_active_total"), + "(Transactions.UpdateSnapshotTransactions)", + []string{"mssql_instance"}, + nil, + ), + TransactionsVersionCleanupRateBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "transactions_version_cleanup_rate_bytes"), + "(Transactions.VersionCleanupRateKBs)", + []string{"mssql_instance"}, + nil, + ), + TransactionsVersionGenerationRateBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "transactions_version_generation_rate_bytes"), + "(Transactions.VersionGenerationRateKBs)", + []string{"mssql_instance"}, + nil, + ), + TransactionsVersionStoreSizeBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "transactions_version_store_size_bytes"), + "(Transactions.VersionStoreSizeKB)", + []string{"mssql_instance"}, + nil, + ), + TransactionsVersionStoreUnits: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "transactions_version_store_units"), + "(Transactions.VersionStoreUnitCount)", + []string{"mssql_instance"}, + nil, + ), + TransactionsVersionStoreCreationUnits: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "transactions_version_store_creation_units"), + "(Transactions.VersionStoreUnitCreation)", + []string{"mssql_instance"}, + nil, + ), + TransactionsVersionStoreTruncationUnits: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "transactions_version_store_truncation_units"), + "(Transactions.VersionStoreUnitTruncation)", + []string{"mssql_instance"}, + nil, + ), + + mssqlInstances: mssqlInstances, + } + + mssqlCollector.mssqlCollectors = mssqlCollector.getMSSQLCollectors() + mssqlCollector.enabled = expandEnabledChildCollectors(c.MSSQLEnabledCollectors) + + if c.MSSQLPrintCollectors { + fmt.Printf("Available SQLServer Classes:\n") + for name := range mssqlCollector.mssqlCollectors { + fmt.Printf(" - %s\n", name) + } + os.Exit(0) + } + + return &mssqlCollector, nil +} + +type mssqlCollectorFunc func(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) + +func (c *MSSQLCollector) execute(ctx *ScrapeContext, name string, fn mssqlCollectorFunc, ch chan<- prometheus.Metric, sqlInstance string, wg *sync.WaitGroup) { + // Reset failure counter on each scrape + c.mssqlChildCollectorFailure = 0 + defer wg.Done() + + begin := time.Now() + _, err := fn(ctx, ch, sqlInstance) + duration := time.Since(begin) + var success float64 + + if err != nil { + log.Errorf("mssql class collector %s failed after %fs: %s", name, duration.Seconds(), err) + success = 0 + c.mssqlChildCollectorFailure++ + } else { + log.Debugf("mssql class collector %s succeeded after %fs.", name, duration.Seconds()) + success = 1 + } + ch <- prometheus.MustNewConstMetric( + c.mssqlScrapeDurationDesc, + prometheus.GaugeValue, + duration.Seconds(), + name, sqlInstance, + ) + ch <- prometheus.MustNewConstMetric( + c.mssqlScrapeSuccessDesc, + prometheus.GaugeValue, + success, + name, sqlInstance, + ) +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *MSSQLCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + wg := sync.WaitGroup{} + + for sqlInstance := range c.mssqlInstances { + for _, name := range c.enabled { + function := c.mssqlCollectors[name] + + wg.Add(1) + go c.execute(ctx, name, function, ch, sqlInstance, &wg) + } + } + wg.Wait() + + // this shoud return an error if any? some? children errord. + if c.mssqlChildCollectorFailure > 0 { + return errors.New("at least one child collector failed") + } + return nil +} + +// Win32_PerfRawData_MSSQLSERVER_SQLServerAccessMethods docs: +// - https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-access-methods-object +type mssqlAccessMethods struct { + AUcleanupbatchesPersec float64 `perflib:"AU cleanup batches/sec"` + AUcleanupsPersec float64 `perflib:"AU cleanups/sec"` + ByreferenceLobCreateCount float64 `perflib:"By-reference Lob Create Count"` + ByreferenceLobUseCount float64 `perflib:"By-reference Lob Use Count"` + CountLobReadahead float64 `perflib:"Count Lob Readahead"` + CountPullInRow float64 `perflib:"Count Pull In Row"` + CountPushOffRow float64 `perflib:"Count Push Off Row"` + DeferreddroppedAUs float64 `perflib:"Deferred dropped AUs"` + DeferredDroppedrowsets float64 `perflib:"Deferred Dropped rowsets"` + DroppedrowsetcleanupsPersec float64 `perflib:"Dropped rowset cleanups/sec"` + DroppedrowsetsskippedPersec float64 `perflib:"Dropped rowsets skipped/sec"` + ExtentDeallocationsPersec float64 `perflib:"Extent Deallocations/sec"` + ExtentsAllocatedPersec float64 `perflib:"Extents Allocated/sec"` + FailedAUcleanupbatchesPersec float64 `perflib:"Failed AU cleanup batches/sec"` + Failedleafpagecookie float64 `perflib:"Failed leaf page cookie"` + Failedtreepagecookie float64 `perflib:"Failed tree page cookie"` + ForwardedRecordsPersec float64 `perflib:"Forwarded Records/sec"` + FreeSpacePageFetchesPersec float64 `perflib:"FreeSpace Page Fetches/sec"` + FreeSpaceScansPersec float64 `perflib:"FreeSpace Scans/sec"` + FullScansPersec float64 `perflib:"Full Scans/sec"` + IndexSearchesPersec float64 `perflib:"Index Searches/sec"` + InSysXactwaitsPersec float64 `perflib:"InSysXact waits/sec"` + LobHandleCreateCount float64 `perflib:"LobHandle Create Count"` + LobHandleDestroyCount float64 `perflib:"LobHandle Destroy Count"` + LobSSProviderCreateCount float64 `perflib:"LobSS Provider Create Count"` + LobSSProviderDestroyCount float64 `perflib:"LobSS Provider Destroy Count"` + LobSSProviderTruncationCount float64 `perflib:"LobSS Provider Truncation Count"` + MixedpageallocationsPersec float64 `perflib:"Mixed page allocations/sec"` + PagecompressionattemptsPersec float64 `perflib:"Page compression attempts/sec"` + PageDeallocationsPersec float64 `perflib:"Page Deallocations/sec"` + PagesAllocatedPersec float64 `perflib:"Pages Allocated/sec"` + PagescompressedPersec float64 `perflib:"Pages compressed/sec"` + PageSplitsPersec float64 `perflib:"Page Splits/sec"` + ProbeScansPersec float64 `perflib:"Probe Scans/sec"` + RangeScansPersec float64 `perflib:"Range Scans/sec"` + ScanPointRevalidationsPersec float64 `perflib:"Scan Point Revalidations/sec"` + SkippedGhostedRecordsPersec float64 `perflib:"Skipped Ghosted Records/sec"` + TableLockEscalationsPersec float64 `perflib:"Table Lock Escalations/sec"` + Usedleafpagecookie float64 `perflib:"Used leaf page cookie"` + Usedtreepagecookie float64 `perflib:"Used tree page cookie"` + WorkfilesCreatedPersec float64 `perflib:"Workfiles Created/sec"` + WorktablesCreatedPersec float64 `perflib:"Worktables Created/sec"` + WorktablesFromCacheRatio float64 `perflib:"Worktables From Cache Ratio"` + WorktablesFromCacheRatio_Base float64 `perflib:"Worktables From Cache Base_Base"` +} + +func (c *MSSQLCollector) collectAccessMethods(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { + var dst []mssqlAccessMethods + log.Debugf("mssql_accessmethods collector iterating sql instance %s.", sqlInstance) + + if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "accessmethods")], &dst); err != nil { + return nil, err + } + + for _, v := range dst { + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsAUcleanupbatches, + prometheus.CounterValue, + v.AUcleanupbatchesPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsAUcleanups, + prometheus.CounterValue, + v.AUcleanupsPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsByreferenceLobCreateCount, + prometheus.CounterValue, + v.ByreferenceLobCreateCount, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsByreferenceLobUseCount, + prometheus.CounterValue, + v.ByreferenceLobUseCount, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsCountLobReadahead, + prometheus.CounterValue, + v.CountLobReadahead, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsCountPullInRow, + prometheus.CounterValue, + v.CountPullInRow, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsCountPushOffRow, + prometheus.CounterValue, + v.CountPushOffRow, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsDeferreddroppedAUs, + prometheus.GaugeValue, + v.DeferreddroppedAUs, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsDeferredDroppedrowsets, + prometheus.GaugeValue, + v.DeferredDroppedrowsets, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsDroppedrowsetcleanups, + prometheus.CounterValue, + v.DroppedrowsetcleanupsPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsDroppedrowsetsskipped, + prometheus.CounterValue, + v.DroppedrowsetsskippedPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsExtentDeallocations, + prometheus.CounterValue, + v.ExtentDeallocationsPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsExtentsAllocated, + prometheus.CounterValue, + v.ExtentsAllocatedPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsFailedAUcleanupbatches, + prometheus.CounterValue, + v.FailedAUcleanupbatchesPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsFailedleafpagecookie, + prometheus.CounterValue, + v.Failedleafpagecookie, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsFailedtreepagecookie, + prometheus.CounterValue, + v.Failedtreepagecookie, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsForwardedRecords, + prometheus.CounterValue, + v.ForwardedRecordsPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsFreeSpacePageFetches, + prometheus.CounterValue, + v.FreeSpacePageFetchesPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsFreeSpaceScans, + prometheus.CounterValue, + v.FreeSpaceScansPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsFullScans, + prometheus.CounterValue, + v.FullScansPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsIndexSearches, + prometheus.CounterValue, + v.IndexSearchesPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsInSysXactwaits, + prometheus.CounterValue, + v.InSysXactwaitsPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsLobHandleCreateCount, + prometheus.CounterValue, + v.LobHandleCreateCount, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsLobHandleDestroyCount, + prometheus.CounterValue, + v.LobHandleDestroyCount, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsLobSSProviderCreateCount, + prometheus.CounterValue, + v.LobSSProviderCreateCount, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsLobSSProviderDestroyCount, + prometheus.CounterValue, + v.LobSSProviderDestroyCount, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsLobSSProviderTruncationCount, + prometheus.CounterValue, + v.LobSSProviderTruncationCount, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsMixedpageallocations, + prometheus.CounterValue, + v.MixedpageallocationsPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsPagecompressionattempts, + prometheus.CounterValue, + v.PagecompressionattemptsPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsPageDeallocations, + prometheus.CounterValue, + v.PageDeallocationsPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsPagesAllocated, + prometheus.CounterValue, + v.PagesAllocatedPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsPagescompressed, + prometheus.CounterValue, + v.PagescompressedPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsPageSplits, + prometheus.CounterValue, + v.PageSplitsPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsProbeScans, + prometheus.CounterValue, + v.ProbeScansPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsRangeScans, + prometheus.CounterValue, + v.RangeScansPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsScanPointRevalidations, + prometheus.CounterValue, + v.ScanPointRevalidationsPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsSkippedGhostedRecords, + prometheus.CounterValue, + v.SkippedGhostedRecordsPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsTableLockEscalations, + prometheus.CounterValue, + v.TableLockEscalationsPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsUsedleafpagecookie, + prometheus.CounterValue, + v.Usedleafpagecookie, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsUsedtreepagecookie, + prometheus.CounterValue, + v.Usedtreepagecookie, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsWorkfilesCreated, + prometheus.CounterValue, + v.WorkfilesCreatedPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsWorktablesCreated, + prometheus.CounterValue, + v.WorktablesCreatedPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsWorktablesFromCacheHits, + prometheus.CounterValue, + v.WorktablesFromCacheRatio, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.AccessMethodsWorktablesFromCacheLookups, + prometheus.CounterValue, + v.WorktablesFromCacheRatio_Base, + sqlInstance, + ) + } + return nil, nil +} + +// Win32_PerfRawData_MSSQLSERVER_SQLServerAvailabilityReplica docs: +// - https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-availability-replica +type mssqlAvailabilityReplica struct { + Name string + BytesReceivedfromReplicaPersec float64 `perflib:"Bytes Received from Replica/sec"` + BytesSenttoReplicaPersec float64 `perflib:"Bytes Sent to Replica/sec"` + BytesSenttoTransportPersec float64 `perflib:"Bytes Sent to Transport/sec"` + FlowControlPersec float64 `perflib:"Flow Control/sec"` + FlowControlTimemsPersec float64 `perflib:"Flow Control Time (ms/sec)"` + ReceivesfromReplicaPersec float64 `perflib:"Receives from Replica/sec"` + ResentMessagesPersec float64 `perflib:"Resent Messages/sec"` + SendstoReplicaPersec float64 `perflib:"Sends to Replica/sec"` + SendstoTransportPersec float64 `perflib:"Sends to Transport/sec"` +} + +func (c *MSSQLCollector) collectAvailabilityReplica(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { + var dst []mssqlAvailabilityReplica + log.Debugf("mssql_availreplica collector iterating sql instance %s.", sqlInstance) + + if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "availreplica")], &dst); err != nil { + return nil, err + } + + for _, v := range dst { + if strings.ToLower(v.Name) == "_total" { + continue + } + replicaName := v.Name + + ch <- prometheus.MustNewConstMetric( + c.AvailReplicaBytesReceivedfromReplica, + prometheus.CounterValue, + v.BytesReceivedfromReplicaPersec, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.AvailReplicaBytesSenttoReplica, + prometheus.CounterValue, + v.BytesSenttoReplicaPersec, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.AvailReplicaBytesSenttoTransport, + prometheus.CounterValue, + v.BytesSenttoTransportPersec, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.AvailReplicaFlowControl, + prometheus.CounterValue, + v.FlowControlPersec, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.AvailReplicaFlowControlTimems, + prometheus.CounterValue, + v.FlowControlTimemsPersec/1000.0, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.AvailReplicaReceivesfromReplica, + prometheus.CounterValue, + v.ReceivesfromReplicaPersec, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.AvailReplicaResentMessages, + prometheus.CounterValue, + v.ResentMessagesPersec, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.AvailReplicaSendstoReplica, + prometheus.CounterValue, + v.SendstoReplicaPersec, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.AvailReplicaSendstoTransport, + prometheus.CounterValue, + v.SendstoTransportPersec, + sqlInstance, replicaName, + ) + } + return nil, nil +} + +// Win32_PerfRawData_MSSQLSERVER_SQLServerBufferManager docs: +// - https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-buffer-manager-object +type mssqlBufferManager struct { + BackgroundwriterpagesPersec float64 `perflib:"Background writer pages/sec"` + Buffercachehitratio float64 `perflib:"Buffer cache hit ratio"` + Buffercachehitratio_Base float64 `perflib:"Buffer cache hit ratio base_Base"` + CheckpointpagesPersec float64 `perflib:"Checkpoint pages/sec"` + Databasepages float64 `perflib:"Database pages"` + Extensionallocatedpages float64 `perflib:"Extension allocated pages"` + Extensionfreepages float64 `perflib:"Extension free pages"` + Extensioninuseaspercentage float64 `perflib:"Extension in use as percentage"` + ExtensionoutstandingIOcounter float64 `perflib:"Extension outstanding IO counter"` + ExtensionpageevictionsPersec float64 `perflib:"Extension page evictions/sec"` + ExtensionpagereadsPersec float64 `perflib:"Extension page reads/sec"` + Extensionpageunreferencedtime float64 `perflib:"Extension page unreferenced time"` + ExtensionpagewritesPersec float64 `perflib:"Extension page writes/sec"` + FreeliststallsPersec float64 `perflib:"Free list stalls/sec"` + IntegralControllerSlope float64 `perflib:"Integral Controller Slope"` + LazywritesPersec float64 `perflib:"Lazy writes/sec"` + Pagelifeexpectancy float64 `perflib:"Page life expectancy"` + PagelookupsPersec float64 `perflib:"Page lookups/sec"` + PagereadsPersec float64 `perflib:"Page reads/sec"` + PagewritesPersec float64 `perflib:"Page writes/sec"` + ReadaheadpagesPersec float64 `perflib:"Readahead pages/sec"` + ReadaheadtimePersec float64 `perflib:"Readahead time/sec"` + Targetpages float64 `perflib:"Target pages"` +} + +func (c *MSSQLCollector) collectBufferManager(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { + var dst []mssqlBufferManager + log.Debugf("mssql_bufman collector iterating sql instance %s.", sqlInstance) + + if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "bufman")], &dst); err != nil { + return nil, err + } + + for _, v := range dst { + ch <- prometheus.MustNewConstMetric( + c.BufManBackgroundwriterpages, + prometheus.CounterValue, + v.BackgroundwriterpagesPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.BufManBuffercachehits, + prometheus.GaugeValue, + v.Buffercachehitratio, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.BufManBuffercachelookups, + prometheus.GaugeValue, + v.Buffercachehitratio_Base, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.BufManCheckpointpages, + prometheus.CounterValue, + v.CheckpointpagesPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.BufManDatabasepages, + prometheus.GaugeValue, + v.Databasepages, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.BufManExtensionallocatedpages, + prometheus.GaugeValue, + v.Extensionallocatedpages, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.BufManExtensionfreepages, + prometheus.GaugeValue, + v.Extensionfreepages, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.BufManExtensioninuseaspercentage, + prometheus.GaugeValue, + v.Extensioninuseaspercentage, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.BufManExtensionoutstandingIOcounter, + prometheus.GaugeValue, + v.ExtensionoutstandingIOcounter, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.BufManExtensionpageevictions, + prometheus.CounterValue, + v.ExtensionpageevictionsPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.BufManExtensionpagereads, + prometheus.CounterValue, + v.ExtensionpagereadsPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.BufManExtensionpageunreferencedtime, + prometheus.GaugeValue, + v.Extensionpageunreferencedtime, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.BufManExtensionpagewrites, + prometheus.CounterValue, + v.ExtensionpagewritesPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.BufManFreeliststalls, + prometheus.CounterValue, + v.FreeliststallsPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.BufManIntegralControllerSlope, + prometheus.GaugeValue, + v.IntegralControllerSlope, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.BufManLazywrites, + prometheus.CounterValue, + v.LazywritesPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.BufManPagelifeexpectancy, + prometheus.GaugeValue, + v.Pagelifeexpectancy, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.BufManPagelookups, + prometheus.CounterValue, + v.PagelookupsPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.BufManPagereads, + prometheus.CounterValue, + v.PagereadsPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.BufManPagewrites, + prometheus.CounterValue, + v.PagewritesPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.BufManReadaheadpages, + prometheus.CounterValue, + v.ReadaheadpagesPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.BufManReadaheadtime, + prometheus.CounterValue, + v.ReadaheadtimePersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.BufManTargetpages, + prometheus.GaugeValue, + v.Targetpages, + sqlInstance, + ) + } + + return nil, nil +} + +// Win32_PerfRawData_MSSQLSERVER_SQLServerDatabaseReplica docs: +// - https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-database-replica +type mssqlDatabaseReplica struct { + Name string + DatabaseFlowControlDelay float64 `perflib:"Database Flow Control Delay"` + DatabaseFlowControlsPersec float64 `perflib:"Database Flow Controls/sec"` + FileBytesReceivedPersec float64 `perflib:"File Bytes Received/sec"` + GroupCommitsPerSec float64 `perflib:"Group Commits/Sec"` + GroupCommitTime float64 `perflib:"Group Commit Time"` + LogApplyPendingQueue float64 `perflib:"Log Apply Pending Queue"` + LogApplyReadyQueue float64 `perflib:"Log Apply Ready Queue"` + LogBytesCompressedPersec float64 `perflib:"Log Bytes Compressed/sec"` + LogBytesDecompressedPersec float64 `perflib:"Log Bytes Decompressed/sec"` + LogBytesReceivedPersec float64 `perflib:"Log Bytes Received/sec"` + LogCompressionCachehitsPersec float64 `perflib:"Log Compression Cache hits/sec"` + LogCompressionCachemissesPersec float64 `perflib:"Log Compression Cache misses/sec"` + LogCompressionsPersec float64 `perflib:"Log Compressions/sec"` + LogDecompressionsPersec float64 `perflib:"Log Decompressions/sec"` + Logremainingforundo float64 `perflib:"Log remaining for undo"` + LogSendQueue float64 `perflib:"Log Send Queue"` + MirroredWriteTransactionsPersec float64 `perflib:"Mirrored Write Transactions/sec"` + RecoveryQueue float64 `perflib:"Recovery Queue"` + RedoblockedPersec float64 `perflib:"Redo blocked/sec"` + RedoBytesRemaining float64 `perflib:"Redo Bytes Remaining"` + RedoneBytesPersec float64 `perflib:"Redone Bytes/sec"` + RedonesPersec float64 `perflib:"Redones/sec"` + TotalLogrequiringundo float64 `perflib:"Total Log requiring undo"` + TransactionDelay float64 `perflib:"Transaction Delay"` +} + +func (c *MSSQLCollector) collectDatabaseReplica(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { + var dst []mssqlDatabaseReplica + log.Debugf("mssql_dbreplica collector iterating sql instance %s.", sqlInstance) + + if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "dbreplica")], &dst); err != nil { + return nil, err + } + + for _, v := range dst { + if strings.ToLower(v.Name) == "_total" { + continue + } + replicaName := v.Name + + ch <- prometheus.MustNewConstMetric( + c.DBReplicaDatabaseFlowControlDelay, + prometheus.GaugeValue, + v.DatabaseFlowControlDelay, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DBReplicaDatabaseFlowControls, + prometheus.CounterValue, + v.DatabaseFlowControlsPersec, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DBReplicaFileBytesReceived, + prometheus.CounterValue, + v.FileBytesReceivedPersec, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DBReplicaGroupCommits, + prometheus.CounterValue, + v.GroupCommitsPerSec, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DBReplicaGroupCommitTime, + prometheus.GaugeValue, + v.GroupCommitTime, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DBReplicaLogApplyPendingQueue, + prometheus.GaugeValue, + v.LogApplyPendingQueue, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DBReplicaLogApplyReadyQueue, + prometheus.GaugeValue, + v.LogApplyReadyQueue, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DBReplicaLogBytesCompressed, + prometheus.CounterValue, + v.LogBytesCompressedPersec, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DBReplicaLogBytesDecompressed, + prometheus.CounterValue, + v.LogBytesDecompressedPersec, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DBReplicaLogBytesReceived, + prometheus.CounterValue, + v.LogBytesReceivedPersec, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DBReplicaLogCompressionCachehits, + prometheus.CounterValue, + v.LogCompressionCachehitsPersec, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DBReplicaLogCompressionCachemisses, + prometheus.CounterValue, + v.LogCompressionCachemissesPersec, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DBReplicaLogCompressions, + prometheus.CounterValue, + v.LogCompressionsPersec, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DBReplicaLogDecompressions, + prometheus.CounterValue, + v.LogDecompressionsPersec, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DBReplicaLogremainingforundo, + prometheus.GaugeValue, + v.Logremainingforundo, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DBReplicaLogSendQueue, + prometheus.GaugeValue, + v.LogSendQueue, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DBReplicaMirroredWriteTransactions, + prometheus.CounterValue, + v.MirroredWriteTransactionsPersec, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DBReplicaRecoveryQueue, + prometheus.GaugeValue, + v.RecoveryQueue, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DBReplicaRedoblocked, + prometheus.CounterValue, + v.RedoblockedPersec, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DBReplicaRedoBytesRemaining, + prometheus.GaugeValue, + v.RedoBytesRemaining, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DBReplicaRedoneBytes, + prometheus.CounterValue, + v.RedoneBytesPersec, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DBReplicaRedones, + prometheus.CounterValue, + v.RedonesPersec, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DBReplicaTotalLogrequiringundo, + prometheus.GaugeValue, + v.TotalLogrequiringundo, + sqlInstance, replicaName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DBReplicaTransactionDelay, + prometheus.GaugeValue, + v.TransactionDelay/1000.0, + sqlInstance, replicaName, + ) + } + return nil, nil +} + +// Win32_PerfRawData_MSSQLSERVER_SQLServerDatabases docs: +// - https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-databases-object?view=sql-server-2017 +type mssqlDatabases struct { + Name string + Activeparallelredothreads float64 `perflib:"Active parallel redo threads"` + ActiveTransactions float64 `perflib:"Active Transactions"` + BackupPerRestoreThroughputPersec float64 `perflib:"Backup/Restore Throughput/sec"` + BulkCopyRowsPersec float64 `perflib:"Bulk Copy Rows/sec"` + BulkCopyThroughputPersec float64 `perflib:"Bulk Copy Throughput/sec"` + Committableentries float64 `perflib:"Commit table entries"` + DataFilesSizeKB float64 `perflib:"Data File(s) Size (KB)"` + DBCCLogicalScanBytesPersec float64 `perflib:"DBCC Logical Scan Bytes/sec"` + GroupCommitTimePersec float64 `perflib:"Group Commit Time/sec"` + LogBytesFlushedPersec float64 `perflib:"Log Bytes Flushed/sec"` + LogCacheHitRatio float64 `perflib:"Log Cache Hit Ratio"` + LogCacheHitRatio_Base float64 `perflib:"Log Cache Hit Ratio Base_Base"` + LogCacheReadsPersec float64 `perflib:"Log Cache Reads/sec"` + LogFilesSizeKB float64 `perflib:"Log File(s) Size (KB)"` + LogFilesUsedSizeKB float64 `perflib:"Log File(s) Used Size (KB)"` + LogFlushesPersec float64 `perflib:"Log Flushes/sec"` + LogFlushWaitsPersec float64 `perflib:"Log Flush Waits/sec"` + LogFlushWaitTime float64 `perflib:"Log Flush Wait Time"` + LogFlushWriteTimems float64 `perflib:"Log Flush Write Time (ms)"` + LogGrowths float64 `perflib:"Log Growths"` + LogPoolCacheMissesPersec float64 `perflib:"Log Pool Cache Misses/sec"` + LogPoolDiskReadsPersec float64 `perflib:"Log Pool Disk Reads/sec"` + LogPoolHashDeletesPersec float64 `perflib:"Log Pool Hash Deletes/sec"` + LogPoolHashInsertsPersec float64 `perflib:"Log Pool Hash Inserts/sec"` + LogPoolInvalidHashEntryPersec float64 `perflib:"Log Pool Invalid Hash Entry/sec"` + LogPoolLogScanPushesPersec float64 `perflib:"Log Pool Log Scan Pushes/sec"` + LogPoolLogWriterPushesPersec float64 `perflib:"Log Pool LogWriter Pushes/sec"` + LogPoolPushEmptyFreePoolPersec float64 `perflib:"Log Pool Push Empty FreePool/sec"` + LogPoolPushLowMemoryPersec float64 `perflib:"Log Pool Push Low Memory/sec"` + LogPoolPushNoFreeBufferPersec float64 `perflib:"Log Pool Push No Free Buffer/sec"` + LogPoolReqBehindTruncPersec float64 `perflib:"Log Pool Req. Behind Trunc/sec"` + LogPoolRequestsOldVLFPersec float64 `perflib:"Log Pool Requests Old VLF/sec"` + LogPoolRequestsPersec float64 `perflib:"Log Pool Requests/sec"` + LogPoolTotalActiveLogSize float64 `perflib:"Log Pool Total Active Log Size"` + LogPoolTotalSharedPoolSize float64 `perflib:"Log Pool Total Shared Pool Size"` + LogShrinks float64 `perflib:"Log Shrinks"` + LogTruncations float64 `perflib:"Log Truncations"` + PercentLogUsed float64 `perflib:"Percent Log Used"` + ReplPendingXacts float64 `perflib:"Repl. Pending Xacts"` + ReplTransRate float64 `perflib:"Repl. Trans. Rate"` + ShrinkDataMovementBytesPersec float64 `perflib:"Shrink Data Movement Bytes/sec"` + TrackedtransactionsPersec float64 `perflib:"Tracked transactions/sec"` + TransactionsPersec float64 `perflib:"Transactions/sec"` + WriteTransactionsPersec float64 `perflib:"Write Transactions/sec"` + XTPControllerDLCLatencyPerFetch float64 `perflib:"XTP Controller DLC Latency/Fetch"` + XTPControllerDLCPeakLatency float64 `perflib:"XTP Controller DLC Peak Latency"` + XTPControllerLogProcessedPersec float64 `perflib:"XTP Controller Log Processed/sec"` + XTPMemoryUsedKB float64 `perflib:"XTP Memory Used (KB)"` +} + +func (c *MSSQLCollector) collectDatabases(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { + var dst []mssqlDatabases + log.Debugf("mssql_databases collector iterating sql instance %s.", sqlInstance) + + if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "databases")], &dst); err != nil { + return nil, err + } + + for _, v := range dst { + if strings.ToLower(v.Name) == "_total" { + continue + } + dbName := v.Name + + ch <- prometheus.MustNewConstMetric( + c.DatabasesActiveParallelredothreads, + prometheus.GaugeValue, + v.Activeparallelredothreads, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesActiveTransactions, + prometheus.GaugeValue, + v.ActiveTransactions, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesBackupPerRestoreThroughput, + prometheus.CounterValue, + v.BackupPerRestoreThroughputPersec, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesBulkCopyRows, + prometheus.CounterValue, + v.BulkCopyRowsPersec, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesBulkCopyThroughput, + prometheus.CounterValue, + v.BulkCopyThroughputPersec*1024, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesCommittableentries, + prometheus.GaugeValue, + v.Committableentries, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesDataFilesSizeKB, + prometheus.GaugeValue, + v.DataFilesSizeKB*1024, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesDBCCLogicalScanBytes, + prometheus.CounterValue, + v.DBCCLogicalScanBytesPersec, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesGroupCommitTime, + prometheus.CounterValue, + v.GroupCommitTimePersec/1000000.0, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesLogBytesFlushed, + prometheus.CounterValue, + v.LogBytesFlushedPersec, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesLogCacheHits, + prometheus.GaugeValue, + v.LogCacheHitRatio, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesLogCacheLookups, + prometheus.GaugeValue, + v.LogCacheHitRatio_Base, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesLogCacheReads, + prometheus.CounterValue, + v.LogCacheReadsPersec, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesLogFilesSizeKB, + prometheus.GaugeValue, + v.LogFilesSizeKB*1024, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesLogFilesUsedSizeKB, + prometheus.GaugeValue, + v.LogFilesUsedSizeKB*1024, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesLogFlushes, + prometheus.CounterValue, + v.LogFlushesPersec, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesLogFlushWaits, + prometheus.CounterValue, + v.LogFlushWaitsPersec, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesLogFlushWaitTime, + prometheus.GaugeValue, + v.LogFlushWaitTime/1000.0, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesLogFlushWriteTimems, + prometheus.GaugeValue, + v.LogFlushWriteTimems/1000.0, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesLogGrowths, + prometheus.GaugeValue, + v.LogGrowths, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesLogPoolCacheMisses, + prometheus.CounterValue, + v.LogPoolCacheMissesPersec, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesLogPoolDiskReads, + prometheus.CounterValue, + v.LogPoolDiskReadsPersec, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesLogPoolHashDeletes, + prometheus.CounterValue, + v.LogPoolHashDeletesPersec, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesLogPoolHashInserts, + prometheus.CounterValue, + v.LogPoolHashInsertsPersec, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesLogPoolInvalidHashEntry, + prometheus.CounterValue, + v.LogPoolInvalidHashEntryPersec, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesLogPoolLogScanPushes, + prometheus.CounterValue, + v.LogPoolLogScanPushesPersec, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesLogPoolLogWriterPushes, + prometheus.CounterValue, + v.LogPoolLogWriterPushesPersec, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesLogPoolPushEmptyFreePool, + prometheus.CounterValue, + v.LogPoolPushEmptyFreePoolPersec, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesLogPoolPushLowMemory, + prometheus.CounterValue, + v.LogPoolPushLowMemoryPersec, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesLogPoolPushNoFreeBuffer, + prometheus.CounterValue, + v.LogPoolPushNoFreeBufferPersec, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesLogPoolReqBehindTrunc, + prometheus.CounterValue, + v.LogPoolReqBehindTruncPersec, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesLogPoolRequestsOldVLF, + prometheus.CounterValue, + v.LogPoolRequestsOldVLFPersec, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesLogPoolRequests, + prometheus.CounterValue, + v.LogPoolRequestsPersec, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesLogPoolTotalActiveLogSize, + prometheus.GaugeValue, + v.LogPoolTotalActiveLogSize, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesLogPoolTotalSharedPoolSize, + prometheus.GaugeValue, + v.LogPoolTotalSharedPoolSize, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesLogShrinks, + prometheus.GaugeValue, + v.LogShrinks, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesLogTruncations, + prometheus.GaugeValue, + v.LogTruncations, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesPercentLogUsed, + prometheus.GaugeValue, + v.PercentLogUsed, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesReplPendingXacts, + prometheus.GaugeValue, + v.ReplPendingXacts, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesReplTransRate, + prometheus.CounterValue, + v.ReplTransRate, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesShrinkDataMovementBytes, + prometheus.CounterValue, + v.ShrinkDataMovementBytesPersec, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesTrackedtransactions, + prometheus.CounterValue, + v.TrackedtransactionsPersec, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesTransactions, + prometheus.CounterValue, + v.TransactionsPersec, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesWriteTransactions, + prometheus.CounterValue, + v.WriteTransactionsPersec, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesXTPControllerDLCLatencyPerFetch, + prometheus.GaugeValue, + v.XTPControllerDLCLatencyPerFetch, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesXTPControllerDLCPeakLatency, + prometheus.GaugeValue, + v.XTPControllerDLCPeakLatency*1000000.0, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesXTPControllerLogProcessed, + prometheus.CounterValue, + v.XTPControllerLogProcessedPersec, + sqlInstance, dbName, + ) + + ch <- prometheus.MustNewConstMetric( + c.DatabasesXTPMemoryUsedKB, + prometheus.GaugeValue, + v.XTPMemoryUsedKB*1024, + sqlInstance, dbName, + ) + } + return nil, nil +} + +// Win32_PerfRawData_MSSQLSERVER_SQLServerGeneralStatistics docs: +// - https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-general-statistics-object +type mssqlGeneralStatistics struct { + ActiveTempTables float64 `perflib:"Active Temp Tables"` + ConnectionResetPersec float64 `perflib:"Connection Reset/sec"` + EventNotificationsDelayedDrop float64 `perflib:"Event Notifications Delayed Drop"` + HTTPAuthenticatedRequests float64 `perflib:"HTTP Authenticated Requests"` + LogicalConnections float64 `perflib:"Logical Connections"` + LoginsPersec float64 `perflib:"Logins/sec"` + LogoutsPersec float64 `perflib:"Logouts/sec"` + MarsDeadlocks float64 `perflib:"Mars Deadlocks"` + Nonatomicyieldrate float64 `perflib:"Non-atomic yield rate"` + Processesblocked float64 `perflib:"Processes blocked"` + SOAPEmptyRequests float64 `perflib:"SOAP Empty Requests"` + SOAPMethodInvocations float64 `perflib:"SOAP Method Invocations"` + SOAPSessionInitiateRequests float64 `perflib:"SOAP Session Initiate Requests"` + SOAPSessionTerminateRequests float64 `perflib:"SOAP Session Terminate Requests"` + SOAPSQLRequests float64 `perflib:"SOAP SQL Requests"` + SOAPWSDLRequests float64 `perflib:"SOAP WSDL Requests"` + SQLTraceIOProviderLockWaits float64 `perflib:"SQL Trace IO Provider Lock Waits"` + Tempdbrecoveryunitid float64 `perflib:"Tempdb recovery unit id"` + Tempdbrowsetid float64 `perflib:"Tempdb rowset id"` + TempTablesCreationRate float64 `perflib:"Temp Tables Creation Rate"` + TempTablesForDestruction float64 `perflib:"Temp Tables For Destruction"` + TraceEventNotificationQueue float64 `perflib:"Trace Event Notification Queue"` + Transactions float64 `perflib:"Transactions"` + UserConnections float64 `perflib:"User Connections"` +} + +func (c *MSSQLCollector) collectGeneralStatistics(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { + var dst []mssqlGeneralStatistics + log.Debugf("mssql_genstats collector iterating sql instance %s.", sqlInstance) + + if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "genstats")], &dst); err != nil { + return nil, err + } + + for _, v := range dst { + ch <- prometheus.MustNewConstMetric( + c.GenStatsActiveTempTables, + prometheus.GaugeValue, + v.ActiveTempTables, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.GenStatsConnectionReset, + prometheus.CounterValue, + v.ConnectionResetPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.GenStatsEventNotificationsDelayedDrop, + prometheus.GaugeValue, + v.EventNotificationsDelayedDrop, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.GenStatsHTTPAuthenticatedRequests, + prometheus.GaugeValue, + v.HTTPAuthenticatedRequests, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.GenStatsLogicalConnections, + prometheus.GaugeValue, + v.LogicalConnections, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.GenStatsLogins, + prometheus.CounterValue, + v.LoginsPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.GenStatsLogouts, + prometheus.CounterValue, + v.LogoutsPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.GenStatsMarsDeadlocks, + prometheus.GaugeValue, + v.MarsDeadlocks, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.GenStatsNonatomicyieldrate, + prometheus.CounterValue, + v.Nonatomicyieldrate, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.GenStatsProcessesblocked, + prometheus.GaugeValue, + v.Processesblocked, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.GenStatsSOAPEmptyRequests, + prometheus.GaugeValue, + v.SOAPEmptyRequests, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.GenStatsSOAPMethodInvocations, + prometheus.GaugeValue, + v.SOAPMethodInvocations, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.GenStatsSOAPSessionInitiateRequests, + prometheus.GaugeValue, + v.SOAPSessionInitiateRequests, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.GenStatsSOAPSessionTerminateRequests, + prometheus.GaugeValue, + v.SOAPSessionTerminateRequests, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.GenStatsSOAPSQLRequests, + prometheus.GaugeValue, + v.SOAPSQLRequests, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.GenStatsSOAPWSDLRequests, + prometheus.GaugeValue, + v.SOAPWSDLRequests, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.GenStatsSQLTraceIOProviderLockWaits, + prometheus.GaugeValue, + v.SQLTraceIOProviderLockWaits, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.GenStatsTempdbrecoveryunitid, + prometheus.GaugeValue, + v.Tempdbrecoveryunitid, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.GenStatsTempdbrowsetid, + prometheus.GaugeValue, + v.Tempdbrowsetid, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.GenStatsTempTablesCreationRate, + prometheus.CounterValue, + v.TempTablesCreationRate, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.GenStatsTempTablesForDestruction, + prometheus.GaugeValue, + v.TempTablesForDestruction, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.GenStatsTraceEventNotificationQueue, + prometheus.GaugeValue, + v.TraceEventNotificationQueue, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.GenStatsTransactions, + prometheus.GaugeValue, + v.Transactions, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.GenStatsUserConnections, + prometheus.GaugeValue, + v.UserConnections, + sqlInstance, + ) + } + + return nil, nil +} + +// Win32_PerfRawData_MSSQLSERVER_SQLServerLocks docs: +// - https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-locks-object +type mssqlLocks struct { + Name string + AverageWaitTimems float64 `perflib:"Average Wait Time (ms)"` + AverageWaitTimems_Base float64 `perflib:"Average Wait Time Base_Base"` + LockRequestsPersec float64 `perflib:"Lock Requests/sec"` + LockTimeoutsPersec float64 `perflib:"Lock Timeouts/sec"` + LockTimeoutstimeout0Persec float64 `perflib:"Lock Timeouts (timeout > 0)/sec"` + LockWaitsPersec float64 `perflib:"Lock Waits/sec"` + LockWaitTimems float64 `perflib:"Lock Wait Time (ms)"` + NumberofDeadlocksPersec float64 `perflib:"Number of Deadlocks/sec"` +} + +func (c *MSSQLCollector) collectLocks(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { + var dst []mssqlLocks + log.Debugf("mssql_locks collector iterating sql instance %s.", sqlInstance) + + if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "locks")], &dst); err != nil { + return nil, err + } + + for _, v := range dst { + if strings.ToLower(v.Name) == "_total" { + continue + } + lockResourceName := v.Name + + ch <- prometheus.MustNewConstMetric( + c.LocksWaitTime, + prometheus.GaugeValue, + v.AverageWaitTimems/1000.0, + sqlInstance, lockResourceName, + ) + + ch <- prometheus.MustNewConstMetric( + c.LocksCount, + prometheus.GaugeValue, + v.AverageWaitTimems_Base/1000.0, + sqlInstance, lockResourceName, + ) + + ch <- prometheus.MustNewConstMetric( + c.LocksLockRequests, + prometheus.CounterValue, + v.LockRequestsPersec, + sqlInstance, lockResourceName, + ) + + ch <- prometheus.MustNewConstMetric( + c.LocksLockTimeouts, + prometheus.CounterValue, + v.LockTimeoutsPersec, + sqlInstance, lockResourceName, + ) + + ch <- prometheus.MustNewConstMetric( + c.LocksLockTimeoutstimeout0, + prometheus.CounterValue, + v.LockTimeoutstimeout0Persec, + sqlInstance, lockResourceName, + ) + + ch <- prometheus.MustNewConstMetric( + c.LocksLockWaits, + prometheus.CounterValue, + v.LockWaitsPersec, + sqlInstance, lockResourceName, + ) + + ch <- prometheus.MustNewConstMetric( + c.LocksLockWaitTimems, + prometheus.GaugeValue, + v.LockWaitTimems/1000.0, + sqlInstance, lockResourceName, + ) + + ch <- prometheus.MustNewConstMetric( + c.LocksNumberofDeadlocks, + prometheus.CounterValue, + v.NumberofDeadlocksPersec, + sqlInstance, lockResourceName, + ) + } + return nil, nil +} + +// Win32_PerfRawData_MSSQLSERVER_SQLServerMemoryManager docs: +// - https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-memory-manager-object +type mssqlMemoryManager struct { + ConnectionMemoryKB float64 `perflib:"Connection Memory (KB)"` + DatabaseCacheMemoryKB float64 `perflib:"Database Cache Memory (KB)"` + Externalbenefitofmemory float64 `perflib:"External benefit of memory"` + FreeMemoryKB float64 `perflib:"Free Memory (KB)"` + GrantedWorkspaceMemoryKB float64 `perflib:"Granted Workspace Memory (KB)"` + LockBlocks float64 `perflib:"Lock Blocks"` + LockBlocksAllocated float64 `perflib:"Lock Blocks Allocated"` + LockMemoryKB float64 `perflib:"Lock Memory (KB)"` + LockOwnerBlocks float64 `perflib:"Lock Owner Blocks"` + LockOwnerBlocksAllocated float64 `perflib:"Lock Owner Blocks Allocated"` + LogPoolMemoryKB float64 `perflib:"Log Pool Memory (KB)"` + MaximumWorkspaceMemoryKB float64 `perflib:"Maximum Workspace Memory (KB)"` + MemoryGrantsOutstanding float64 `perflib:"Memory Grants Outstanding"` + MemoryGrantsPending float64 `perflib:"Memory Grants Pending"` + OptimizerMemoryKB float64 `perflib:"Optimizer Memory (KB)"` + ReservedServerMemoryKB float64 `perflib:"Reserved Server Memory (KB)"` + SQLCacheMemoryKB float64 `perflib:"SQL Cache Memory (KB)"` + StolenServerMemoryKB float64 `perflib:"Stolen Server Memory (KB)"` + TargetServerMemoryKB float64 `perflib:"Target Server Memory (KB)"` + TotalServerMemoryKB float64 `perflib:"Total Server Memory (KB)"` +} + +func (c *MSSQLCollector) collectMemoryManager(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { + var dst []mssqlMemoryManager + log.Debugf("mssql_memmgr collector iterating sql instance %s.", sqlInstance) + + if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "memmgr")], &dst); err != nil { + return nil, err + } + + for _, v := range dst { + ch <- prometheus.MustNewConstMetric( + c.MemMgrConnectionMemoryKB, + prometheus.GaugeValue, + v.ConnectionMemoryKB*1024, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.MemMgrDatabaseCacheMemoryKB, + prometheus.GaugeValue, + v.DatabaseCacheMemoryKB*1024, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.MemMgrExternalbenefitofmemory, + prometheus.GaugeValue, + v.Externalbenefitofmemory, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.MemMgrFreeMemoryKB, + prometheus.GaugeValue, + v.FreeMemoryKB*1024, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.MemMgrGrantedWorkspaceMemoryKB, + prometheus.GaugeValue, + v.GrantedWorkspaceMemoryKB*1024, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.MemMgrLockBlocks, + prometheus.GaugeValue, + v.LockBlocks, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.MemMgrLockBlocksAllocated, + prometheus.GaugeValue, + v.LockBlocksAllocated, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.MemMgrLockMemoryKB, + prometheus.GaugeValue, + v.LockMemoryKB*1024, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.MemMgrLockOwnerBlocks, + prometheus.GaugeValue, + v.LockOwnerBlocks, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.MemMgrLockOwnerBlocksAllocated, + prometheus.GaugeValue, + v.LockOwnerBlocksAllocated, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.MemMgrLogPoolMemoryKB, + prometheus.GaugeValue, + v.LogPoolMemoryKB*1024, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.MemMgrMaximumWorkspaceMemoryKB, + prometheus.GaugeValue, + v.MaximumWorkspaceMemoryKB*1024, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.MemMgrMemoryGrantsOutstanding, + prometheus.GaugeValue, + v.MemoryGrantsOutstanding, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.MemMgrMemoryGrantsPending, + prometheus.GaugeValue, + v.MemoryGrantsPending, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.MemMgrOptimizerMemoryKB, + prometheus.GaugeValue, + v.OptimizerMemoryKB*1024, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.MemMgrReservedServerMemoryKB, + prometheus.GaugeValue, + v.ReservedServerMemoryKB*1024, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.MemMgrSQLCacheMemoryKB, + prometheus.GaugeValue, + v.SQLCacheMemoryKB*1024, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.MemMgrStolenServerMemoryKB, + prometheus.GaugeValue, + v.StolenServerMemoryKB*1024, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.MemMgrTargetServerMemoryKB, + prometheus.GaugeValue, + v.TargetServerMemoryKB*1024, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.MemMgrTotalServerMemoryKB, + prometheus.GaugeValue, + v.TotalServerMemoryKB*1024, + sqlInstance, + ) + } + + return nil, nil +} + +// Win32_PerfRawData_MSSQLSERVER_SQLServerSQLStatistics docs: +// - https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-sql-statistics-object +type mssqlSQLStatistics struct { + AutoParamAttemptsPersec float64 `perflib:"Auto-Param Attempts/sec"` + BatchRequestsPersec float64 `perflib:"Batch Requests/sec"` + FailedAutoParamsPersec float64 `perflib:"Failed Auto-Params/sec"` + ForcedParameterizationsPersec float64 `perflib:"Forced Parameterizations/sec"` + GuidedplanexecutionsPersec float64 `perflib:"Guided plan executions/sec"` + MisguidedplanexecutionsPersec float64 `perflib:"Misguided plan executions/sec"` + SafeAutoParamsPersec float64 `perflib:"Safe Auto-Params/sec"` + SQLAttentionrate float64 `perflib:"SQL Attention rate"` + SQLCompilationsPersec float64 `perflib:"SQL Compilations/sec"` + SQLReCompilationsPersec float64 `perflib:"SQL Re-Compilations/sec"` + UnsafeAutoParamsPersec float64 `perflib:"Unsafe Auto-Params/sec"` +} + +func (c *MSSQLCollector) collectSQLStats(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { + var dst []mssqlSQLStatistics + log.Debugf("mssql_sqlstats collector iterating sql instance %s.", sqlInstance) + + if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "sqlstats")], &dst); err != nil { + return nil, err + } + + for _, v := range dst { + ch <- prometheus.MustNewConstMetric( + c.SQLStatsAutoParamAttempts, + prometheus.CounterValue, + v.AutoParamAttemptsPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.SQLStatsBatchRequests, + prometheus.CounterValue, + v.BatchRequestsPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.SQLStatsFailedAutoParams, + prometheus.CounterValue, + v.FailedAutoParamsPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.SQLStatsForcedParameterizations, + prometheus.CounterValue, + v.ForcedParameterizationsPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.SQLStatsGuidedplanexecutions, + prometheus.CounterValue, + v.GuidedplanexecutionsPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.SQLStatsMisguidedplanexecutions, + prometheus.CounterValue, + v.MisguidedplanexecutionsPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.SQLStatsSafeAutoParams, + prometheus.CounterValue, + v.SafeAutoParamsPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.SQLStatsSQLAttentionrate, + prometheus.CounterValue, + v.SQLAttentionrate, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.SQLStatsSQLCompilations, + prometheus.CounterValue, + v.SQLCompilationsPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.SQLStatsSQLReCompilations, + prometheus.CounterValue, + v.SQLReCompilationsPersec, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.SQLStatsUnsafeAutoParams, + prometheus.CounterValue, + v.UnsafeAutoParamsPersec, + sqlInstance, + ) + } + + return nil, nil +} + +type mssqlSQLErrors struct { + Name string + ErrorsPersec float64 `perflib:"Errors/sec"` +} + +// Win32_PerfRawData_MSSQLSERVER_SQLServerErrors docs: +// - https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-sql-errors-object +func (c *MSSQLCollector) collectSQLErrors(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { + var dst []mssqlSQLErrors + log.Debugf("mssql_sqlerrors collector iterating sql instance %s.", sqlInstance) + + if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "sqlerrors")], &dst); err != nil { + return nil, err + } + + for _, v := range dst { + if strings.ToLower(v.Name) == "_total" { + continue + } + resource := v.Name + + ch <- prometheus.MustNewConstMetric( + c.SQLErrorsTotal, + prometheus.CounterValue, + v.ErrorsPersec, + sqlInstance, resource, + ) + } + + return nil, nil +} + +type mssqlTransactions struct { + FreeSpaceintempdbKB float64 `perflib:"Free Space in tempdb (KB)"` + LongestTransactionRunningTime float64 `perflib:"Longest Transaction Running Time"` + NonSnapshotVersionTransactions float64 `perflib:"NonSnapshot Version Transactions"` + SnapshotTransactions float64 `perflib:"Snapshot Transactions"` + Transactions float64 `perflib:"Transactions"` + Updateconflictratio float64 `perflib:"Update conflict ratio"` + UpdateSnapshotTransactions float64 `perflib:"Update Snapshot Transactions"` + VersionCleanuprateKBPers float64 `perflib:"Version Cleanup rate (KB/s)"` + VersionGenerationrateKBPers float64 `perflib:"Version Generation rate (KB/s)"` + VersionStoreSizeKB float64 `perflib:"Version Store Size (KB)"` + VersionStoreunitcount float64 `perflib:"Version Store unit count"` + VersionStoreunitcreation float64 `perflib:"Version Store unit creation"` + VersionStoreunittruncation float64 `perflib:"Version Store unit truncation"` +} + +// Win32_PerfRawData_MSSQLSERVER_Transactions docs: +// - https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-transactions-object +func (c *MSSQLCollector) collectTransactions(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { + var dst []mssqlTransactions + log.Debugf("mssql_transactions collector iterating sql instance %s.", sqlInstance) + + if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "transactions")], &dst); err != nil { + return nil, err + } + + for _, v := range dst { + ch <- prometheus.MustNewConstMetric( + c.TransactionsTempDbFreeSpaceBytes, + prometheus.GaugeValue, + v.FreeSpaceintempdbKB*1024, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.TransactionsLongestTransactionRunningSeconds, + prometheus.GaugeValue, + v.LongestTransactionRunningTime, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.TransactionsNonSnapshotVersionActiveTotal, + prometheus.CounterValue, + v.NonSnapshotVersionTransactions, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.TransactionsSnapshotActiveTotal, + prometheus.CounterValue, + v.SnapshotTransactions, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.TransactionsActive, + prometheus.GaugeValue, + v.Transactions, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.TransactionsUpdateConflictsTotal, + prometheus.CounterValue, + v.Updateconflictratio, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.TransactionsUpdateSnapshotActiveTotal, + prometheus.CounterValue, + v.UpdateSnapshotTransactions, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.TransactionsVersionCleanupRateBytes, + prometheus.GaugeValue, + v.VersionCleanuprateKBPers*1024, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.TransactionsVersionGenerationRateBytes, + prometheus.GaugeValue, + v.VersionGenerationrateKBPers*1024, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.TransactionsVersionStoreSizeBytes, + prometheus.GaugeValue, + v.VersionStoreSizeKB*1024, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.TransactionsVersionStoreUnits, + prometheus.CounterValue, + v.VersionStoreunitcount, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.TransactionsVersionStoreCreationUnits, + prometheus.CounterValue, + v.VersionStoreunitcreation, + sqlInstance, + ) + + ch <- prometheus.MustNewConstMetric( + c.TransactionsVersionStoreTruncationUnits, + prometheus.CounterValue, + v.VersionStoreunittruncation, + sqlInstance, + ) + } + + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/net.go b/vendor/github.com/prometheus-community/windows_exporter/collector/net.go new file mode 100644 index 000000000000..959cb28cc776 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/net.go @@ -0,0 +1,269 @@ +// +build windows + +package collector + +import ( + "fmt" + "regexp" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" + "gopkg.in/alecthomas/kingpin.v2" +) + +func init() { + registerCollectorWithConfig("net", func() Config { return &NetworkConfig{} }, "Network Interface") +} + +var nicNameToUnderscore = regexp.MustCompile("[^a-zA-Z0-9]") + +type NetworkConfig struct { + NICWhiteList string + NICBlackList string +} + +func (n *NetworkConfig) RegisterKingpin(ka *kingpin.Application) { + ka.Flag( + "collector.net.nic-whitelist", + "Regexp of NIC:s to whitelist. NIC name must both match whitelist and not match blacklist to be included.", + ).Default(".+").StringVar(&n.NICWhiteList) + ka.Flag( + "collector.net.nic-blacklist", + "Regexp of NIC:s to blacklist. NIC name must both match whitelist and not match blacklist to be included.", + ).Default("").StringVar(&n.NICBlackList) +} + +func (n *NetworkConfig) Build() (Collector, error) { + return NewNetworkCollector(n) +} + +// A NetworkCollector is a Prometheus collector for Perflib Network Interface metrics +type NetworkCollector struct { + BytesReceivedTotal *prometheus.Desc + BytesSentTotal *prometheus.Desc + BytesTotal *prometheus.Desc + PacketsOutboundDiscarded *prometheus.Desc + PacketsOutboundErrors *prometheus.Desc + PacketsTotal *prometheus.Desc + PacketsReceivedDiscarded *prometheus.Desc + PacketsReceivedErrors *prometheus.Desc + PacketsReceivedTotal *prometheus.Desc + PacketsReceivedUnknown *prometheus.Desc + PacketsSentTotal *prometheus.Desc + CurrentBandwidth *prometheus.Desc + + nicWhitelistPattern *regexp.Regexp + nicBlacklistPattern *regexp.Regexp +} + +// NewNetworkCollector ... +func NewNetworkCollector(n *NetworkConfig) (Collector, error) { + const subsystem = "net" + + return &NetworkCollector{ + BytesReceivedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bytes_received_total"), + "(Network.BytesReceivedPerSec)", + []string{"nic"}, + nil, + ), + BytesSentTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bytes_sent_total"), + "(Network.BytesSentPerSec)", + []string{"nic"}, + nil, + ), + BytesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bytes_total"), + "(Network.BytesTotalPerSec)", + []string{"nic"}, + nil, + ), + PacketsOutboundDiscarded: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "packets_outbound_discarded_total"), + "(Network.PacketsOutboundDiscarded)", + []string{"nic"}, + nil, + ), + PacketsOutboundErrors: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "packets_outbound_errors_total"), + "(Network.PacketsOutboundErrors)", + []string{"nic"}, + nil, + ), + PacketsReceivedDiscarded: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "packets_received_discarded_total"), + "(Network.PacketsReceivedDiscarded)", + []string{"nic"}, + nil, + ), + PacketsReceivedErrors: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "packets_received_errors_total"), + "(Network.PacketsReceivedErrors)", + []string{"nic"}, + nil, + ), + PacketsReceivedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "packets_received_total"), + "(Network.PacketsReceivedPerSec)", + []string{"nic"}, + nil, + ), + PacketsReceivedUnknown: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "packets_received_unknown_total"), + "(Network.PacketsReceivedUnknown)", + []string{"nic"}, + nil, + ), + PacketsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "packets_total"), + "(Network.PacketsPerSec)", + []string{"nic"}, + nil, + ), + PacketsSentTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "packets_sent_total"), + "(Network.PacketsSentPerSec)", + []string{"nic"}, + nil, + ), + CurrentBandwidth: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "current_bandwidth"), + "(Network.CurrentBandwidth)", + []string{"nic"}, + nil, + ), + + nicWhitelistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", n.NICWhiteList)), + nicBlacklistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", n.NICBlackList)), + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *NetworkCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ctx, ch); err != nil { + log.Error("failed collecting net metrics:", desc, err) + return err + } + return nil +} + +// mangleNetworkName mangles Network Adapter name (non-alphanumeric to _) +// that is used in networkInterface. +func mangleNetworkName(name string) string { + return nicNameToUnderscore.ReplaceAllString(name, "_") +} + +// Win32_PerfRawData_Tcpip_NetworkInterface docs: +// - https://technet.microsoft.com/en-us/security/aa394340(v=vs.80) +type networkInterface struct { + BytesReceivedPerSec float64 `perflib:"Bytes Received/sec"` + BytesSentPerSec float64 `perflib:"Bytes Sent/sec"` + BytesTotalPerSec float64 `perflib:"Bytes Total/sec"` + Name string + PacketsOutboundDiscarded float64 `perflib:"Packets Outbound Discarded"` + PacketsOutboundErrors float64 `perflib:"Packets Outbound Errors"` + PacketsPerSec float64 `perflib:"Packets/sec"` + PacketsReceivedDiscarded float64 `perflib:"Packets Received Discarded"` + PacketsReceivedErrors float64 `perflib:"Packets Received Errors"` + PacketsReceivedPerSec float64 `perflib:"Packets Received/sec"` + PacketsReceivedUnknown float64 `perflib:"Packets Received Unknown"` + PacketsSentPerSec float64 `perflib:"Packets Sent/sec"` + CurrentBandwidth float64 `perflib:"Current Bandwidth"` +} + +func (c *NetworkCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []networkInterface + + if err := unmarshalObject(ctx.perfObjects["Network Interface"], &dst); err != nil { + return nil, err + } + + for _, nic := range dst { + if c.nicBlacklistPattern.MatchString(nic.Name) || + !c.nicWhitelistPattern.MatchString(nic.Name) { + continue + } + + name := mangleNetworkName(nic.Name) + if name == "" { + continue + } + + // Counters + ch <- prometheus.MustNewConstMetric( + c.BytesReceivedTotal, + prometheus.CounterValue, + nic.BytesReceivedPerSec, + name, + ) + ch <- prometheus.MustNewConstMetric( + c.BytesSentTotal, + prometheus.CounterValue, + nic.BytesSentPerSec, + name, + ) + ch <- prometheus.MustNewConstMetric( + c.BytesTotal, + prometheus.CounterValue, + nic.BytesTotalPerSec, + name, + ) + ch <- prometheus.MustNewConstMetric( + c.PacketsOutboundDiscarded, + prometheus.CounterValue, + nic.PacketsOutboundDiscarded, + name, + ) + ch <- prometheus.MustNewConstMetric( + c.PacketsOutboundErrors, + prometheus.CounterValue, + nic.PacketsOutboundErrors, + name, + ) + ch <- prometheus.MustNewConstMetric( + c.PacketsTotal, + prometheus.CounterValue, + nic.PacketsPerSec, + name, + ) + ch <- prometheus.MustNewConstMetric( + c.PacketsReceivedDiscarded, + prometheus.CounterValue, + nic.PacketsReceivedDiscarded, + name, + ) + ch <- prometheus.MustNewConstMetric( + c.PacketsReceivedErrors, + prometheus.CounterValue, + nic.PacketsReceivedErrors, + name, + ) + ch <- prometheus.MustNewConstMetric( + c.PacketsReceivedTotal, + prometheus.CounterValue, + nic.PacketsReceivedPerSec, + name, + ) + ch <- prometheus.MustNewConstMetric( + c.PacketsReceivedUnknown, + prometheus.CounterValue, + nic.PacketsReceivedUnknown, + name, + ) + ch <- prometheus.MustNewConstMetric( + c.PacketsSentTotal, + prometheus.CounterValue, + nic.PacketsSentPerSec, + name, + ) + ch <- prometheus.MustNewConstMetric( + c.CurrentBandwidth, + prometheus.GaugeValue, + nic.CurrentBandwidth, + name, + ) + } + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/netframework_clrexceptions.go b/vendor/github.com/prometheus-community/windows_exporter/collector/netframework_clrexceptions.go new file mode 100644 index 000000000000..ffced9129df8 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/netframework_clrexceptions.go @@ -0,0 +1,117 @@ +// +build windows + +package collector + +import ( + "github.com/StackExchange/wmi" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +func init() { + registerCollector("netframework_clrexceptions", NewNETFramework_NETCLRExceptionsCollector) +} + +// A NETFramework_NETCLRExceptionsCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRExceptions metrics +type NETFramework_NETCLRExceptionsCollector struct { + NumberofExcepsThrown *prometheus.Desc + NumberofFilters *prometheus.Desc + NumberofFinallys *prometheus.Desc + ThrowToCatchDepth *prometheus.Desc +} + +// NewNETFramework_NETCLRExceptionsCollector ... +func NewNETFramework_NETCLRExceptionsCollector() (Collector, error) { + const subsystem = "netframework_clrexceptions" + return &NETFramework_NETCLRExceptionsCollector{ + NumberofExcepsThrown: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "exceptions_thrown_total"), + "Displays the total number of exceptions thrown since the application started. This includes both .NET exceptions and unmanaged exceptions that are converted into .NET exceptions.", + []string{"process"}, + nil, + ), + NumberofFilters: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "exceptions_filters_total"), + "Displays the total number of .NET exception filters executed. An exception filter evaluates regardless of whether an exception is handled.", + []string{"process"}, + nil, + ), + NumberofFinallys: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "exceptions_finallys_total"), + "Displays the total number of finally blocks executed. Only the finally blocks executed for an exception are counted; finally blocks on normal code paths are not counted by this counter.", + []string{"process"}, + nil, + ), + ThrowToCatchDepth: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "throw_to_catch_depth_total"), + "Displays the total number of stack frames traversed, from the frame that threw the exception to the frame that handled the exception.", + []string{"process"}, + nil, + ), + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *NETFramework_NETCLRExceptionsCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + log.Error("failed collecting win32_perfrawdata_netframework_netclrexceptions metrics:", desc, err) + return err + } + return nil +} + +type Win32_PerfRawData_NETFramework_NETCLRExceptions struct { + Name string + + NumberofExcepsThrown uint32 + NumberofExcepsThrownPersec uint32 + NumberofFiltersPersec uint32 + NumberofFinallysPersec uint32 + ThrowToCatchDepthPersec uint32 +} + +func (c *NETFramework_NETCLRExceptionsCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_NETFramework_NETCLRExceptions + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, process := range dst { + + if process.Name == "_Global_" { + continue + } + + ch <- prometheus.MustNewConstMetric( + c.NumberofExcepsThrown, + prometheus.CounterValue, + float64(process.NumberofExcepsThrown), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.NumberofFilters, + prometheus.CounterValue, + float64(process.NumberofFiltersPersec), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.NumberofFinallys, + prometheus.CounterValue, + float64(process.NumberofFinallysPersec), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.ThrowToCatchDepth, + prometheus.CounterValue, + float64(process.ThrowToCatchDepthPersec), + process.Name, + ) + } + + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/netframework_clrinterop.go b/vendor/github.com/prometheus-community/windows_exporter/collector/netframework_clrinterop.go new file mode 100644 index 000000000000..78171919bdc3 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/netframework_clrinterop.go @@ -0,0 +1,103 @@ +// +build windows + +package collector + +import ( + "github.com/StackExchange/wmi" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +func init() { + registerCollector("netframework_clrinterop", NewNETFramework_NETCLRInteropCollector) +} + +// A NETFramework_NETCLRInteropCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRInterop metrics +type NETFramework_NETCLRInteropCollector struct { + NumberofCCWs *prometheus.Desc + Numberofmarshalling *prometheus.Desc + NumberofStubs *prometheus.Desc +} + +// NewNETFramework_NETCLRInteropCollector ... +func NewNETFramework_NETCLRInteropCollector() (Collector, error) { + const subsystem = "netframework_clrinterop" + return &NETFramework_NETCLRInteropCollector{ + NumberofCCWs: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "com_callable_wrappers_total"), + "Displays the current number of COM callable wrappers (CCWs). A CCW is a proxy for a managed object being referenced from an unmanaged COM client.", + []string{"process"}, + nil, + ), + Numberofmarshalling: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "interop_marshalling_total"), + "Displays the total number of times arguments and return values have been marshaled from managed to unmanaged code, and vice versa, since the application started.", + []string{"process"}, + nil, + ), + NumberofStubs: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "interop_stubs_created_total"), + "Displays the current number of stubs created by the common language runtime. Stubs are responsible for marshaling arguments and return values from managed to unmanaged code, and vice versa, during a COM interop call or a platform invoke call.", + []string{"process"}, + nil, + ), + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *NETFramework_NETCLRInteropCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + log.Error("failed collecting win32_perfrawdata_netframework_netclrinterop metrics:", desc, err) + return err + } + return nil +} + +type Win32_PerfRawData_NETFramework_NETCLRInterop struct { + Name string + + NumberofCCWs uint32 + Numberofmarshalling uint32 + NumberofStubs uint32 + NumberofTLBexportsPersec uint32 + NumberofTLBimportsPersec uint32 +} + +func (c *NETFramework_NETCLRInteropCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_NETFramework_NETCLRInterop + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, process := range dst { + + if process.Name == "_Global_" { + continue + } + + ch <- prometheus.MustNewConstMetric( + c.NumberofCCWs, + prometheus.CounterValue, + float64(process.NumberofCCWs), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.Numberofmarshalling, + prometheus.CounterValue, + float64(process.Numberofmarshalling), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.NumberofStubs, + prometheus.CounterValue, + float64(process.NumberofStubs), + process.Name, + ) + } + + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/netframework_clrjit.go b/vendor/github.com/prometheus-community/windows_exporter/collector/netframework_clrjit.go new file mode 100644 index 000000000000..fb3d4c2a5f34 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/netframework_clrjit.go @@ -0,0 +1,119 @@ +// +build windows + +package collector + +import ( + "github.com/StackExchange/wmi" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +func init() { + registerCollector("netframework_clrjit", NewNETFramework_NETCLRJitCollector) +} + +// A NETFramework_NETCLRJitCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRJit metrics +type NETFramework_NETCLRJitCollector struct { + NumberofMethodsJitted *prometheus.Desc + TimeinJit *prometheus.Desc + StandardJitFailures *prometheus.Desc + TotalNumberofILBytesJitted *prometheus.Desc +} + +// NewNETFramework_NETCLRJitCollector ... +func NewNETFramework_NETCLRJitCollector() (Collector, error) { + const subsystem = "netframework_clrjit" + return &NETFramework_NETCLRJitCollector{ + NumberofMethodsJitted: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "jit_methods_total"), + "Displays the total number of methods JIT-compiled since the application started. This counter does not include pre-JIT-compiled methods.", + []string{"process"}, + nil, + ), + TimeinJit: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "jit_time_percent"), + "Displays the percentage of time spent in JIT compilation. This counter is updated at the end of every JIT compilation phase. A JIT compilation phase occurs when a method and its dependencies are compiled.", + []string{"process"}, + nil, + ), + StandardJitFailures: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "jit_standard_failures_total"), + "Displays the peak number of methods the JIT compiler has failed to compile since the application started. This failure can occur if the MSIL cannot be verified or if there is an internal error in the JIT compiler.", + []string{"process"}, + nil, + ), + TotalNumberofILBytesJitted: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "jit_il_bytes_total"), + "Displays the total number of Microsoft intermediate language (MSIL) bytes compiled by the just-in-time (JIT) compiler since the application started", + []string{"process"}, + nil, + ), + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *NETFramework_NETCLRJitCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + log.Error("failed collecting win32_perfrawdata_netframework_netclrjit metrics:", desc, err) + return err + } + return nil +} + +type Win32_PerfRawData_NETFramework_NETCLRJit struct { + Name string + + Frequency_PerfTime uint32 + ILBytesJittedPersec uint32 + NumberofILBytesJitted uint32 + NumberofMethodsJitted uint32 + PercentTimeinJit uint32 + StandardJitFailures uint32 + TotalNumberofILBytesJitted uint32 +} + +func (c *NETFramework_NETCLRJitCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_NETFramework_NETCLRJit + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, process := range dst { + + if process.Name == "_Global_" { + continue + } + + ch <- prometheus.MustNewConstMetric( + c.NumberofMethodsJitted, + prometheus.CounterValue, + float64(process.NumberofMethodsJitted), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TimeinJit, + prometheus.GaugeValue, + float64(process.PercentTimeinJit)/float64(process.Frequency_PerfTime), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.StandardJitFailures, + prometheus.GaugeValue, + float64(process.StandardJitFailures), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TotalNumberofILBytesJitted, + prometheus.CounterValue, + float64(process.TotalNumberofILBytesJitted), + process.Name, + ) + } + + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/netframework_clrloading.go b/vendor/github.com/prometheus-community/windows_exporter/collector/netframework_clrloading.go new file mode 100644 index 000000000000..aba0921c1232 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/netframework_clrloading.go @@ -0,0 +1,198 @@ +// +build windows + +package collector + +import ( + "github.com/StackExchange/wmi" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +func init() { + registerCollector("netframework_clrloading", NewNETFramework_NETCLRLoadingCollector) +} + +// A NETFramework_NETCLRLoadingCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRLoading metrics +type NETFramework_NETCLRLoadingCollector struct { + BytesinLoaderHeap *prometheus.Desc + Currentappdomains *prometheus.Desc + CurrentAssemblies *prometheus.Desc + CurrentClassesLoaded *prometheus.Desc + TotalAppdomains *prometheus.Desc + Totalappdomainsunloaded *prometheus.Desc + TotalAssemblies *prometheus.Desc + TotalClassesLoaded *prometheus.Desc + TotalNumberofLoadFailures *prometheus.Desc +} + +// NewNETFramework_NETCLRLoadingCollector ... +func NewNETFramework_NETCLRLoadingCollector() (Collector, error) { + const subsystem = "netframework_clrloading" + return &NETFramework_NETCLRLoadingCollector{ + BytesinLoaderHeap: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "loader_heap_size_bytes"), + "Displays the current size, in bytes, of the memory committed by the class loader across all application domains. Committed memory is the physical space reserved in the disk paging file.", + []string{"process"}, + nil, + ), + Currentappdomains: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "appdomains_loaded_current"), + "Displays the current number of application domains loaded in this application.", + []string{"process"}, + nil, + ), + CurrentAssemblies: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "assemblies_loaded_current"), + "Displays the current number of assemblies loaded across all application domains in the currently running application. If the assembly is loaded as domain-neutral from multiple application domains, this counter is incremented only once.", + []string{"process"}, + nil, + ), + CurrentClassesLoaded: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "classes_loaded_current"), + "Displays the current number of classes loaded in all assemblies.", + []string{"process"}, + nil, + ), + TotalAppdomains: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "appdomains_loaded_total"), + "Displays the peak number of application domains loaded since the application started.", + []string{"process"}, + nil, + ), + Totalappdomainsunloaded: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "appdomains_unloaded_total"), + "Displays the total number of application domains unloaded since the application started. If an application domain is loaded and unloaded multiple times, this counter increments each time the application domain is unloaded.", + []string{"process"}, + nil, + ), + TotalAssemblies: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "assemblies_loaded_total"), + "Displays the total number of assemblies loaded since the application started. If the assembly is loaded as domain-neutral from multiple application domains, this counter is incremented only once.", + []string{"process"}, + nil, + ), + TotalClassesLoaded: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "classes_loaded_total"), + "Displays the cumulative number of classes loaded in all assemblies since the application started.", + []string{"process"}, + nil, + ), + TotalNumberofLoadFailures: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "class_load_failures_total"), + "Displays the peak number of classes that have failed to load since the application started.", + []string{"process"}, + nil, + ), + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *NETFramework_NETCLRLoadingCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + log.Error("failed collecting win32_perfrawdata_netframework_netclrloading metrics:", desc, err) + return err + } + return nil +} + +type Win32_PerfRawData_NETFramework_NETCLRLoading struct { + Name string + + AssemblySearchLength uint32 + BytesinLoaderHeap uint64 + Currentappdomains uint32 + CurrentAssemblies uint32 + CurrentClassesLoaded uint32 + PercentTimeLoading uint64 + Rateofappdomains uint32 + Rateofappdomainsunloaded uint32 + RateofAssemblies uint32 + RateofClassesLoaded uint32 + RateofLoadFailures uint32 + TotalAppdomains uint32 + Totalappdomainsunloaded uint32 + TotalAssemblies uint32 + TotalClassesLoaded uint32 + TotalNumberofLoadFailures uint32 +} + +func (c *NETFramework_NETCLRLoadingCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_NETFramework_NETCLRLoading + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, process := range dst { + + if process.Name == "_Global_" { + continue + } + + ch <- prometheus.MustNewConstMetric( + c.BytesinLoaderHeap, + prometheus.GaugeValue, + float64(process.BytesinLoaderHeap), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.Currentappdomains, + prometheus.GaugeValue, + float64(process.Currentappdomains), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.CurrentAssemblies, + prometheus.GaugeValue, + float64(process.CurrentAssemblies), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.CurrentClassesLoaded, + prometheus.GaugeValue, + float64(process.CurrentClassesLoaded), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TotalAppdomains, + prometheus.CounterValue, + float64(process.TotalAppdomains), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.Totalappdomainsunloaded, + prometheus.CounterValue, + float64(process.Totalappdomainsunloaded), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TotalAssemblies, + prometheus.CounterValue, + float64(process.TotalAssemblies), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TotalClassesLoaded, + prometheus.CounterValue, + float64(process.TotalClassesLoaded), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TotalNumberofLoadFailures, + prometheus.CounterValue, + float64(process.TotalNumberofLoadFailures), + process.Name, + ) + } + + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/netframework_clrlocksandthreads.go b/vendor/github.com/prometheus-community/windows_exporter/collector/netframework_clrlocksandthreads.go new file mode 100644 index 000000000000..e446eaa205a4 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/netframework_clrlocksandthreads.go @@ -0,0 +1,164 @@ +// +build windows + +package collector + +import ( + "github.com/StackExchange/wmi" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +func init() { + registerCollector("netframework_clrlocksandthreads", NewNETFramework_NETCLRLocksAndThreadsCollector) +} + +// A NETFramework_NETCLRLocksAndThreadsCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads metrics +type NETFramework_NETCLRLocksAndThreadsCollector struct { + CurrentQueueLength *prometheus.Desc + NumberofcurrentlogicalThreads *prometheus.Desc + NumberofcurrentphysicalThreads *prometheus.Desc + Numberofcurrentrecognizedthreads *prometheus.Desc + Numberoftotalrecognizedthreads *prometheus.Desc + QueueLengthPeak *prometheus.Desc + TotalNumberofContentions *prometheus.Desc +} + +// NewNETFramework_NETCLRLocksAndThreadsCollector ... +func NewNETFramework_NETCLRLocksAndThreadsCollector() (Collector, error) { + const subsystem = "netframework_clrlocksandthreads" + return &NETFramework_NETCLRLocksAndThreadsCollector{ + CurrentQueueLength: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "current_queue_length"), + "Displays the total number of threads that are currently waiting to acquire a managed lock in the application.", + []string{"process"}, + nil, + ), + NumberofcurrentlogicalThreads: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "current_logical_threads"), + "Displays the number of current managed thread objects in the application. This counter maintains the count of both running and stopped threads. ", + []string{"process"}, + nil, + ), + NumberofcurrentphysicalThreads: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "physical_threads_current"), + "Displays the number of native operating system threads created and owned by the common language runtime to act as underlying threads for managed thread objects. This counter's value does not include the threads used by the runtime in its internal operations; it is a subset of the threads in the operating system process.", + []string{"process"}, + nil, + ), + Numberofcurrentrecognizedthreads: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "recognized_threads_current"), + "Displays the number of threads that are currently recognized by the runtime. These threads are associated with a corresponding managed thread object. The runtime does not create these threads, but they have run inside the runtime at least once.", + []string{"process"}, + nil, + ), + Numberoftotalrecognizedthreads: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "recognized_threads_total"), + "Displays the total number of threads that have been recognized by the runtime since the application started. These threads are associated with a corresponding managed thread object. The runtime does not create these threads, but they have run inside the runtime at least once.", + []string{"process"}, + nil, + ), + QueueLengthPeak: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "queue_length_total"), + "Displays the total number of threads that waited to acquire a managed lock since the application started.", + []string{"process"}, + nil, + ), + TotalNumberofContentions: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "contentions_total"), + "Displays the total number of times that threads in the runtime have attempted to acquire a managed lock unsuccessfully.", + []string{"process"}, + nil, + ), + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *NETFramework_NETCLRLocksAndThreadsCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + log.Error("failed collecting win32_perfrawdata_netframework_netclrlocksandthreads metrics:", desc, err) + return err + } + return nil +} + +type Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads struct { + Name string + + ContentionRatePersec uint32 + CurrentQueueLength uint32 + NumberofcurrentlogicalThreads uint32 + NumberofcurrentphysicalThreads uint32 + Numberofcurrentrecognizedthreads uint32 + Numberoftotalrecognizedthreads uint32 + QueueLengthPeak uint32 + QueueLengthPersec uint32 + RateOfRecognizedThreadsPersec uint32 + TotalNumberofContentions uint32 +} + +func (c *NETFramework_NETCLRLocksAndThreadsCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, process := range dst { + + if process.Name == "_Global_" { + continue + } + + ch <- prometheus.MustNewConstMetric( + c.CurrentQueueLength, + prometheus.GaugeValue, + float64(process.CurrentQueueLength), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.NumberofcurrentlogicalThreads, + prometheus.GaugeValue, + float64(process.NumberofcurrentlogicalThreads), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.NumberofcurrentphysicalThreads, + prometheus.GaugeValue, + float64(process.NumberofcurrentphysicalThreads), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.Numberofcurrentrecognizedthreads, + prometheus.GaugeValue, + float64(process.Numberofcurrentrecognizedthreads), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.Numberoftotalrecognizedthreads, + prometheus.CounterValue, + float64(process.Numberoftotalrecognizedthreads), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.QueueLengthPeak, + prometheus.CounterValue, + float64(process.QueueLengthPeak), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TotalNumberofContentions, + prometheus.CounterValue, + float64(process.TotalNumberofContentions), + process.Name, + ) + } + + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/netframework_clrmemory.go b/vendor/github.com/prometheus-community/windows_exporter/collector/netframework_clrmemory.go new file mode 100644 index 000000000000..407edde845c0 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/netframework_clrmemory.go @@ -0,0 +1,302 @@ +// +build windows + +package collector + +import ( + "github.com/StackExchange/wmi" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +func init() { + registerCollector("netframework_clrmemory", NewNETFramework_NETCLRMemoryCollector) +} + +// A NETFramework_NETCLRMemoryCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRMemory metrics +type NETFramework_NETCLRMemoryCollector struct { + AllocatedBytes *prometheus.Desc + FinalizationSurvivors *prometheus.Desc + HeapSize *prometheus.Desc + PromotedBytes *prometheus.Desc + NumberGCHandles *prometheus.Desc + NumberCollections *prometheus.Desc + NumberInducedGC *prometheus.Desc + NumberofPinnedObjects *prometheus.Desc + NumberofSinkBlocksinuse *prometheus.Desc + NumberTotalCommittedBytes *prometheus.Desc + NumberTotalreservedBytes *prometheus.Desc + TimeinGC *prometheus.Desc + PromotedFinalizationMemoryfromGen0 *prometheus.Desc + PromotedMemoryfromGen0 *prometheus.Desc + PromotedMemoryfromGen1 *prometheus.Desc +} + +// NewNETFramework_NETCLRMemoryCollector ... +func NewNETFramework_NETCLRMemoryCollector() (Collector, error) { + const subsystem = "netframework_clrmemory" + return &NETFramework_NETCLRMemoryCollector{ + AllocatedBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "allocated_bytes_total"), + "Displays the total number of bytes allocated on the garbage collection heap.", + []string{"process"}, + nil, + ), + FinalizationSurvivors: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "finalization_survivors"), + "Displays the number of garbage-collected objects that survive a collection because they are waiting to be finalized.", + []string{"process"}, + nil, + ), + HeapSize: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "heap_size_bytes"), + "Displays the maximum bytes that can be allocated; it does not indicate the current number of bytes allocated.", + []string{"process", "area"}, + nil, + ), + PromotedBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "promoted_bytes"), + "Displays the bytes that were promoted from the generation to the next one during the last GC. Memory is promoted when it survives a garbage collection.", + []string{"process", "area"}, + nil, + ), + NumberGCHandles: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "number_gc_handles"), + "Displays the current number of garbage collection handles in use. Garbage collection handles are handles to resources external to the common language runtime and the managed environment.", + []string{"process"}, + nil, + ), + NumberCollections: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "collections_total"), + "Displays the number of times the generation objects are garbage collected since the application started.", + []string{"process", "area"}, + nil, + ), + NumberInducedGC: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "induced_gc_total"), + "Displays the peak number of times garbage collection was performed because of an explicit call to GC.Collect.", + []string{"process"}, + nil, + ), + NumberofPinnedObjects: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "number_pinned_objects"), + "Displays the number of pinned objects encountered in the last garbage collection.", + []string{"process"}, + nil, + ), + NumberofSinkBlocksinuse: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "number_sink_blocksinuse"), + "Displays the current number of synchronization blocks in use. Synchronization blocks are per-object data structures allocated for storing synchronization information. They hold weak references to managed objects and must be scanned by the garbage collector.", + []string{"process"}, + nil, + ), + NumberTotalCommittedBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "committed_bytes"), + "Displays the amount of virtual memory, in bytes, currently committed by the garbage collector. Committed memory is the physical memory for which space has been reserved in the disk paging file.", + []string{"process"}, + nil, + ), + NumberTotalreservedBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "reserved_bytes"), + "Displays the amount of virtual memory, in bytes, currently reserved by the garbage collector. Reserved memory is the virtual memory space reserved for the application when no disk or main memory pages have been used.", + []string{"process"}, + nil, + ), + TimeinGC: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "gc_time_percent"), + "Displays the percentage of time that was spent performing a garbage collection in the last sample.", + []string{"process"}, + nil, + ), + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *NETFramework_NETCLRMemoryCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + log.Error("failed collecting win32_perfrawdata_netframework_netclrmemory metrics:", desc, err) + return err + } + return nil +} + +type Win32_PerfRawData_NETFramework_NETCLRMemory struct { + Name string + + AllocatedBytesPersec uint64 + FinalizationSurvivors uint64 + Frequency_PerfTime uint64 + Gen0heapsize uint64 + Gen0PromotedBytesPerSec uint64 + Gen1heapsize uint64 + Gen1PromotedBytesPerSec uint64 + Gen2heapsize uint64 + LargeObjectHeapsize uint64 + NumberBytesinallHeaps uint64 + NumberGCHandles uint64 + NumberGen0Collections uint64 + NumberGen1Collections uint64 + NumberGen2Collections uint64 + NumberInducedGC uint64 + NumberofPinnedObjects uint64 + NumberofSinkBlocksinuse uint64 + NumberTotalcommittedBytes uint64 + NumberTotalreservedBytes uint64 + PercentTimeinGC uint32 + ProcessID uint64 + PromotedFinalizationMemoryfromGen0 uint64 + PromotedMemoryfromGen0 uint64 + PromotedMemoryfromGen1 uint64 +} + +func (c *NETFramework_NETCLRMemoryCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_NETFramework_NETCLRMemory + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, process := range dst { + + if process.Name == "_Global_" { + continue + } + + ch <- prometheus.MustNewConstMetric( + c.AllocatedBytes, + prometheus.CounterValue, + float64(process.AllocatedBytesPersec), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.FinalizationSurvivors, + prometheus.GaugeValue, + float64(process.FinalizationSurvivors), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.HeapSize, + prometheus.GaugeValue, + float64(process.Gen0heapsize), + process.Name, + "Gen0", + ) + + ch <- prometheus.MustNewConstMetric( + c.PromotedBytes, + prometheus.GaugeValue, + float64(process.Gen0PromotedBytesPerSec), + process.Name, + "Gen0", + ) + + ch <- prometheus.MustNewConstMetric( + c.HeapSize, + prometheus.GaugeValue, + float64(process.Gen1heapsize), + process.Name, + "Gen1", + ) + + ch <- prometheus.MustNewConstMetric( + c.PromotedBytes, + prometheus.GaugeValue, + float64(process.Gen1PromotedBytesPerSec), + process.Name, + "Gen1", + ) + + ch <- prometheus.MustNewConstMetric( + c.HeapSize, + prometheus.GaugeValue, + float64(process.Gen2heapsize), + process.Name, + "Gen2", + ) + + ch <- prometheus.MustNewConstMetric( + c.HeapSize, + prometheus.GaugeValue, + float64(process.LargeObjectHeapsize), + process.Name, + "LOH", + ) + + ch <- prometheus.MustNewConstMetric( + c.NumberGCHandles, + prometheus.GaugeValue, + float64(process.NumberGCHandles), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.NumberCollections, + prometheus.CounterValue, + float64(process.NumberGen0Collections), + process.Name, + "Gen0", + ) + + ch <- prometheus.MustNewConstMetric( + c.NumberCollections, + prometheus.CounterValue, + float64(process.NumberGen1Collections), + process.Name, + "Gen1", + ) + + ch <- prometheus.MustNewConstMetric( + c.NumberCollections, + prometheus.CounterValue, + float64(process.NumberGen2Collections), + process.Name, + "Gen2", + ) + + ch <- prometheus.MustNewConstMetric( + c.NumberInducedGC, + prometheus.CounterValue, + float64(process.NumberInducedGC), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.NumberofPinnedObjects, + prometheus.GaugeValue, + float64(process.NumberofPinnedObjects), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.NumberofSinkBlocksinuse, + prometheus.GaugeValue, + float64(process.NumberofSinkBlocksinuse), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.NumberTotalCommittedBytes, + prometheus.GaugeValue, + float64(process.NumberTotalcommittedBytes), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.NumberTotalreservedBytes, + prometheus.GaugeValue, + float64(process.NumberTotalreservedBytes), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TimeinGC, + prometheus.GaugeValue, + float64(process.PercentTimeinGC)/float64(process.Frequency_PerfTime), + process.Name, + ) + } + + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/netframework_clrremoting.go b/vendor/github.com/prometheus-community/windows_exporter/collector/netframework_clrremoting.go new file mode 100644 index 000000000000..9da318a72714 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/netframework_clrremoting.go @@ -0,0 +1,147 @@ +// +build windows + +package collector + +import ( + "github.com/StackExchange/wmi" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +func init() { + registerCollector("netframework_clrremoting", NewNETFramework_NETCLRRemotingCollector) +} + +// A NETFramework_NETCLRRemotingCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRRemoting metrics +type NETFramework_NETCLRRemotingCollector struct { + Channels *prometheus.Desc + ContextBoundClassesLoaded *prometheus.Desc + ContextBoundObjects *prometheus.Desc + ContextProxies *prometheus.Desc + Contexts *prometheus.Desc + TotalRemoteCalls *prometheus.Desc +} + +// NewNETFramework_NETCLRRemotingCollector ... +func NewNETFramework_NETCLRRemotingCollector() (Collector, error) { + const subsystem = "netframework_clrremoting" + return &NETFramework_NETCLRRemotingCollector{ + Channels: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "channels_total"), + "Displays the total number of remoting channels registered across all application domains since application started.", + []string{"process"}, + nil, + ), + ContextBoundClassesLoaded: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "context_bound_classes_loaded"), + "Displays the current number of context-bound classes that are loaded.", + []string{"process"}, + nil, + ), + ContextBoundObjects: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "context_bound_objects_total"), + "Displays the total number of context-bound objects allocated.", + []string{"process"}, + nil, + ), + ContextProxies: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "context_proxies_total"), + "Displays the total number of remoting proxy objects in this process since it started.", + []string{"process"}, + nil, + ), + Contexts: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "contexts"), + "Displays the current number of remoting contexts in the application.", + []string{"process"}, + nil, + ), + TotalRemoteCalls: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "remote_calls_total"), + "Displays the total number of remote procedure calls invoked since the application started.", + []string{"process"}, + nil, + ), + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *NETFramework_NETCLRRemotingCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + log.Error("failed collecting win32_perfrawdata_netframework_netclrremoting metrics:", desc, err) + return err + } + return nil +} + +type Win32_PerfRawData_NETFramework_NETCLRRemoting struct { + Name string + + Channels uint32 + ContextBoundClassesLoaded uint32 + ContextBoundObjectsAllocPersec uint32 + ContextProxies uint32 + Contexts uint32 + RemoteCallsPersec uint32 + TotalRemoteCalls uint32 +} + +func (c *NETFramework_NETCLRRemotingCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_NETFramework_NETCLRRemoting + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, process := range dst { + + if process.Name == "_Global_" { + continue + } + + ch <- prometheus.MustNewConstMetric( + c.Channels, + prometheus.CounterValue, + float64(process.Channels), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.ContextBoundClassesLoaded, + prometheus.GaugeValue, + float64(process.ContextBoundClassesLoaded), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.ContextBoundObjects, + prometheus.CounterValue, + float64(process.ContextBoundObjectsAllocPersec), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.ContextProxies, + prometheus.CounterValue, + float64(process.ContextProxies), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.Contexts, + prometheus.GaugeValue, + float64(process.Contexts), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TotalRemoteCalls, + prometheus.CounterValue, + float64(process.TotalRemoteCalls), + process.Name, + ) + } + + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/netframework_clrsecurity.go b/vendor/github.com/prometheus-community/windows_exporter/collector/netframework_clrsecurity.go new file mode 100644 index 000000000000..1ea0ded15050 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/netframework_clrsecurity.go @@ -0,0 +1,118 @@ +// +build windows + +package collector + +import ( + "github.com/StackExchange/wmi" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +func init() { + registerCollector("netframework_clrsecurity", NewNETFramework_NETCLRSecurityCollector) +} + +// A NETFramework_NETCLRSecurityCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRSecurity metrics +type NETFramework_NETCLRSecurityCollector struct { + NumberLinkTimeChecks *prometheus.Desc + TimeinRTchecks *prometheus.Desc + StackWalkDepth *prometheus.Desc + TotalRuntimeChecks *prometheus.Desc +} + +// NewNETFramework_NETCLRSecurityCollector ... +func NewNETFramework_NETCLRSecurityCollector() (Collector, error) { + const subsystem = "netframework_clrsecurity" + return &NETFramework_NETCLRSecurityCollector{ + NumberLinkTimeChecks: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "link_time_checks_total"), + "Displays the total number of link-time code access security checks since the application started.", + []string{"process"}, + nil, + ), + TimeinRTchecks: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "rt_checks_time_percent"), + "Displays the percentage of time spent performing runtime code access security checks in the last sample.", + []string{"process"}, + nil, + ), + StackWalkDepth: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "stack_walk_depth"), + "Displays the depth of the stack during that last runtime code access security check.", + []string{"process"}, + nil, + ), + TotalRuntimeChecks: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "runtime_checks_total"), + "Displays the total number of runtime code access security checks performed since the application started.", + []string{"process"}, + nil, + ), + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *NETFramework_NETCLRSecurityCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + log.Error("failed collecting win32_perfrawdata_netframework_netclrsecurity metrics:", desc, err) + return err + } + return nil +} + +type Win32_PerfRawData_NETFramework_NETCLRSecurity struct { + Name string + + Frequency_PerfTime uint32 + NumberLinkTimeChecks uint32 + PercentTimeinRTchecks uint32 + PercentTimeSigAuthenticating uint64 + StackWalkDepth uint32 + TotalRuntimeChecks uint32 +} + +func (c *NETFramework_NETCLRSecurityCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_NETFramework_NETCLRSecurity + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, process := range dst { + + if process.Name == "_Global_" { + continue + } + + ch <- prometheus.MustNewConstMetric( + c.NumberLinkTimeChecks, + prometheus.CounterValue, + float64(process.NumberLinkTimeChecks), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TimeinRTchecks, + prometheus.GaugeValue, + float64(process.PercentTimeinRTchecks)/float64(process.Frequency_PerfTime), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.StackWalkDepth, + prometheus.GaugeValue, + float64(process.StackWalkDepth), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TotalRuntimeChecks, + prometheus.CounterValue, + float64(process.TotalRuntimeChecks), + process.Name, + ) + } + + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/os.go b/vendor/github.com/prometheus-community/windows_exporter/collector/os.go new file mode 100644 index 000000000000..45486acee824 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/os.go @@ -0,0 +1,246 @@ +// +build windows + +package collector + +import ( + "errors" + "time" + + "github.com/StackExchange/wmi" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +func init() { + registerCollector("os", NewOSCollector) +} + +// A OSCollector is a Prometheus collector for WMI metrics +type OSCollector struct { + OSInformation *prometheus.Desc + PhysicalMemoryFreeBytes *prometheus.Desc + PagingFreeBytes *prometheus.Desc + VirtualMemoryFreeBytes *prometheus.Desc + ProcessesLimit *prometheus.Desc + ProcessMemoryLimitBytes *prometheus.Desc + Processes *prometheus.Desc + Users *prometheus.Desc + PagingLimitBytes *prometheus.Desc + VirtualMemoryBytes *prometheus.Desc + VisibleMemoryBytes *prometheus.Desc + Time *prometheus.Desc + Timezone *prometheus.Desc +} + +// NewOSCollector ... +func NewOSCollector() (Collector, error) { + const subsystem = "os" + + return &OSCollector{ + OSInformation: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "info"), + "OperatingSystem.Caption, OperatingSystem.Version", + []string{"product", "version"}, + nil, + ), + PagingLimitBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "paging_limit_bytes"), + "OperatingSystem.SizeStoredInPagingFiles", + nil, + nil, + ), + PagingFreeBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "paging_free_bytes"), + "OperatingSystem.FreeSpaceInPagingFiles", + nil, + nil, + ), + PhysicalMemoryFreeBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "physical_memory_free_bytes"), + "OperatingSystem.FreePhysicalMemory", + nil, + nil, + ), + Time: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "time"), + "OperatingSystem.LocalDateTime", + nil, + nil, + ), + Timezone: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "timezone"), + "OperatingSystem.LocalDateTime", + []string{"timezone"}, + nil, + ), + Processes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "processes"), + "OperatingSystem.NumberOfProcesses", + nil, + nil, + ), + ProcessesLimit: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "processes_limit"), + "OperatingSystem.MaxNumberOfProcesses", + nil, + nil, + ), + ProcessMemoryLimitBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "process_memory_limix_bytes"), + "OperatingSystem.MaxProcessMemorySize", + nil, + nil, + ), + Users: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "users"), + "OperatingSystem.NumberOfUsers", + nil, + nil, + ), + VirtualMemoryBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "virtual_memory_bytes"), + "OperatingSystem.TotalVirtualMemorySize", + nil, + nil, + ), + VisibleMemoryBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "visible_memory_bytes"), + "OperatingSystem.TotalVisibleMemorySize", + nil, + nil, + ), + VirtualMemoryFreeBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "virtual_memory_free_bytes"), + "OperatingSystem.FreeVirtualMemory", + nil, + nil, + ), + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *OSCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + log.Error("failed collecting os metrics:", desc, err) + return err + } + return nil +} + +// Win32_OperatingSystem docs: +// - https://msdn.microsoft.com/en-us/library/aa394239 - Win32_OperatingSystem class +type Win32_OperatingSystem struct { + Caption string + FreePhysicalMemory uint64 + FreeSpaceInPagingFiles uint64 + FreeVirtualMemory uint64 + LocalDateTime time.Time + MaxNumberOfProcesses uint32 + MaxProcessMemorySize uint64 + NumberOfProcesses uint32 + NumberOfUsers uint32 + SizeStoredInPagingFiles uint64 + TotalVirtualMemorySize uint64 + TotalVisibleMemorySize uint64 + Version string +} + +func (c *OSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_OperatingSystem + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + if len(dst) == 0 { + return nil, errors.New("WMI query returned empty result set") + } + + ch <- prometheus.MustNewConstMetric( + c.OSInformation, + prometheus.GaugeValue, + 1.0, + dst[0].Caption, + dst[0].Version, + ) + + ch <- prometheus.MustNewConstMetric( + c.PhysicalMemoryFreeBytes, + prometheus.GaugeValue, + float64(dst[0].FreePhysicalMemory*1024), // KiB -> bytes + ) + + time := dst[0].LocalDateTime + + ch <- prometheus.MustNewConstMetric( + c.Time, + prometheus.GaugeValue, + float64(time.Unix()), + ) + + timezoneName, _ := time.Zone() + + ch <- prometheus.MustNewConstMetric( + c.Timezone, + prometheus.GaugeValue, + 1.0, + timezoneName, + ) + + ch <- prometheus.MustNewConstMetric( + c.PagingFreeBytes, + prometheus.GaugeValue, + float64(dst[0].FreeSpaceInPagingFiles*1024), // KiB -> bytes + ) + + ch <- prometheus.MustNewConstMetric( + c.VirtualMemoryFreeBytes, + prometheus.GaugeValue, + float64(dst[0].FreeVirtualMemory*1024), // KiB -> bytes + ) + + ch <- prometheus.MustNewConstMetric( + c.ProcessesLimit, + prometheus.GaugeValue, + float64(dst[0].MaxNumberOfProcesses), + ) + + ch <- prometheus.MustNewConstMetric( + c.ProcessMemoryLimitBytes, + prometheus.GaugeValue, + float64(dst[0].MaxProcessMemorySize*1024), // KiB -> bytes + ) + + ch <- prometheus.MustNewConstMetric( + c.Processes, + prometheus.GaugeValue, + float64(dst[0].NumberOfProcesses), + ) + + ch <- prometheus.MustNewConstMetric( + c.Users, + prometheus.GaugeValue, + float64(dst[0].NumberOfUsers), + ) + + ch <- prometheus.MustNewConstMetric( + c.PagingLimitBytes, + prometheus.GaugeValue, + float64(dst[0].SizeStoredInPagingFiles*1024), // KiB -> bytes + ) + + ch <- prometheus.MustNewConstMetric( + c.VirtualMemoryBytes, + prometheus.GaugeValue, + float64(dst[0].TotalVirtualMemorySize*1024), // KiB -> bytes + ) + + ch <- prometheus.MustNewConstMetric( + c.VisibleMemoryBytes, + prometheus.GaugeValue, + float64(dst[0].TotalVisibleMemorySize*1024), // KiB -> bytes + ) + + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/perflib.go b/vendor/github.com/prometheus-community/windows_exporter/collector/perflib.go new file mode 100644 index 000000000000..19ce2ad7d8ee --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/perflib.go @@ -0,0 +1,107 @@ +package collector + +import ( + "fmt" + "reflect" + "strconv" + + perflibCollector "github.com/leoluk/perflib_exporter/collector" + "github.com/leoluk/perflib_exporter/perflib" + "github.com/prometheus/common/log" +) + +var nametable = perflib.QueryNameTable("Counter 009") // Reads the names in English TODO: validate that the English names are always present + +func MapCounterToIndex(name string) string { + return strconv.Itoa(int(nametable.LookupIndex(name))) +} + +func getPerflibSnapshot(objNames string) (map[string]*perflib.PerfObject, error) { + objects, err := perflib.QueryPerformanceData(objNames) + if err != nil { + return nil, err + } + + indexed := make(map[string]*perflib.PerfObject) + for _, obj := range objects { + indexed[obj.Name] = obj + } + return indexed, nil +} + +func unmarshalObject(obj *perflib.PerfObject, vs interface{}) error { + if obj == nil { + return fmt.Errorf("counter not found") + } + rv := reflect.ValueOf(vs) + if rv.Kind() != reflect.Ptr || rv.IsNil() { + return fmt.Errorf("%v is nil or not a pointer to slice", reflect.TypeOf(vs)) + } + ev := rv.Elem() + if ev.Kind() != reflect.Slice { + return fmt.Errorf("%v is not slice", reflect.TypeOf(vs)) + } + + // Ensure sufficient length + if ev.Cap() < len(obj.Instances) { + nvs := reflect.MakeSlice(ev.Type(), len(obj.Instances), len(obj.Instances)) + ev.Set(nvs) + } + + for idx, instance := range obj.Instances { + target := ev.Index(idx) + rt := target.Type() + + counters := make(map[string]*perflib.PerfCounter, len(instance.Counters)) + for _, ctr := range instance.Counters { + if ctr.Def.IsBaseValue && !ctr.Def.IsNanosecondCounter { + counters[ctr.Def.Name+"_Base"] = ctr + } else { + counters[ctr.Def.Name] = ctr + } + } + + for i := 0; i < target.NumField(); i++ { + f := rt.Field(i) + tag := f.Tag.Get("perflib") + if tag == "" { + continue + } + + ctr, found := counters[tag] + if !found { + log.Debugf("missing counter %q, have %v", tag, counterMapKeys(counters)) + continue + } + if !target.Field(i).CanSet() { + return fmt.Errorf("tagged field %v cannot be written to", f.Name) + } + if fieldType := target.Field(i).Type(); fieldType != reflect.TypeOf((*float64)(nil)).Elem() { + return fmt.Errorf("tagged field %v has wrong type %v, must be float64", f.Name, fieldType) + } + + switch ctr.Def.CounterType { + case perflibCollector.PERF_ELAPSED_TIME: + target.Field(i).SetFloat(float64(ctr.Value-windowsEpoch) / float64(obj.Frequency)) + case perflibCollector.PERF_100NSEC_TIMER, perflibCollector.PERF_PRECISION_100NS_TIMER: + target.Field(i).SetFloat(float64(ctr.Value) * ticksToSecondsScaleFactor) + default: + target.Field(i).SetFloat(float64(ctr.Value)) + } + } + + if instance.Name != "" && target.FieldByName("Name").CanSet() { + target.FieldByName("Name").SetString(instance.Name) + } + } + + return nil +} + +func counterMapKeys(m map[string]*perflib.PerfCounter) []string { + keys := make([]string, 0, len(m)) + for k := range m { + keys = append(keys, k) + } + return keys +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/process.go b/vendor/github.com/prometheus-community/windows_exporter/collector/process.go new file mode 100644 index 000000000000..df8536918664 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/process.go @@ -0,0 +1,403 @@ +// +build windows + +package collector + +import ( + "fmt" + "regexp" + "strconv" + "strings" + + "github.com/StackExchange/wmi" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" + "gopkg.in/alecthomas/kingpin.v2" +) + +func init() { + registerCollectorWithConfig("process", func() Config { return &ProcessConfig{} }, "Process") +} + +type ProcessConfig struct { + ProcessWhiteList string + ProcessBlackList string +} + +func (p *ProcessConfig) RegisterKingpin(ka *kingpin.Application) { + ka.Flag( + "collector.process.whitelist", + "Regexp of processes to include. Process name must both match whitelist and not match blacklist to be included.", + ).Default(".*").StringVar(&p.ProcessWhiteList) + ka.Flag( + "collector.process.blacklist", + "Regexp of processes to exclude. Process name must both match whitelist and not match blacklist to be included.", + ).Default("").StringVar(&p.ProcessBlackList) +} + +func (p *ProcessConfig) Build() (Collector, error) { + return newProcessCollector(p) +} + +type processCollector struct { + StartTime *prometheus.Desc + CPUTimeTotal *prometheus.Desc + HandleCount *prometheus.Desc + IOBytesTotal *prometheus.Desc + IOOperationsTotal *prometheus.Desc + PageFaultsTotal *prometheus.Desc + PageFileBytes *prometheus.Desc + PoolBytes *prometheus.Desc + PriorityBase *prometheus.Desc + PrivateBytes *prometheus.Desc + ThreadCount *prometheus.Desc + VirtualBytes *prometheus.Desc + WorkingSet *prometheus.Desc + + processWhitelistPattern *regexp.Regexp + processBlacklistPattern *regexp.Regexp +} + +// NewProcessCollector ... +func newProcessCollector(p *ProcessConfig) (Collector, error) { + const subsystem = "process" + + if p.ProcessWhiteList == ".*" && p.ProcessBlackList == "" { + log.Warn("No filters specified for process collector. This will generate a very large number of metrics!") + } + + return &processCollector{ + StartTime: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "start_time"), + "Time of process start.", + []string{"process", "process_id", "creating_process_id"}, + nil, + ), + CPUTimeTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "cpu_time_total"), + "Returns elapsed time that all of the threads of this process used the processor to execute instructions by mode (privileged, user). An instruction is the basic unit of execution in a computer, a thread is the object that executes instructions, and a process is the object created when a program is run. Code executed to handle some hardware interrupts and trap conditions is included in this count.", + []string{"process", "process_id", "creating_process_id", "mode"}, + nil, + ), + HandleCount: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "handle_count"), + "Total number of handles the process has open. This number is the sum of the handles currently open by each thread in the process.", + []string{"process", "process_id", "creating_process_id"}, + nil, + ), + IOBytesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "io_bytes_total"), + "Bytes issued to I/O operations in different modes (read, write, other). This property counts all I/O activity generated by the process to include file, network, and device I/Os. Read and write mode includes data operations; other mode includes those that do not involve data, such as control operations. ", + []string{"process", "process_id", "creating_process_id", "mode"}, + nil, + ), + IOOperationsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "io_operations_total"), + "I/O operations issued in different modes (read, write, other). This property counts all I/O activity generated by the process to include file, network, and device I/Os. Read and write mode includes data operations; other mode includes those that do not involve data, such as control operations. ", + []string{"process", "process_id", "creating_process_id", "mode"}, + nil, + ), + PageFaultsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "page_faults_total"), + "Page faults by the threads executing in this process. A page fault occurs when a thread refers to a virtual memory page that is not in its working set in main memory. This can cause the page not to be fetched from disk if it is on the standby list and hence already in main memory, or if it is in use by another process with which the page is shared.", + []string{"process", "process_id", "creating_process_id"}, + nil, + ), + PageFileBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "page_file_bytes"), + "Current number of bytes this process has used in the paging file(s). Paging files are used to store pages of memory used by the process that are not contained in other files. Paging files are shared by all processes, and lack of space in paging files can prevent other processes from allocating memory.", + []string{"process", "process_id", "creating_process_id"}, + nil, + ), + PoolBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "pool_bytes"), + "Pool Bytes is the last observed number of bytes in the paged or nonpaged pool. The nonpaged pool is an area of system memory (physical memory used by the operating system) for objects that cannot be written to disk, but must remain in physical memory as long as they are allocated. The paged pool is an area of system memory (physical memory used by the operating system) for objects that can be written to disk when they are not being used. Nonpaged pool bytes is calculated differently than paged pool bytes, so it might not equal the total of paged pool bytes.", + []string{"process", "process_id", "creating_process_id", "pool"}, + nil, + ), + PriorityBase: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "priority_base"), + "Current base priority of this process. Threads within a process can raise and lower their own base priority relative to the process base priority of the process.", + []string{"process", "process_id", "creating_process_id"}, + nil, + ), + PrivateBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "private_bytes"), + "Current number of bytes this process has allocated that cannot be shared with other processes.", + []string{"process", "process_id", "creating_process_id"}, + nil, + ), + ThreadCount: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "thread_count"), + "Number of threads currently active in this process. An instruction is the basic unit of execution in a processor, and a thread is the object that executes instructions. Every running process has at least one thread.", + []string{"process", "process_id", "creating_process_id"}, + nil, + ), + VirtualBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "virtual_bytes"), + "Current size, in bytes, of the virtual address space that the process is using. Use of virtual address space does not necessarily imply corresponding use of either disk or main memory pages. Virtual space is finite and, by using too much, the process can limit its ability to load libraries.", + []string{"process", "process_id", "creating_process_id"}, + nil, + ), + WorkingSet: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "working_set"), + "Maximum number of bytes in the working set of this process at any point in time. The working set is the set of memory pages touched recently by the threads in the process. If free memory in the computer is above a threshold, pages are left in the working set of a process even if they are not in use. When free memory falls below a threshold, pages are trimmed from working sets. If they are needed, they are then soft-faulted back into the working set before they leave main memory.", + []string{"process", "process_id", "creating_process_id"}, + nil, + ), + processWhitelistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", p.ProcessWhiteList)), + processBlacklistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", p.ProcessBlackList)), + }, nil +} + +type perflibProcess struct { + Name string + PercentProcessorTime float64 `perflib:"% Processor Time"` + PercentPrivilegedTime float64 `perflib:"% Privileged Time"` + PercentUserTime float64 `perflib:"% User Time"` + CreatingProcessID float64 `perflib:"Creating Process ID"` + ElapsedTime float64 `perflib:"Elapsed Time"` + HandleCount float64 `perflib:"Handle Count"` + IDProcess float64 `perflib:"ID Process"` + IODataBytesPerSec float64 `perflib:"IO Data Bytes/sec"` + IODataOperationsPerSec float64 `perflib:"IO Data Operations/sec"` + IOOtherBytesPerSec float64 `perflib:"IO Other Bytes/sec"` + IOOtherOperationsPerSec float64 `perflib:"IO Other Operations/sec"` + IOReadBytesPerSec float64 `perflib:"IO Read Bytes/sec"` + IOReadOperationsPerSec float64 `perflib:"IO Read Operations/sec"` + IOWriteBytesPerSec float64 `perflib:"IO Write Bytes/sec"` + IOWriteOperationsPerSec float64 `perflib:"IO Write Operations/sec"` + PageFaultsPerSec float64 `perflib:"Page Faults/sec"` + PageFileBytesPeak float64 `perflib:"Page File Bytes Peak"` + PageFileBytes float64 `perflib:"Page File Bytes"` + PoolNonpagedBytes float64 `perflib:"Pool Nonpaged Bytes"` + PoolPagedBytes float64 `perflib:"Pool Paged Bytes"` + PriorityBase float64 `perflib:"Priority Base"` + PrivateBytes float64 `perflib:"Private Bytes"` + ThreadCount float64 `perflib:"Thread Count"` + VirtualBytesPeak float64 `perflib:"Virtual Bytes Peak"` + VirtualBytes float64 `perflib:"Virtual Bytes"` + WorkingSetPrivate float64 `perflib:"Working Set - Private"` + WorkingSetPeak float64 `perflib:"Working Set Peak"` + WorkingSet float64 `perflib:"Working Set"` +} + +type WorkerProcess struct { + AppPoolName string + ProcessId uint64 +} + +func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + data := make([]perflibProcess, 0) + err := unmarshalObject(ctx.perfObjects["Process"], &data) + if err != nil { + return err + } + + var dst_wp []WorkerProcess + q_wp := queryAll(&dst_wp) + if err := wmi.QueryNamespace(q_wp, &dst_wp, "root\\WebAdministration"); err != nil { + log.Debugf("Could not query WebAdministration namespace for IIS worker processes: %v. Skipping", err) + } + + for _, process := range data { + if process.Name == "_Total" || + c.processBlacklistPattern.MatchString(process.Name) || + !c.processWhitelistPattern.MatchString(process.Name) { + continue + } + // Duplicate processes are suffixed # and an index number. Remove those. + processName := strings.Split(process.Name, "#")[0] + pid := strconv.FormatUint(uint64(process.IDProcess), 10) + cpid := strconv.FormatUint(uint64(process.CreatingProcessID), 10) + + for _, wp := range dst_wp { + if wp.ProcessId == uint64(process.IDProcess) { + processName = strings.Join([]string{processName, wp.AppPoolName}, "_") + break + } + } + + ch <- prometheus.MustNewConstMetric( + c.StartTime, + prometheus.GaugeValue, + process.ElapsedTime, + processName, + pid, + cpid, + ) + + ch <- prometheus.MustNewConstMetric( + c.HandleCount, + prometheus.GaugeValue, + process.HandleCount, + processName, + pid, + cpid, + ) + + ch <- prometheus.MustNewConstMetric( + c.CPUTimeTotal, + prometheus.CounterValue, + process.PercentPrivilegedTime, + processName, + pid, + cpid, + "privileged", + ) + + ch <- prometheus.MustNewConstMetric( + c.CPUTimeTotal, + prometheus.CounterValue, + process.PercentUserTime, + processName, + pid, + cpid, + "user", + ) + + ch <- prometheus.MustNewConstMetric( + c.IOBytesTotal, + prometheus.CounterValue, + process.IOOtherBytesPerSec, + processName, + pid, + cpid, + "other", + ) + + ch <- prometheus.MustNewConstMetric( + c.IOOperationsTotal, + prometheus.CounterValue, + process.IOOtherOperationsPerSec, + processName, + pid, + cpid, + "other", + ) + + ch <- prometheus.MustNewConstMetric( + c.IOBytesTotal, + prometheus.CounterValue, + process.IOReadBytesPerSec, + processName, + pid, + cpid, + "read", + ) + + ch <- prometheus.MustNewConstMetric( + c.IOOperationsTotal, + prometheus.CounterValue, + process.IOReadOperationsPerSec, + processName, + pid, + cpid, + "read", + ) + + ch <- prometheus.MustNewConstMetric( + c.IOBytesTotal, + prometheus.CounterValue, + process.IOWriteBytesPerSec, + processName, + pid, + cpid, + "write", + ) + + ch <- prometheus.MustNewConstMetric( + c.IOOperationsTotal, + prometheus.CounterValue, + process.IOWriteOperationsPerSec, + processName, + pid, + cpid, + "write", + ) + + ch <- prometheus.MustNewConstMetric( + c.PageFaultsTotal, + prometheus.CounterValue, + process.PageFaultsPerSec, + processName, + pid, + cpid, + ) + + ch <- prometheus.MustNewConstMetric( + c.PageFileBytes, + prometheus.GaugeValue, + process.PageFileBytes, + processName, + pid, + cpid, + ) + + ch <- prometheus.MustNewConstMetric( + c.PoolBytes, + prometheus.GaugeValue, + process.PoolNonpagedBytes, + processName, + pid, + cpid, + "nonpaged", + ) + + ch <- prometheus.MustNewConstMetric( + c.PoolBytes, + prometheus.GaugeValue, + process.PoolPagedBytes, + processName, + pid, + cpid, + "paged", + ) + + ch <- prometheus.MustNewConstMetric( + c.PriorityBase, + prometheus.GaugeValue, + process.PriorityBase, + processName, + pid, + cpid, + ) + + ch <- prometheus.MustNewConstMetric( + c.PrivateBytes, + prometheus.GaugeValue, + process.PrivateBytes, + processName, + pid, + cpid, + ) + + ch <- prometheus.MustNewConstMetric( + c.ThreadCount, + prometheus.GaugeValue, + process.ThreadCount, + processName, + pid, + cpid, + ) + + ch <- prometheus.MustNewConstMetric( + c.VirtualBytes, + prometheus.GaugeValue, + process.VirtualBytes, + processName, + pid, + cpid, + ) + + ch <- prometheus.MustNewConstMetric( + c.WorkingSet, + prometheus.GaugeValue, + process.WorkingSet, + processName, + pid, + cpid, + ) + } + + return nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/remote_fx.go b/vendor/github.com/prometheus-community/windows_exporter/collector/remote_fx.go new file mode 100644 index 000000000000..f81066f7dd43 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/remote_fx.go @@ -0,0 +1,351 @@ +// +build windows + +package collector + +import ( + "strings" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +func init() { + registerCollector("remote_fx", NewRemoteFx, "RemoteFX Network", "RemoteFX Graphics") +} + +// A RemoteFxNetworkCollector is a Prometheus collector for +// WMI Win32_PerfRawData_Counters_RemoteFXNetwork & Win32_PerfRawData_Counters_RemoteFXGraphics metrics +// https://wutils.com/wmi/root/cimv2/win32_perfrawdata_counters_remotefxnetwork/ +// https://wutils.com/wmi/root/cimv2/win32_perfrawdata_counters_remotefxgraphics/ + +type RemoteFxCollector struct { + // net + BaseTCPRTT *prometheus.Desc + BaseUDPRTT *prometheus.Desc + CurrentTCPBandwidth *prometheus.Desc + CurrentTCPRTT *prometheus.Desc + CurrentUDPBandwidth *prometheus.Desc + CurrentUDPRTT *prometheus.Desc + TotalReceivedBytes *prometheus.Desc + TotalSentBytes *prometheus.Desc + UDPPacketsReceivedPersec *prometheus.Desc + UDPPacketsSentPersec *prometheus.Desc + + //gfx + AverageEncodingTime *prometheus.Desc + FrameQuality *prometheus.Desc + FramesSkippedPerSecondInsufficientResources *prometheus.Desc + GraphicsCompressionratio *prometheus.Desc + InputFramesPerSecond *prometheus.Desc + OutputFramesPerSecond *prometheus.Desc + SourceFramesPerSecond *prometheus.Desc +} + +// NewRemoteFx ... +func NewRemoteFx() (Collector, error) { + const subsystem = "remote_fx" + return &RemoteFxCollector{ + // net + BaseTCPRTT: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "net_base_tcp_rtt_seconds"), + "Base TCP round-trip time (RTT) detected in seconds", + []string{"session_name"}, + nil, + ), + BaseUDPRTT: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "net_base_udp_rtt_seconds"), + "Base UDP round-trip time (RTT) detected in seconds.", + []string{"session_name"}, + nil, + ), + CurrentTCPBandwidth: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "net_current_tcp_bandwidth"), + "TCP Bandwidth detected in bytes per seccond.", + []string{"session_name"}, + nil, + ), + CurrentTCPRTT: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "net_current_tcp_rtt_seconds"), + "Average TCP round-trip time (RTT) detected in seconds.", + []string{"session_name"}, + nil, + ), + CurrentUDPBandwidth: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "net_current_udp_bandwidth"), + "UDP Bandwidth detected in bytes per second.", + []string{"session_name"}, + nil, + ), + CurrentUDPRTT: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "net_current_udp_rtt_seconds"), + "Average UDP round-trip time (RTT) detected in seconds.", + []string{"session_name"}, + nil, + ), + TotalReceivedBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "net_received_bytes_total"), + "(TotalReceivedBytes)", + []string{"session_name"}, + nil, + ), + TotalSentBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "net_sent_bytes_total"), + "(TotalSentBytes)", + []string{"session_name"}, + nil, + ), + UDPPacketsReceivedPersec: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "net_udp_packets_received_total"), + "Rate in packets per second at which packets are received over UDP.", + []string{"session_name"}, + nil, + ), + UDPPacketsSentPersec: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "net_udp_packets_sent_total"), + "Rate in packets per second at which packets are sent over UDP.", + []string{"session_name"}, + nil, + ), + + //gfx + AverageEncodingTime: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "gfx_average_encoding_time_seconds"), + "Average frame encoding time in seconds", + []string{"session_name"}, + nil, + ), + FrameQuality: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "gfx_frame_quality"), + "Quality of the output frame expressed as a percentage of the quality of the source frame.", + []string{"session_name"}, + nil, + ), + FramesSkippedPerSecondInsufficientResources: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "gfx_frames_skipped_insufficient_resource_total"), + "Number of frames skipped per second due to insufficient client resources.", + []string{"session_name", "resource"}, + nil, + ), + GraphicsCompressionratio: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "gfx_graphics_compression_ratio"), + "Ratio of the number of bytes encoded to the number of bytes input.", + []string{"session_name"}, + nil, + ), + InputFramesPerSecond: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "gfx_input_frames_total"), + "Number of sources frames provided as input to RemoteFX graphics per second.", + []string{"session_name"}, + nil, + ), + OutputFramesPerSecond: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "gfx_output_frames_total"), + "Number of frames sent to the client per second.", + []string{"session_name"}, + nil, + ), + SourceFramesPerSecond: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "gfx_source_frames_total"), + "Number of frames composed by the source (DWM) per second.", + []string{"session_name"}, + nil, + ), + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *RemoteFxCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collectRemoteFXNetworkCount(ctx, ch); err != nil { + log.Error("failed collecting terminal services session count metrics:", desc, err) + return err + } + if desc, err := c.collectRemoteFXGraphicsCounters(ctx, ch); err != nil { + log.Error("failed collecting terminal services session count metrics:", desc, err) + return err + } + return nil +} + +type perflibRemoteFxNetwork struct { + Name string + BaseTCPRTT float64 `perflib:"Base TCP RTT"` + BaseUDPRTT float64 `perflib:"Base UDP RTT"` + CurrentTCPBandwidth float64 `perflib:"Current TCP Bandwidth"` + CurrentTCPRTT float64 `perflib:"Current TCP RTT"` + CurrentUDPBandwidth float64 `perflib:"Current UDP Bandwidth"` + CurrentUDPRTT float64 `perflib:"Current UDP RTT"` + TotalReceivedBytes float64 `perflib:"Total Received Bytes"` + TotalSentBytes float64 `perflib:"Total Sent Bytes"` + UDPPacketsReceivedPersec float64 `perflib:"UDP Packets Received/sec"` + UDPPacketsSentPersec float64 `perflib:"UDP Packets Sent/sec"` +} + +func (c *RemoteFxCollector) collectRemoteFXNetworkCount(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + dst := make([]perflibRemoteFxNetwork, 0) + err := unmarshalObject(ctx.perfObjects["RemoteFX Network"], &dst) + if err != nil { + return nil, err + } + + for _, d := range dst { + // only connect metrics for remote named sessions + n := strings.ToLower(d.Name) + if n == "" || n == "services" || n == "console" { + continue + } + ch <- prometheus.MustNewConstMetric( + c.BaseTCPRTT, + prometheus.GaugeValue, + milliSecToSec(d.BaseTCPRTT), + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.BaseUDPRTT, + prometheus.GaugeValue, + milliSecToSec(d.BaseUDPRTT), + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.CurrentTCPBandwidth, + prometheus.GaugeValue, + (d.CurrentTCPBandwidth*1000)/8, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.CurrentTCPRTT, + prometheus.GaugeValue, + milliSecToSec(d.CurrentTCPRTT), + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.CurrentUDPBandwidth, + prometheus.GaugeValue, + (d.CurrentUDPBandwidth*1000)/8, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.CurrentUDPRTT, + prometheus.GaugeValue, + milliSecToSec(d.CurrentUDPRTT), + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.TotalReceivedBytes, + prometheus.CounterValue, + d.TotalReceivedBytes, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.TotalSentBytes, + prometheus.CounterValue, + d.TotalSentBytes, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.UDPPacketsReceivedPersec, + prometheus.CounterValue, + d.UDPPacketsReceivedPersec, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.UDPPacketsSentPersec, + prometheus.CounterValue, + d.UDPPacketsSentPersec, + d.Name, + ) + } + return nil, nil +} + +type perflibRemoteFxGraphics struct { + Name string + AverageEncodingTime float64 `perflib:"Average Encoding Time"` + FrameQuality float64 `perflib:"Frame Quality"` + FramesSkippedPerSecondInsufficientClientResources float64 `perflib:"Frames Skipped/Second - Insufficient Server Resources"` + FramesSkippedPerSecondInsufficientNetworkResources float64 `perflib:"Frames Skipped/Second - Insufficient Network Resources"` + FramesSkippedPerSecondInsufficientServerResources float64 `perflib:"Frames Skipped/Second - Insufficient Client Resources"` + GraphicsCompressionratio float64 `perflib:"Graphics Compression ratio"` + InputFramesPerSecond float64 `perflib:"Input Frames/Second"` + OutputFramesPerSecond float64 `perflib:"Output Frames/Second"` + SourceFramesPerSecond float64 `perflib:"Source Frames/Second"` +} + +func (c *RemoteFxCollector) collectRemoteFXGraphicsCounters(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + dst := make([]perflibRemoteFxGraphics, 0) + err := unmarshalObject(ctx.perfObjects["RemoteFX Graphics"], &dst) + if err != nil { + return nil, err + } + + for _, d := range dst { + // only connect metrics for remote named sessions + n := strings.ToLower(d.Name) + if n == "" || n == "services" || n == "console" { + continue + } + ch <- prometheus.MustNewConstMetric( + c.AverageEncodingTime, + prometheus.GaugeValue, + milliSecToSec(d.AverageEncodingTime), + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.FrameQuality, + prometheus.GaugeValue, + d.FrameQuality, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.FramesSkippedPerSecondInsufficientResources, + prometheus.CounterValue, + d.FramesSkippedPerSecondInsufficientClientResources, + d.Name, + "client", + ) + ch <- prometheus.MustNewConstMetric( + c.FramesSkippedPerSecondInsufficientResources, + prometheus.CounterValue, + d.FramesSkippedPerSecondInsufficientNetworkResources, + d.Name, + "network", + ) + ch <- prometheus.MustNewConstMetric( + c.FramesSkippedPerSecondInsufficientResources, + prometheus.CounterValue, + d.FramesSkippedPerSecondInsufficientServerResources, + d.Name, + "server", + ) + ch <- prometheus.MustNewConstMetric( + c.GraphicsCompressionratio, + prometheus.GaugeValue, + d.GraphicsCompressionratio, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.InputFramesPerSecond, + prometheus.CounterValue, + d.InputFramesPerSecond, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.OutputFramesPerSecond, + prometheus.CounterValue, + d.OutputFramesPerSecond, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.SourceFramesPerSecond, + prometheus.CounterValue, + d.SourceFramesPerSecond, + d.Name, + ) + } + + return nil, nil +} + +func milliSecToSec(t float64) float64 { + return t / 1000 +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/service.go b/vendor/github.com/prometheus-community/windows_exporter/collector/service.go new file mode 100644 index 000000000000..aa8de4b1c09a --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/service.go @@ -0,0 +1,203 @@ +// +build windows + +package collector + +import ( + "strconv" + "strings" + + "github.com/StackExchange/wmi" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" + "gopkg.in/alecthomas/kingpin.v2" +) + +func init() { + registerCollectorWithConfig("service", func() Config { return &ServiceConfig{} }) +} + +type ServiceConfig struct { + ServiceWhereClause string +} + +func (s *ServiceConfig) RegisterKingpin(ka *kingpin.Application) { + ka.Flag( + "collector.service.services-where", + "WQL 'where' clause to use in WMI metrics query. Limits the response to the services you specify and reduces the size of the response.", + ).Default("").StringVar(&s.ServiceWhereClause) +} + +func (s *ServiceConfig) Build() (Collector, error) { + return NewserviceCollector(s) +} + +// A serviceCollector is a Prometheus collector for WMI Win32_Service metrics +type serviceCollector struct { + Information *prometheus.Desc + State *prometheus.Desc + StartMode *prometheus.Desc + Status *prometheus.Desc + + queryWhereClause string +} + +// NewserviceCollector ... +func NewserviceCollector(s *ServiceConfig) (Collector, error) { + const subsystem = "service" + + if s.ServiceWhereClause == "" { + log.Warn("No where-clause specified for service collector. This will generate a very large number of metrics!") + } + + return &serviceCollector{ + Information: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "info"), + "A metric with a constant '1' value labeled with service information", + []string{"name", "display_name", "process_id", "run_as"}, + nil, + ), + State: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "state"), + "The state of the service (State)", + []string{"name", "state"}, + nil, + ), + StartMode: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "start_mode"), + "The start mode of the service (StartMode)", + []string{"name", "start_mode"}, + nil, + ), + Status: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "status"), + "The status of the service (Status)", + []string{"name", "status"}, + nil, + ), + queryWhereClause: s.ServiceWhereClause, + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *serviceCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + log.Error("failed collecting service metrics:", desc, err) + return err + } + return nil +} + +// Win32_Service docs: +// - https://msdn.microsoft.com/en-us/library/aa394418(v=vs.85).aspx +type Win32_Service struct { + DisplayName string + Name string + ProcessId uint32 + State string + Status string + StartMode string + StartName *string +} + +var ( + allStates = []string{ + "stopped", + "start pending", + "stop pending", + "running", + "continue pending", + "pause pending", + "paused", + "unknown", + } + allStartModes = []string{ + "boot", + "system", + "auto", + "manual", + "disabled", + } + allStatuses = []string{ + "ok", + "error", + "degraded", + "unknown", + "pred fail", + "starting", + "stopping", + "service", + "stressed", + "nonrecover", + "no contact", + "lost comm", + } +) + +func (c *serviceCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_Service + q := queryAllWhere(&dst, c.queryWhereClause) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + for _, service := range dst { + pid := strconv.FormatUint(uint64(service.ProcessId), 10) + + runAs := "" + if service.StartName != nil { + runAs = *service.StartName + } + ch <- prometheus.MustNewConstMetric( + c.Information, + prometheus.GaugeValue, + 1.0, + strings.ToLower(service.Name), + service.DisplayName, + pid, + runAs, + ) + + for _, state := range allStates { + isCurrentState := 0.0 + if state == strings.ToLower(service.State) { + isCurrentState = 1.0 + } + ch <- prometheus.MustNewConstMetric( + c.State, + prometheus.GaugeValue, + isCurrentState, + strings.ToLower(service.Name), + state, + ) + } + + for _, startMode := range allStartModes { + isCurrentStartMode := 0.0 + if startMode == strings.ToLower(service.StartMode) { + isCurrentStartMode = 1.0 + } + ch <- prometheus.MustNewConstMetric( + c.StartMode, + prometheus.GaugeValue, + isCurrentStartMode, + strings.ToLower(service.Name), + startMode, + ) + } + + for _, status := range allStatuses { + isCurrentStatus := 0.0 + if status == strings.ToLower(service.Status) { + isCurrentStatus = 1.0 + } + ch <- prometheus.MustNewConstMetric( + c.Status, + prometheus.GaugeValue, + isCurrentStatus, + strings.ToLower(service.Name), + status, + ) + } + } + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/smtp.go b/vendor/github.com/prometheus-community/windows_exporter/collector/smtp.go new file mode 100644 index 000000000000..b26eb92f63a0 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/smtp.go @@ -0,0 +1,708 @@ +// +build windows + +package collector + +import ( + "fmt" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" + "gopkg.in/alecthomas/kingpin.v2" + "regexp" +) + +func init() { + log.Info("smtp collector is in an experimental state! Metrics for this collector have not been tested.") + registerCollectorWithConfig("smtp", func() Config { return &SMTPConfig{} }, "SMTP Server") +} + +type SMTPConfig struct { + ServerWhiteList string + ServerBlackList string +} + +func (s *SMTPConfig) RegisterKingpin(ka *kingpin.Application) { + ka.Flag( + "collector.smtp.server-whitelist", + "Regexp of virtual servers to whitelist. Server name must both match whitelist and not match blacklist to be included.", + ).Default(".+").StringVar(&s.ServerWhiteList) + ka.Flag( + "collector.smtp.server-blacklist", + "Regexp of virtual servers to blacklist. Server name must both match whitelist and not match blacklist to be included.", + ).StringVar(&s.ServerBlackList) +} + +func (s *SMTPConfig) Build() (Collector, error) { + return NewSMTPCollector(s) +} + +type SMTPCollector struct { + BadmailedMessagesBadPickupFileTotal *prometheus.Desc + BadmailedMessagesGeneralFailureTotal *prometheus.Desc + BadmailedMessagesHopCountExceededTotal *prometheus.Desc + BadmailedMessagesNDROfDSNTotal *prometheus.Desc + BadmailedMessagesNoRecipientsTotal *prometheus.Desc + BadmailedMessagesTriggeredViaEventTotal *prometheus.Desc + BytesSentTotal *prometheus.Desc + BytesReceivedTotal *prometheus.Desc + CategorizerQueueLength *prometheus.Desc + ConnectionErrorsTotal *prometheus.Desc + CurrentMessagesInLocalDelivery *prometheus.Desc + DirectoryDropsTotal *prometheus.Desc + DNSQueriesTotal *prometheus.Desc + DSNFailuresTotal *prometheus.Desc + ETRNMessagesTotal *prometheus.Desc + InboundConnectionsCurrent *prometheus.Desc + InboundConnectionsTotal *prometheus.Desc + LocalQueueLength *prometheus.Desc + LocalRetryQueueLength *prometheus.Desc + MailFilesOpen *prometheus.Desc + MessageBytesReceivedTotal *prometheus.Desc + MessageBytesSentTotal *prometheus.Desc + MessageDeliveryRetriesTotal *prometheus.Desc + MessageSendRetriesTotal *prometheus.Desc + MessagesCurrentlyUndeliverable *prometheus.Desc + MessagesDeliveredTotal *prometheus.Desc + MessagesPendingRouting *prometheus.Desc + MessagesReceivedTotal *prometheus.Desc + MessagesRefusedForAddressObjectsTotal *prometheus.Desc + MessagesRefusedForMailObjectsTotal *prometheus.Desc + MessagesRefusedForSizeTotal *prometheus.Desc + MessagesSentTotal *prometheus.Desc + MessagesSubmittedTotal *prometheus.Desc + NDRsGeneratedTotal *prometheus.Desc + OutboundConnectionsCurrent *prometheus.Desc + OutboundConnectionsRefusedTotal *prometheus.Desc + OutboundConnectionsTotal *prometheus.Desc + QueueFilesOpen *prometheus.Desc + PickupDirectoryMessagesRetrievedTotal *prometheus.Desc + RemoteQueueLength *prometheus.Desc + RemoteRetryQueueLength *prometheus.Desc + RoutingTableLookupsTotal *prometheus.Desc + + serverWhitelistPattern *regexp.Regexp + serverBlacklistPattern *regexp.Regexp +} + +func NewSMTPCollector(s *SMTPConfig) (Collector, error) { + const subsystem = "smtp" + + return &SMTPCollector{ + BadmailedMessagesBadPickupFileTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "badmailed_messages_bad_pickup_file_total"), + "Total number of malformed pickup messages sent to badmail", + []string{"site"}, + nil, + ), + BadmailedMessagesGeneralFailureTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "badmailed_messages_general_failure_total"), + "Total number of messages sent to badmail for reasons not associated with a specific counter", + []string{"site"}, + nil, + ), + BadmailedMessagesHopCountExceededTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "badmailed_messages_hop_count_exceeded_total"), + "Total number of messages sent to badmail because they had exceeded the maximum hop count", + []string{"site"}, + nil, + ), + BadmailedMessagesNDROfDSNTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "badmailed_messages_ndr_of_dns_total"), + "Total number of Delivery Status Notifications sent to badmail because they could not be delivered", + []string{"site"}, + nil, + ), + BadmailedMessagesNoRecipientsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "badmailed_messages_no_recipients_total"), + "Total number of messages sent to badmail because they had no recipients", + []string{"site"}, + nil, + ), + BadmailedMessagesTriggeredViaEventTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "badmailed_messages_triggered_via_event_total"), + "Total number of messages sent to badmail at the request of a server event sink", + []string{"site"}, + nil, + ), + BytesSentTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bytes_sent_total"), + "Total number of bytes sent", + []string{"site"}, + nil, + ), + BytesReceivedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "bytes_received_total"), + "Total number of bytes received", + []string{"site"}, + nil, + ), + CategorizerQueueLength: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "categorizer_queue_length"), + "Number of messages in the categorizer queue", + []string{"site"}, + nil, + ), + ConnectionErrorsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "connection_errors_total"), + "Total number of connection errors", + []string{"site"}, + nil, + ), + CurrentMessagesInLocalDelivery: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "current_messages_in_local_delivery"), + "Number of messages that are currently being processed by a server event sink for local delivery", + []string{"site"}, + nil, + ), + DirectoryDropsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "directory_drops_total"), + "Total number of messages placed in a drop directory", + []string{"site"}, + nil, + ), + DSNFailuresTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dsn_failures_total"), + "Total number of failed DSN generation attempts", + []string{"site"}, + nil, + ), + DNSQueriesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "dns_queries_total"), + "Total number of DNS lookups", + []string{"site"}, + nil, + ), + ETRNMessagesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "etrn_messages_total"), + "Total number of ETRN messages received by the server", + []string{"site"}, + nil, + ), + InboundConnectionsCurrent: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "inbound_connections_current"), + "Total number of connections currently inbound", + []string{"site"}, + nil, + ), + InboundConnectionsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "inbound_connections_total"), + "Total number of inbound connections received", + []string{"site"}, + nil, + ), + LocalQueueLength: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "local_queue_length"), + "Number of messages in the local queue", + []string{"site"}, + nil, + ), + LocalRetryQueueLength: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "local_retry_queue_length"), + "Number of messages in the local retry queue", + []string{"site"}, + nil, + ), + MailFilesOpen: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "mail_files_open"), + "Number of handles to open mail files", + []string{"site"}, + nil, + ), + MessageBytesReceivedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "message_bytes_received_total"), + "Total number of bytes received in messages", + []string{"site"}, + nil, + ), + MessageBytesSentTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "message_bytes_sent_total"), + "Total number of bytes sent in messages", + []string{"site"}, + nil, + ), + MessageDeliveryRetriesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "message_delivery_retries_total"), + "Total number of local deliveries that were retried", + []string{"site"}, + nil, + ), + MessageSendRetriesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "message_send_retries_total"), + "Total number of outbound message sends that were retried", + []string{"site"}, + nil, + ), + MessagesCurrentlyUndeliverable: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "messages_currently_undeliverable"), + "Number of messages that have been reported as currently undeliverable by routing", + []string{"site"}, + nil, + ), + MessagesDeliveredTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "messages_delivered_total"), + "Total number of messages delivered to local mailboxes", + []string{"site"}, + nil, + ), + MessagesPendingRouting: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "messages_pending_routing"), + "Number of messages that have been categorized but not routed", + []string{"site"}, + nil, + ), + MessagesReceivedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "messages_received_total"), + "Total number of inbound messages accepted", + []string{"site"}, + nil, + ), + MessagesRefusedForAddressObjectsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "messages_refused_for_address_objects_total"), + "Total number of messages refused due to no address objects", + []string{"site"}, + nil, + ), + MessagesRefusedForMailObjectsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "messages_refused_for_mail_objects_total"), + "Total number of messages refused due to no mail objects", + []string{"site"}, + nil, + ), + MessagesRefusedForSizeTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "messages_refused_for_size_total"), + "Total number of messages rejected because they were too big", + []string{"site"}, + nil, + ), + MessagesSentTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "messages_sent_total"), + "Total number of outbound messages sent", + []string{"site"}, + nil, + ), + MessagesSubmittedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "messages_submitted_total"), + "Total number of messages submitted to queuing for delivery", + []string{"site"}, + nil, + ), + NDRsGeneratedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "ndrs_generated_total"), + "Total number of non-delivery reports that have been generated", + []string{"site"}, + nil, + ), + OutboundConnectionsCurrent: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "outbound_connections_current"), + "Number of connections currently outbound", + []string{"site"}, + nil, + ), + OutboundConnectionsRefusedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "outbound_connections_refused_total"), + "Total number of connection attempts refused by remote sites", + []string{"site"}, + nil, + ), + OutboundConnectionsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "outbound_connections_total"), + "Total number of outbound connections attempted", + []string{"site"}, + nil, + ), + PickupDirectoryMessagesRetrievedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "pickup_directory_messages_retrieved_total"), + "Total number of messages retrieved from the mail pick-up directory", + []string{"site"}, + nil, + ), + QueueFilesOpen: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "queue_files_open"), + "Number of handles to open queue files", + []string{"site"}, + nil, + ), + RemoteQueueLength: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "remote_queue_length"), + "Number of messages in the remote queue", + []string{"site"}, + nil, + ), + RemoteRetryQueueLength: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "remote_retry_queue_length"), + "Number of messages in the retry queue for remote delivery", + []string{"site"}, + nil, + ), + RoutingTableLookupsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "routing_table_lookups_total"), + "Total number of routing table lookups", + []string{"site"}, + nil, + ), + + serverWhitelistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", s.ServerWhiteList)), + serverBlacklistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", s.ServerBlackList)), + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *SMTPCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ctx, ch); err != nil { + log.Error("failed collecting smtp metrics:", desc, err) + return err + } + return nil +} + +// Perflib: "SMTP Server" +type PerflibSMTPServer struct { + Name string + + BadmailedMessagesBadPickupFileTotal float64 `perflib:"Badmailed Messages (Bad Pickup File)"` + BadmailedMessagesGeneralFailureTotal float64 `perflib:"Badmailed Messages (General Failure)"` + BadmailedMessagesHopCountExceededTotal float64 `perflib:"Badmailed Messages (Hop Count Exceeded)"` + BadmailedMessagesNDROfDSNTotal float64 `perflib:"Badmailed Messages (NDR of DSN)"` + BadmailedMessagesNoRecipientsTotal float64 `perflib:"Badmailed Messages (No Recipients)"` + BadmailedMessagesTriggeredViaEventTotal float64 `perflib:"Badmailed Messages (Triggered via Event)"` + BytesSentTotal float64 `perflib:"Bytes Sent Total"` + BytesReceivedTotal float64 `perflib:"Bytes Received Total"` + CategorizerQueueLength float64 `perflib:"Categorizer Queue Length"` + ConnectionErrorsTotal float64 `perflib:"Total Connection Errors"` + CurrentMessagesInLocalDelivery float64 `perflib:"Current Messages in Local Delivery"` + DirectoryDropsTotal float64 `perflib:"Directory Drops Total"` + DNSQueriesTotal float64 `perflib:"DNS Queries Total"` + DSNFailuresTotal float64 `perflib:"Total DSN Failures"` + ETRNMessagesTotal float64 `perflib:"ETRN Messages Total"` + InboundConnectionsCurrent float64 `perflib:"Inbound Connections Current"` + InboundConnectionsTotal float64 `perflib:"Inbound Connections Total"` + LocalQueueLength float64 `perflib:"Local Queue Length"` + LocalRetryQueueLength float64 `perflib:"Local Retry Queue Length"` + MailFilesOpen float64 `perflib:"Number of MailFiles Open"` + MessageBytesReceivedTotal float64 `perflib:"Message Bytes Received Total"` + MessageBytesSentTotal float64 `perflib:"Message Bytes Sent Total"` + MessageDeliveryRetriesTotal float64 `perflib:"Message Delivery Retries"` + MessageSendRetriesTotal float64 `perflib:"Message Send Retries"` + MessagesCurrentlyUndeliverable float64 `perflib:"Messages Currently Undeliverable"` + MessagesDeliveredTotal float64 `perflib:"Messages Delivered Total"` + MessagesPendingRouting float64 `perflib:"Messages Pending Routing"` + MessagesReceivedTotal float64 `perflib:"Messages Received Total"` + MessagesRefusedForAddressObjectsTotal float64 `perflib:"Messages Refused for Address Objects"` + MessagesRefusedForMailObjectsTotal float64 `perflib:"Messages Refused for Mail Objects"` + MessagesRefusedForSizeTotal float64 `perflib:"Messages Refused for Size"` + MessagesSentTotal float64 `perflib:"Messages Sent Total"` + MessagesSubmittedTotal float64 `perflib:"Total messages submitted"` + NDRsGeneratedTotal float64 `perflib:"NDRs Generated"` + OutboundConnectionsCurrent float64 `perflib:"Outbound Connections Current"` + OutboundConnectionsRefusedTotal float64 `perflib:"Outbound Connections Refused"` + OutboundConnectionsTotal float64 `perflib:"Outbound Connections Total"` + QueueFilesOpen float64 `perflib:"Number of QueueFiles Open"` + PickupDirectoryMessagesRetrievedTotal float64 `perflib:"Pickup Directory Messages Retrieved Total"` + RemoteQueueLength float64 `perflib:"Remote Queue Length"` + RemoteRetryQueueLength float64 `perflib:"Remote Retry Queue Length"` + RoutingTableLookupsTotal float64 `perflib:"Routing Table Lookups Total"` +} + +func (c *SMTPCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []PerflibSMTPServer + if err := unmarshalObject(ctx.perfObjects["SMTP Server"], &dst); err != nil { + return nil, err + } + + for _, server := range dst { + if server.Name == "_Total" || + c.serverBlacklistPattern.MatchString(server.Name) || + !c.serverWhitelistPattern.MatchString(server.Name) { + continue + } + + ch <- prometheus.MustNewConstMetric( + c.BadmailedMessagesBadPickupFileTotal, + prometheus.CounterValue, + server.BadmailedMessagesBadPickupFileTotal, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.BadmailedMessagesHopCountExceededTotal, + prometheus.CounterValue, + server.BadmailedMessagesHopCountExceededTotal, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.BadmailedMessagesNDROfDSNTotal, + prometheus.CounterValue, + server.BadmailedMessagesNDROfDSNTotal, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.BadmailedMessagesNoRecipientsTotal, + prometheus.CounterValue, + server.BadmailedMessagesNoRecipientsTotal, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.BadmailedMessagesTriggeredViaEventTotal, + prometheus.CounterValue, + server.BadmailedMessagesTriggeredViaEventTotal, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.BytesSentTotal, + prometheus.CounterValue, + server.BytesSentTotal, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.BytesReceivedTotal, + prometheus.CounterValue, + server.BytesReceivedTotal, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.CategorizerQueueLength, + prometheus.GaugeValue, + server.CategorizerQueueLength, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.ConnectionErrorsTotal, + prometheus.CounterValue, + server.ConnectionErrorsTotal, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.CurrentMessagesInLocalDelivery, + prometheus.GaugeValue, + server.CurrentMessagesInLocalDelivery, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.DirectoryDropsTotal, + prometheus.CounterValue, + server.DirectoryDropsTotal, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.DSNFailuresTotal, + prometheus.CounterValue, + server.DSNFailuresTotal, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.DNSQueriesTotal, + prometheus.CounterValue, + server.DNSQueriesTotal, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.ETRNMessagesTotal, + prometheus.CounterValue, + server.ETRNMessagesTotal, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.InboundConnectionsTotal, + prometheus.CounterValue, + server.InboundConnectionsTotal, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.InboundConnectionsCurrent, + prometheus.GaugeValue, + server.InboundConnectionsCurrent, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.LocalQueueLength, + prometheus.GaugeValue, + server.LocalQueueLength, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.LocalRetryQueueLength, + prometheus.GaugeValue, + server.LocalRetryQueueLength, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.MailFilesOpen, + prometheus.GaugeValue, + server.MailFilesOpen, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.MessageBytesReceivedTotal, + prometheus.CounterValue, + server.MessageBytesReceivedTotal, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.MessageBytesSentTotal, + prometheus.CounterValue, + server.MessageBytesSentTotal, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.MessageDeliveryRetriesTotal, + prometheus.CounterValue, + server.MessageDeliveryRetriesTotal, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.MessageSendRetriesTotal, + prometheus.CounterValue, + server.MessageSendRetriesTotal, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.MessagesCurrentlyUndeliverable, + prometheus.GaugeValue, + server.MessagesCurrentlyUndeliverable, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.MessagesDeliveredTotal, + prometheus.CounterValue, + server.MessagesDeliveredTotal, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.MessagesPendingRouting, + prometheus.GaugeValue, + server.MessagesPendingRouting, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.MessagesReceivedTotal, + prometheus.CounterValue, + server.MessagesReceivedTotal, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.MessagesRefusedForAddressObjectsTotal, + prometheus.CounterValue, + server.MessagesRefusedForAddressObjectsTotal, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.MessagesRefusedForMailObjectsTotal, + prometheus.CounterValue, + server.MessagesRefusedForMailObjectsTotal, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.MessagesRefusedForSizeTotal, + prometheus.CounterValue, + server.MessagesRefusedForSizeTotal, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.MessagesSentTotal, + prometheus.CounterValue, + server.MessagesSentTotal, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.MessagesSubmittedTotal, + prometheus.CounterValue, + server.MessagesSubmittedTotal, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.NDRsGeneratedTotal, + prometheus.CounterValue, + server.NDRsGeneratedTotal, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.OutboundConnectionsCurrent, + prometheus.GaugeValue, + server.OutboundConnectionsCurrent, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.OutboundConnectionsRefusedTotal, + prometheus.CounterValue, + server.OutboundConnectionsRefusedTotal, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.OutboundConnectionsTotal, + prometheus.CounterValue, + server.OutboundConnectionsTotal, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.QueueFilesOpen, + prometheus.GaugeValue, + server.QueueFilesOpen, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.PickupDirectoryMessagesRetrievedTotal, + prometheus.CounterValue, + server.PickupDirectoryMessagesRetrievedTotal, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.RemoteQueueLength, + prometheus.GaugeValue, + server.RemoteQueueLength, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.RemoteRetryQueueLength, + prometheus.GaugeValue, + server.RemoteRetryQueueLength, + server.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.RoutingTableLookupsTotal, + prometheus.CounterValue, + server.RoutingTableLookupsTotal, + server.Name, + ) + + } + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/system.go b/vendor/github.com/prometheus-community/windows_exporter/collector/system.go new file mode 100644 index 000000000000..a4eec8abbfb8 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/system.go @@ -0,0 +1,126 @@ +// +build windows + +package collector + +import ( + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +func init() { + registerCollector("system", NewSystemCollector, "System") +} + +// A SystemCollector is a Prometheus collector for WMI metrics +type SystemCollector struct { + ContextSwitchesTotal *prometheus.Desc + ExceptionDispatchesTotal *prometheus.Desc + ProcessorQueueLength *prometheus.Desc + SystemCallsTotal *prometheus.Desc + SystemUpTime *prometheus.Desc + Threads *prometheus.Desc +} + +// NewSystemCollector ... +func NewSystemCollector() (Collector, error) { + const subsystem = "system" + + return &SystemCollector{ + ContextSwitchesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "context_switches_total"), + "Total number of context switches (WMI source: PerfOS_System.ContextSwitchesPersec)", + nil, + nil, + ), + ExceptionDispatchesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "exception_dispatches_total"), + "Total number of exceptions dispatched (WMI source: PerfOS_System.ExceptionDispatchesPersec)", + nil, + nil, + ), + ProcessorQueueLength: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "processor_queue_length"), + "Length of processor queue (WMI source: PerfOS_System.ProcessorQueueLength)", + nil, + nil, + ), + SystemCallsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "system_calls_total"), + "Total number of system calls (WMI source: PerfOS_System.SystemCallsPersec)", + nil, + nil, + ), + SystemUpTime: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "system_up_time"), + "System boot time (WMI source: PerfOS_System.SystemUpTime)", + nil, + nil, + ), + Threads: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "threads"), + "Current number of threads (WMI source: PerfOS_System.Threads)", + nil, + nil, + ), + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *SystemCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ctx, ch); err != nil { + log.Error("failed collecting system metrics:", desc, err) + return err + } + return nil +} + +// Win32_PerfRawData_PerfOS_System docs: +// - https://web.archive.org/web/20050830140516/http://msdn.microsoft.com/library/en-us/wmisdk/wmi/win32_perfrawdata_perfos_system.asp +type system struct { + ContextSwitchesPersec float64 `perflib:"Context Switches/sec"` + ExceptionDispatchesPersec float64 `perflib:"Exception Dispatches/sec"` + ProcessorQueueLength float64 `perflib:"Processor Queue Length"` + SystemCallsPersec float64 `perflib:"System Calls/sec"` + SystemUpTime float64 `perflib:"System Up Time"` + Threads float64 `perflib:"Threads"` +} + +func (c *SystemCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []system + if err := unmarshalObject(ctx.perfObjects["System"], &dst); err != nil { + return nil, err + } + + ch <- prometheus.MustNewConstMetric( + c.ContextSwitchesTotal, + prometheus.CounterValue, + dst[0].ContextSwitchesPersec, + ) + ch <- prometheus.MustNewConstMetric( + c.ExceptionDispatchesTotal, + prometheus.CounterValue, + dst[0].ExceptionDispatchesPersec, + ) + ch <- prometheus.MustNewConstMetric( + c.ProcessorQueueLength, + prometheus.GaugeValue, + dst[0].ProcessorQueueLength, + ) + ch <- prometheus.MustNewConstMetric( + c.SystemCallsTotal, + prometheus.CounterValue, + dst[0].SystemCallsPersec, + ) + ch <- prometheus.MustNewConstMetric( + c.SystemUpTime, + prometheus.GaugeValue, + dst[0].SystemUpTime, + ) + ch <- prometheus.MustNewConstMetric( + c.Threads, + prometheus.GaugeValue, + dst[0].Threads, + ) + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/tcp.go b/vendor/github.com/prometheus-community/windows_exporter/collector/tcp.go new file mode 100644 index 000000000000..e9d2adce0d58 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/tcp.go @@ -0,0 +1,191 @@ +// +build windows + +package collector + +import ( + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +func init() { + registerCollector("tcp", NewTCPCollector, "TCPv4", "TCPv6") +} + +// A TCPCollector is a Prometheus collector for WMI Win32_PerfRawData_Tcpip_TCPv{4,6} metrics +type TCPCollector struct { + ConnectionFailures *prometheus.Desc + ConnectionsActive *prometheus.Desc + ConnectionsEstablished *prometheus.Desc + ConnectionsPassive *prometheus.Desc + ConnectionsReset *prometheus.Desc + SegmentsTotal *prometheus.Desc + SegmentsReceivedTotal *prometheus.Desc + SegmentsRetransmittedTotal *prometheus.Desc + SegmentsSentTotal *prometheus.Desc +} + +// NewTCPCollector ... +func NewTCPCollector() (Collector, error) { + const subsystem = "tcp" + + return &TCPCollector{ + ConnectionFailures: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "connection_failures"), + "(TCP.ConnectionFailures)", + []string{"af"}, + nil, + ), + ConnectionsActive: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "connections_active"), + "(TCP.ConnectionsActive)", + []string{"af"}, + nil, + ), + ConnectionsEstablished: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "connections_established"), + "(TCP.ConnectionsEstablished)", + []string{"af"}, + nil, + ), + ConnectionsPassive: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "connections_passive"), + "(TCP.ConnectionsPassive)", + []string{"af"}, + nil, + ), + ConnectionsReset: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "connections_reset"), + "(TCP.ConnectionsReset)", + []string{"af"}, + nil, + ), + SegmentsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "segments_total"), + "(TCP.SegmentsTotal)", + []string{"af"}, + nil, + ), + SegmentsReceivedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "segments_received_total"), + "(TCP.SegmentsReceivedTotal)", + []string{"af"}, + nil, + ), + SegmentsRetransmittedTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "segments_retransmitted_total"), + "(TCP.SegmentsRetransmittedTotal)", + []string{"af"}, + nil, + ), + SegmentsSentTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "segments_sent_total"), + "(TCP.SegmentsSentTotal)", + []string{"af"}, + nil, + ), + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *TCPCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ctx, ch); err != nil { + log.Error("failed collecting tcp metrics:", desc, err) + return err + } + return nil +} + +// Win32_PerfRawData_Tcpip_TCPv4 docs +// - https://msdn.microsoft.com/en-us/library/aa394341(v=vs.85).aspx +// The TCPv6 performance object uses the same fields. +type tcp struct { + ConnectionFailures float64 `perflib:"Connection Failures"` + ConnectionsActive float64 `perflib:"Connections Active"` + ConnectionsEstablished float64 `perflib:"Connections Established"` + ConnectionsPassive float64 `perflib:"Connections Passive"` + ConnectionsReset float64 `perflib:"Connections Reset"` + SegmentsPersec float64 `perflib:"Segments/sec"` + SegmentsReceivedPersec float64 `perflib:"Segments Received/sec"` + SegmentsRetransmittedPersec float64 `perflib:"Segments Retransmitted/sec"` + SegmentsSentPersec float64 `perflib:"Segments Sent/sec"` +} + +func writeTCPCounters(metrics tcp, labels []string, c *TCPCollector, ch chan<- prometheus.Metric) { + ch <- prometheus.MustNewConstMetric( + c.ConnectionFailures, + prometheus.CounterValue, + metrics.ConnectionFailures, + labels..., + ) + ch <- prometheus.MustNewConstMetric( + c.ConnectionsActive, + prometheus.CounterValue, + metrics.ConnectionsActive, + labels..., + ) + ch <- prometheus.MustNewConstMetric( + c.ConnectionsEstablished, + prometheus.GaugeValue, + metrics.ConnectionsEstablished, + labels..., + ) + ch <- prometheus.MustNewConstMetric( + c.ConnectionsPassive, + prometheus.CounterValue, + metrics.ConnectionsPassive, + labels..., + ) + ch <- prometheus.MustNewConstMetric( + c.ConnectionsReset, + prometheus.CounterValue, + metrics.ConnectionsReset, + labels..., + ) + ch <- prometheus.MustNewConstMetric( + c.SegmentsTotal, + prometheus.CounterValue, + metrics.SegmentsPersec, + labels..., + ) + ch <- prometheus.MustNewConstMetric( + c.SegmentsReceivedTotal, + prometheus.CounterValue, + metrics.SegmentsReceivedPersec, + labels..., + ) + ch <- prometheus.MustNewConstMetric( + c.SegmentsRetransmittedTotal, + prometheus.CounterValue, + metrics.SegmentsRetransmittedPersec, + labels..., + ) + ch <- prometheus.MustNewConstMetric( + c.SegmentsSentTotal, + prometheus.CounterValue, + metrics.SegmentsSentPersec, + labels..., + ) +} + +func (c *TCPCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []tcp + + // TCPv4 counters + if err := unmarshalObject(ctx.perfObjects["TCPv4"], &dst); err != nil { + return nil, err + } + if len(dst) != 0 { + writeTCPCounters(dst[0], []string{"ipv4"}, c, ch) + } + + // TCPv6 counters + if err := unmarshalObject(ctx.perfObjects["TCPv6"], &dst); err != nil { + return nil, err + } + if len(dst) != 0 { + writeTCPCounters(dst[0], []string{"ipv6"}, c, ch) + } + + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/terminal_services.go b/vendor/github.com/prometheus-community/windows_exporter/collector/terminal_services.go new file mode 100644 index 000000000000..1d02d97ab9cd --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/terminal_services.go @@ -0,0 +1,403 @@ +// +build windows + +package collector + +import ( + "errors" + "strings" + + "github.com/StackExchange/wmi" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +const ConnectionBrokerFeatureID uint32 = 133 + +func init() { + registerCollector("terminal_services", NewTerminalServicesCollector, "Terminal Services", "Terminal Services Session", "Remote Desktop Connection Broker Counterset") +} + +var ( + connectionBrokerEnabled = isConnectionBrokerServer() +) + +type Win32_ServerFeature struct { + ID uint32 +} + +func isConnectionBrokerServer() bool { + var dst []Win32_ServerFeature + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { + return false + } + for _, d := range dst { + if d.ID == ConnectionBrokerFeatureID { + return true + } + } + log.Debug("host is not a connection broker skipping Connection Broker performance metrics.") + return false +} + +// A TerminalServicesCollector is a Prometheus collector for WMI +// Win32_PerfRawData_LocalSessionManager_TerminalServices & Win32_PerfRawData_TermService_TerminalServicesSession metrics +// https://docs.microsoft.com/en-us/previous-versions/aa394344(v%3Dvs.85) +// https://wutils.com/wmi/root/cimv2/win32_perfrawdata_localsessionmanager_terminalservices/ +type TerminalServicesCollector struct { + LocalSessionCount *prometheus.Desc + ConnectionBrokerPerformance *prometheus.Desc + HandleCount *prometheus.Desc + PageFaultsPersec *prometheus.Desc + PageFileBytes *prometheus.Desc + PageFileBytesPeak *prometheus.Desc + PercentPrivilegedTime *prometheus.Desc + PercentProcessorTime *prometheus.Desc + PercentUserTime *prometheus.Desc + PoolNonpagedBytes *prometheus.Desc + PoolPagedBytes *prometheus.Desc + PrivateBytes *prometheus.Desc + ThreadCount *prometheus.Desc + VirtualBytes *prometheus.Desc + VirtualBytesPeak *prometheus.Desc + WorkingSet *prometheus.Desc + WorkingSetPeak *prometheus.Desc +} + +// NewTerminalServicesCollector ... +func NewTerminalServicesCollector() (Collector, error) { + const subsystem = "terminal_services" + return &TerminalServicesCollector{ + LocalSessionCount: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "local_session_count"), + "Number of Terminal Services sessions", + []string{"session"}, + nil, + ), + ConnectionBrokerPerformance: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "connection_broker_performance_total"), + "The total number of connections handled by the Connection Brokers since the service started.", + []string{"connection"}, + nil, + ), + HandleCount: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "handle_count"), + "Total number of handles currently opened by this process. This number is the sum of the handles currently opened by each thread in this process.", + []string{"session_name"}, + nil, + ), + PageFaultsPersec: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "page_fault_total"), + "Rate at which page faults occur in the threads executing in this process. A page fault occurs when a thread refers to a virtual memory page that is not in its working set in main memory. The page may not be retrieved from disk if it is on the standby list and therefore already in main memory. The page also may not be retrieved if it is in use by another process which shares the page.", + []string{"session_name"}, + nil, + ), + PageFileBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "page_file_bytes"), + "Current number of bytes this process has used in the paging file(s). Paging files are used to store pages of memory used by the process that are not contained in other files. Paging files are shared by all processes, and lack of space in paging files can prevent other processes from allocating memory.", + []string{"session_name"}, + nil, + ), + PageFileBytesPeak: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "page_file_bytes_peak"), + "Maximum number of bytes this process has used in the paging file(s). Paging files are used to store pages of memory used by the process that are not contained in other files. Paging files are shared by all processes, and lack of space in paging files can prevent other processes from allocating memory.", + []string{"session_name"}, + nil, + ), + PercentPrivilegedTime: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "privileged_time_seconds_total"), + "Total elapsed time that the threads of the process have spent executing code in privileged mode.", + []string{"session_name"}, + nil, + ), + PercentProcessorTime: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "processor_time_seconds_total"), + "Total elapsed time that all of the threads of this process used the processor to execute instructions.", + []string{"session_name"}, + nil, + ), + PercentUserTime: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "user_time_seconds_total"), + "Total elapsed time that this process's threads have spent executing code in user mode. Applications, environment subsystems, and integral subsystems execute in user mode.", + []string{"session_name"}, + nil, + ), + PoolNonpagedBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "pool_non_paged_bytes"), + "Number of bytes in the non-paged pool, an area of system memory (physical memory used by the operating system) for objects that cannot be written to disk, but must remain in physical memory as long as they are allocated. This property displays the last observed value only; it is not an average.", + []string{"session_name"}, + nil, + ), + PoolPagedBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "pool_paged_bytes"), + "Number of bytes in the paged pool, an area of system memory (physical memory used by the operating system) for objects that can be written to disk when they are not being used. This property displays the last observed value only; it is not an average.", + []string{"session_name"}, + nil, + ), + PrivateBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "private_bytes"), + "Current number of bytes this process has allocated that cannot be shared with other processes.", + []string{"session_name"}, + nil, + ), + ThreadCount: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "thread_count"), + "Number of threads currently active in this process. An instruction is the basic unit of execution in a processor, and a thread is the object that executes instructions. Every running process has at least one thread.", + []string{"session_name"}, + nil, + ), + VirtualBytes: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "virtual_bytes"), + "Current size, in bytes, of the virtual address space the process is using. Use of virtual address space does not necessarily imply corresponding use of either disk or main memory pages. Virtual space is finite and, by using too much, the process can limit its ability to load libraries.", + []string{"session_name"}, + nil, + ), + VirtualBytesPeak: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "virtual_bytes_peak"), + "Maximum number of bytes of virtual address space the process has used at any one time. Use of virtual address space does not necessarily imply corresponding use of either disk or main memory pages. Virtual space is finite and, by using too much, the process might limit its ability to load libraries.", + []string{"session_name"}, + nil, + ), + WorkingSet: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "working_set_bytes"), + "Current number of bytes in the working set of this process. The working set is the set of memory pages touched recently by the threads in the process. If free memory in the computer is above a threshold, pages are left in the working set of a process even if they are not in use. When free memory falls below a threshold, pages are trimmed from working sets. If they are needed, they are then soft-faulted back into the working set before they leave main memory.", + []string{"session_name"}, + nil, + ), + WorkingSetPeak: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "working_set_bytes_peak"), + "Maximum number of bytes in the working set of this process at any point in time. The working set is the set of memory pages touched recently by the threads in the process. If free memory in the computer is above a threshold, pages are left in the working set of a process even if they are not in use. When free memory falls below a threshold, pages are trimmed from working sets. If they are needed, they are then soft-faulted back into the working set before they leave main memory.", + []string{"session_name"}, + nil, + ), + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *TerminalServicesCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collectTSSessionCount(ctx, ch); err != nil { + log.Error("failed collecting terminal services session count metrics:", desc, err) + return err + } + if desc, err := c.collectTSSessionCounters(ctx, ch); err != nil { + log.Error("failed collecting terminal services session count metrics:", desc, err) + return err + } + + // only collect CollectionBrokerPerformance if host is a Connection Broker + if connectionBrokerEnabled { + if desc, err := c.collectCollectionBrokerPerformanceCounter(ctx, ch); err != nil { + log.Error("failed collecting Connection Broker performance metrics:", desc, err) + return err + } + } + return nil +} + +type perflibTerminalServices struct { + ActiveSessions float64 `perflib:"Active Sessions"` + InactiveSessions float64 `perflib:"Inactive Sessions"` + TotalSessions float64 `perflib:"Total Sessions"` +} + +func (c *TerminalServicesCollector) collectTSSessionCount(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + dst := make([]perflibTerminalServices, 0) + err := unmarshalObject(ctx.perfObjects["Terminal Services"], &dst) + if err != nil { + return nil, err + } + if len(dst) == 0 { + return nil, errors.New("WMI query returned empty result set") + } + + ch <- prometheus.MustNewConstMetric( + c.LocalSessionCount, + prometheus.GaugeValue, + dst[0].ActiveSessions, + "active", + ) + + ch <- prometheus.MustNewConstMetric( + c.LocalSessionCount, + prometheus.GaugeValue, + dst[0].InactiveSessions, + "inactive", + ) + + ch <- prometheus.MustNewConstMetric( + c.LocalSessionCount, + prometheus.GaugeValue, + dst[0].TotalSessions, + "total", + ) + + return nil, nil +} + +type perflibTerminalServicesSession struct { + Name string + HandleCount float64 `perflib:"Handle Count"` + PageFaultsPersec float64 `perflib:"Page Faults/sec"` + PageFileBytes float64 `perflib:"Page File Bytes"` + PageFileBytesPeak float64 `perflib:"Page File Bytes Peak"` + PercentPrivilegedTime float64 `perflib:"% Privileged Time"` + PercentProcessorTime float64 `perflib:"% Processor Time"` + PercentUserTime float64 `perflib:"% User Time"` + PoolNonpagedBytes float64 `perflib:"Pool Nonpaged Bytes"` + PoolPagedBytes float64 `perflib:"Pool Paged Bytes"` + PrivateBytes float64 `perflib:"Private Bytes"` + ThreadCount float64 `perflib:"Thread Count"` + VirtualBytes float64 `perflib:"Virtual Bytes"` + VirtualBytesPeak float64 `perflib:"Virtual Bytes Peak"` + WorkingSet float64 `perflib:"Working Set"` + WorkingSetPeak float64 `perflib:"Working Set Peak"` +} + +func (c *TerminalServicesCollector) collectTSSessionCounters(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + dst := make([]perflibTerminalServicesSession, 0) + err := unmarshalObject(ctx.perfObjects["Terminal Services Session"], &dst) + if err != nil { + return nil, err + } + + for _, d := range dst { + // only connect metrics for remote named sessions + n := strings.ToLower(d.Name) + if n == "" || n == "services" || n == "console" { + continue + } + ch <- prometheus.MustNewConstMetric( + c.HandleCount, + prometheus.GaugeValue, + d.HandleCount, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.PageFaultsPersec, + prometheus.CounterValue, + d.PageFaultsPersec, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.PageFileBytes, + prometheus.GaugeValue, + d.PageFileBytes, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.PageFileBytesPeak, + prometheus.GaugeValue, + d.PageFileBytesPeak, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.PercentPrivilegedTime, + prometheus.CounterValue, + d.PercentPrivilegedTime, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.PercentProcessorTime, + prometheus.CounterValue, + d.PercentProcessorTime, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.PercentUserTime, + prometheus.CounterValue, + d.PercentUserTime, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.PoolNonpagedBytes, + prometheus.GaugeValue, + d.PoolNonpagedBytes, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.PoolPagedBytes, + prometheus.GaugeValue, + d.PoolPagedBytes, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.PrivateBytes, + prometheus.GaugeValue, + d.PrivateBytes, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.ThreadCount, + prometheus.GaugeValue, + d.ThreadCount, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.VirtualBytes, + prometheus.GaugeValue, + d.VirtualBytes, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.VirtualBytesPeak, + prometheus.GaugeValue, + d.VirtualBytesPeak, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.WorkingSet, + prometheus.GaugeValue, + d.WorkingSet, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.WorkingSetPeak, + prometheus.GaugeValue, + d.WorkingSetPeak, + d.Name, + ) + } + return nil, nil +} + +type perflibRemoteDesktopConnectionBrokerCounterset struct { + SuccessfulConnections float64 `perflib:"Successful Connections"` + PendingConnections float64 `perflib:"Pending Connections"` + FailedConnections float64 `perflib:"Failed Connections"` +} + +func (c *TerminalServicesCollector) collectCollectionBrokerPerformanceCounter(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + + dst := make([]perflibRemoteDesktopConnectionBrokerCounterset, 0) + err := unmarshalObject(ctx.perfObjects["Remote Desktop Connection Broker Counterset"], &dst) + if err != nil { + return nil, err + } + if len(dst) == 0 { + return nil, errors.New("WMI query returned empty result set") + } + + ch <- prometheus.MustNewConstMetric( + c.ConnectionBrokerPerformance, + prometheus.CounterValue, + dst[0].SuccessfulConnections, + "Successful", + ) + + ch <- prometheus.MustNewConstMetric( + c.ConnectionBrokerPerformance, + prometheus.CounterValue, + dst[0].PendingConnections, + "Pending", + ) + + ch <- prometheus.MustNewConstMetric( + c.ConnectionBrokerPerformance, + prometheus.CounterValue, + dst[0].FailedConnections, + "Failed", + ) + + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/textfile.go b/vendor/github.com/prometheus-community/windows_exporter/collector/textfile.go new file mode 100644 index 000000000000..99973ccf769e --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/textfile.go @@ -0,0 +1,308 @@ +// Copyright 2015 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build windows + +package collector + +import ( + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "sort" + "strings" + "time" + + "github.com/dimchansky/utfbom" + "github.com/prometheus/client_golang/prometheus" + dto "github.com/prometheus/client_model/go" + "github.com/prometheus/common/expfmt" + "github.com/prometheus/common/log" + kingpin "gopkg.in/alecthomas/kingpin.v2" +) + +func init() { + registerCollectorWithConfig("textfile", func() Config { return &TextFileConfig{} }) +} + +var mtimeDesc = prometheus.NewDesc( + prometheus.BuildFQName(Namespace, "textfile", "mtime_seconds"), + "Unixtime mtime of textfiles successfully read.", + []string{"file"}, + nil, +) + +type TextFileConfig struct { + TextFileDirectory string +} + +func (t *TextFileConfig) RegisterKingpin(ka *kingpin.Application) { + ka.Flag( + "collector.textfile.directory", + "Directory to read text files with metrics from.", + ).Default("C:\\Program Files\\windows_exporter\\textfile_inputs").StringVar(&t.TextFileDirectory) + +} + +func (t *TextFileConfig) Build() (Collector, error) { + return NewTextFileCollector(t) +} + +type textFileCollector struct { + path string + // Only set for testing to get predictable output. + mtime *float64 +} + +// NewTextFileCollector returns a new Collector exposing metrics read from files +// in the given textfile directory. +func NewTextFileCollector(t *TextFileConfig) (Collector, error) { + return &textFileCollector{ + path: t.TextFileDirectory, + }, nil +} + +func convertMetricFamily(metricFamily *dto.MetricFamily, ch chan<- prometheus.Metric) { + var valType prometheus.ValueType + var val float64 + + allLabelNames := map[string]struct{}{} + for _, metric := range metricFamily.Metric { + labels := metric.GetLabel() + for _, label := range labels { + if _, ok := allLabelNames[label.GetName()]; !ok { + allLabelNames[label.GetName()] = struct{}{} + } + } + } + + for _, metric := range metricFamily.Metric { + if metric.TimestampMs != nil { + log.Warnf("Ignoring unsupported custom timestamp on textfile collector metric %v", metric) + } + + labels := metric.GetLabel() + var names []string + var values []string + for _, label := range labels { + names = append(names, label.GetName()) + values = append(values, label.GetValue()) + } + + for k := range allLabelNames { + present := false + for _, name := range names { + if k == name { + present = true + break + } + } + if present == false { + names = append(names, k) + values = append(values, "") + } + } + + metricType := metricFamily.GetType() + switch metricType { + case dto.MetricType_COUNTER: + valType = prometheus.CounterValue + val = metric.Counter.GetValue() + + case dto.MetricType_GAUGE: + valType = prometheus.GaugeValue + val = metric.Gauge.GetValue() + + case dto.MetricType_UNTYPED: + valType = prometheus.UntypedValue + val = metric.Untyped.GetValue() + + case dto.MetricType_SUMMARY: + quantiles := map[float64]float64{} + for _, q := range metric.Summary.Quantile { + quantiles[q.GetQuantile()] = q.GetValue() + } + ch <- prometheus.MustNewConstSummary( + prometheus.NewDesc( + *metricFamily.Name, + metricFamily.GetHelp(), + names, nil, + ), + metric.Summary.GetSampleCount(), + metric.Summary.GetSampleSum(), + quantiles, values..., + ) + case dto.MetricType_HISTOGRAM: + buckets := map[float64]uint64{} + for _, b := range metric.Histogram.Bucket { + buckets[b.GetUpperBound()] = b.GetCumulativeCount() + } + ch <- prometheus.MustNewConstHistogram( + prometheus.NewDesc( + *metricFamily.Name, + metricFamily.GetHelp(), + names, nil, + ), + metric.Histogram.GetSampleCount(), + metric.Histogram.GetSampleSum(), + buckets, values..., + ) + default: + log.Errorf("unknown metric type for file") + continue + } + if metricType == dto.MetricType_GAUGE || metricType == dto.MetricType_COUNTER || metricType == dto.MetricType_UNTYPED { + ch <- prometheus.MustNewConstMetric( + prometheus.NewDesc( + *metricFamily.Name, + metricFamily.GetHelp(), + names, nil, + ), + valType, val, values..., + ) + } + } +} + +func (c *textFileCollector) exportMTimes(mtimes map[string]time.Time, ch chan<- prometheus.Metric) { + // Export the mtimes of the successful files. + if len(mtimes) > 0 { + // Sorting is needed for predictable output comparison in tests. + filenames := make([]string, 0, len(mtimes)) + for filename := range mtimes { + filenames = append(filenames, filename) + } + sort.Strings(filenames) + + for _, filename := range filenames { + mtime := float64(mtimes[filename].UnixNano() / 1e9) + if c.mtime != nil { + mtime = *c.mtime + } + ch <- prometheus.MustNewConstMetric(mtimeDesc, prometheus.GaugeValue, mtime, filename) + } + } +} + +type carriageReturnFilteringReader struct { + r io.Reader +} + +// Read returns data from the underlying io.Reader, but with \r filtered out +func (cr carriageReturnFilteringReader) Read(p []byte) (int, error) { + buf := make([]byte, len(p)) + n, err := cr.r.Read(buf) + + if err != nil && err != io.EOF { + return n, err + } + + pi := 0 + for i := 0; i < n; i++ { + if buf[i] != '\r' { + p[pi] = buf[i] + pi++ + } + } + + return pi, err +} + +// Update implements the Collector interface. +func (c *textFileCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + error := 0.0 + mtimes := map[string]time.Time{} + + // Iterate over files and accumulate their metrics. + files, err := ioutil.ReadDir(c.path) + if err != nil && c.path != "" { + log.Errorf("Error reading textfile collector directory %q: %s", c.path, err) + error = 1.0 + } + +fileLoop: + for _, f := range files { + if !strings.HasSuffix(f.Name(), ".prom") { + continue + } + path := filepath.Join(c.path, f.Name()) + log.Debugf("Processing file %q", path) + file, err := os.Open(path) + if err != nil { + log.Errorf("Error opening %q: %v", path, err) + error = 1.0 + continue + } + var parser expfmt.TextParser + r, encoding := utfbom.Skip(carriageReturnFilteringReader{r: file}) + if err = checkBOM(encoding); err != nil { + log.Errorf("Invalid file encoding detected in %s: %s - file must be UTF8", path, err.Error()) + error = 1.0 + continue + } + parsedFamilies, err := parser.TextToMetricFamilies(r) + closeErr := file.Close() + if closeErr != nil { + log.Warnf("Error closing file: %v", err) + } + if err != nil { + log.Errorf("Error parsing %q: %v", path, err) + error = 1.0 + continue + } + for _, mf := range parsedFamilies { + for _, m := range mf.Metric { + if m.TimestampMs != nil { + log.Errorf("Textfile %q contains unsupported client-side timestamps, skipping entire file", path) + error = 1.0 + continue fileLoop + } + } + if mf.Help == nil { + help := fmt.Sprintf("Metric read from %s", path) + mf.Help = &help + } + } + + // Only set this once it has been parsed and validated, so that + // a failure does not appear fresh. + mtimes[f.Name()] = f.ModTime() + + for _, mf := range parsedFamilies { + convertMetricFamily(mf, ch) + } + } + + c.exportMTimes(mtimes, ch) + + // Export if there were errors. + ch <- prometheus.MustNewConstMetric( + prometheus.NewDesc( + prometheus.BuildFQName(Namespace, "textfile", "scrape_error"), + "1 if there was an error opening or reading a file, 0 otherwise", + nil, nil, + ), + prometheus.GaugeValue, error, + ) + return nil +} + +func checkBOM(encoding utfbom.Encoding) error { + if encoding == utfbom.Unknown || encoding == utfbom.UTF8 { + return nil + } + + return fmt.Errorf(encoding.String()) +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/thermalzone.go b/vendor/github.com/prometheus-community/windows_exporter/collector/thermalzone.go new file mode 100644 index 000000000000..baf6ec8bfab8 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/thermalzone.go @@ -0,0 +1,103 @@ +package collector + +import ( + "github.com/StackExchange/wmi" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +func init() { + registerCollector("thermalzone", NewThermalZoneCollector) +} + +// A thermalZoneCollector is a Prometheus collector for WMI Win32_PerfRawData_Counters_ThermalZoneInformation metrics +type thermalZoneCollector struct { + PercentPassiveLimit *prometheus.Desc + Temperature *prometheus.Desc + ThrottleReasons *prometheus.Desc +} + +// NewThermalZoneCollector ... +func NewThermalZoneCollector() (Collector, error) { + const subsystem = "thermalzone" + return &thermalZoneCollector{ + Temperature: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "temperature_celsius"), + "(Temperature)", + []string{ + "name", + }, + nil, + ), + PercentPassiveLimit: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "percent_passive_limit"), + "(PercentPassiveLimit)", + []string{ + "name", + }, + nil, + ), + ThrottleReasons: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "throttle_reasons"), + "(ThrottleReasons)", + []string{ + "name", + }, + nil, + ), + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *thermalZoneCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + log.Error("failed collecting thermalzone metrics:", desc, err) + return err + } + return nil +} + +// Win32_PerfRawData_Counters_ThermalZoneInformation docs: +// https://wutils.com/wmi/root/cimv2/win32_perfrawdata_counters_thermalzoneinformation/ +type Win32_PerfRawData_Counters_ThermalZoneInformation struct { + Name string + + HighPrecisionTemperature uint32 + PercentPassiveLimit uint32 + ThrottleReasons uint32 +} + +func (c *thermalZoneCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_Counters_ThermalZoneInformation + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, info := range dst { + //Divide by 10 and subtract 273.15 to convert decikelvin to celsius + ch <- prometheus.MustNewConstMetric( + c.Temperature, + prometheus.GaugeValue, + (float64(info.HighPrecisionTemperature)/10.0)-273.15, + info.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.PercentPassiveLimit, + prometheus.GaugeValue, + float64(info.PercentPassiveLimit), + info.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.ThrottleReasons, + prometheus.GaugeValue, + float64(info.ThrottleReasons), + info.Name, + ) + } + + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/time.go b/vendor/github.com/prometheus-community/windows_exporter/collector/time.go new file mode 100644 index 000000000000..dd1eee424382 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/time.go @@ -0,0 +1,130 @@ +// +build windows + +package collector + +import ( + "errors" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +func init() { + registerCollector("time", newTimeCollector, "Windows Time Service") +} + +// TimeCollector is a Prometheus collector for Perflib counter metrics +type TimeCollector struct { + ClockFrequencyAdjustmentPPBTotal *prometheus.Desc + ComputedTimeOffset *prometheus.Desc + NTPClientTimeSourceCount *prometheus.Desc + NTPRoundtripDelay *prometheus.Desc + NTPServerIncomingRequestsTotal *prometheus.Desc + NTPServerOutgoingResponsesTotal *prometheus.Desc +} + +func newTimeCollector() (Collector, error) { + if getWindowsVersion() <= 6.1 { + return nil, errors.New("Windows version older than Server 2016 detected. The time collector will not run and should be disabled via CLI flags or configuration file") + + } + const subsystem = "time" + + return &TimeCollector{ + ClockFrequencyAdjustmentPPBTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "clock_frequency_adjustment_ppb_total"), + "Total adjustment made to the local system clock frequency by W32Time in Parts Per Billion (PPB) units.", + nil, + nil, + ), + ComputedTimeOffset: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "computed_time_offset_seconds"), + "Absolute time offset between the system clock and the chosen time source, in seconds", + nil, + nil, + ), + NTPClientTimeSourceCount: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "ntp_client_time_source_count"), + "Active number of NTP Time sources being used by the client", + nil, + nil, + ), + NTPRoundtripDelay: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "ntp_round_trip_delay_seconds"), + "Roundtrip delay experienced by the NTP client in receiving a response from the server for the most recent request, in seconds", + nil, + nil, + ), + NTPServerOutgoingResponsesTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "ntp_server_outgoing_responses_total"), + "Total number of requests responded to by NTP server", + nil, + nil, + ), + NTPServerIncomingRequestsTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "ntp_server_incoming_requests_total"), + "Total number of requests received by NTP server", + nil, + nil, + ), + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *TimeCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ctx, ch); err != nil { + log.Error("failed collecting time metrics:", desc, err) + return err + } + return nil +} + +// Perflib "Windows Time Service" +type windowsTime struct { + ClockFrequencyAdjustmentPPBTotal float64 `perflib:"Clock Frequency Adjustment (ppb)"` + ComputedTimeOffset float64 `perflib:"Computed Time Offset"` + NTPClientTimeSourceCount float64 `perflib:"NTP Client Time Source Count"` + NTPRoundtripDelay float64 `perflib:"NTP Roundtrip Delay"` + NTPServerIncomingRequestsTotal float64 `perflib:"NTP Server Incoming Requests"` + NTPServerOutgoingResponsesTotal float64 `perflib:"NTP Server Outgoing Responses"` +} + +func (c *TimeCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []windowsTime // Single-instance class, array is required but will have single entry. + if err := unmarshalObject(ctx.perfObjects["Windows Time Service"], &dst); err != nil { + return nil, err + } + + ch <- prometheus.MustNewConstMetric( + c.ClockFrequencyAdjustmentPPBTotal, + prometheus.CounterValue, + dst[0].ClockFrequencyAdjustmentPPBTotal, + ) + ch <- prometheus.MustNewConstMetric( + c.ComputedTimeOffset, + prometheus.GaugeValue, + dst[0].ComputedTimeOffset/1000000, // microseconds -> seconds + ) + ch <- prometheus.MustNewConstMetric( + c.NTPClientTimeSourceCount, + prometheus.GaugeValue, + dst[0].NTPClientTimeSourceCount, + ) + ch <- prometheus.MustNewConstMetric( + c.NTPRoundtripDelay, + prometheus.GaugeValue, + dst[0].NTPRoundtripDelay/1000000, // microseconds -> seconds + ) + ch <- prometheus.MustNewConstMetric( + c.NTPServerIncomingRequestsTotal, + prometheus.CounterValue, + dst[0].NTPServerIncomingRequestsTotal, + ) + ch <- prometheus.MustNewConstMetric( + c.NTPServerOutgoingResponsesTotal, + prometheus.CounterValue, + dst[0].NTPServerOutgoingResponsesTotal, + ) + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/vmware.go b/vendor/github.com/prometheus-community/windows_exporter/collector/vmware.go new file mode 100644 index 000000000000..acecbf1b6c8e --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/vmware.go @@ -0,0 +1,344 @@ +// +build windows + +package collector + +import ( + "errors" + + "github.com/StackExchange/wmi" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +func init() { + registerCollector("vmware", NewVmwareCollector) +} + +// A VmwareCollector is a Prometheus collector for WMI Win32_PerfRawData_vmGuestLib_VMem/Win32_PerfRawData_vmGuestLib_VCPU metrics +type VmwareCollector struct { + MemActive *prometheus.Desc + MemBallooned *prometheus.Desc + MemLimit *prometheus.Desc + MemMapped *prometheus.Desc + MemOverhead *prometheus.Desc + MemReservation *prometheus.Desc + MemShared *prometheus.Desc + MemSharedSaved *prometheus.Desc + MemShares *prometheus.Desc + MemSwapped *prometheus.Desc + MemTargetSize *prometheus.Desc + MemUsed *prometheus.Desc + + CpuLimitMHz *prometheus.Desc + CpuReservationMHz *prometheus.Desc + CpuShares *prometheus.Desc + CpuStolenTotal *prometheus.Desc + CpuTimeTotal *prometheus.Desc + EffectiveVMSpeedMHz *prometheus.Desc + HostProcessorSpeedMHz *prometheus.Desc +} + +// NewVmwareCollector constructs a new VmwareCollector +func NewVmwareCollector() (Collector, error) { + const subsystem = "vmware" + return &VmwareCollector{ + MemActive: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "mem_active_bytes"), + "(MemActiveMB)", + nil, + nil, + ), + MemBallooned: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "mem_ballooned_bytes"), + "(MemBalloonedMB)", + nil, + nil, + ), + MemLimit: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "mem_limit_bytes"), + "(MemLimitMB)", + nil, + nil, + ), + MemMapped: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "mem_mapped_bytes"), + "(MemMappedMB)", + nil, + nil, + ), + MemOverhead: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "mem_overhead_bytes"), + "(MemOverheadMB)", + nil, + nil, + ), + MemReservation: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "mem_reservation_bytes"), + "(MemReservationMB)", + nil, + nil, + ), + MemShared: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "mem_shared_bytes"), + "(MemSharedMB)", + nil, + nil, + ), + MemSharedSaved: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "mem_shared_saved_bytes"), + "(MemSharedSavedMB)", + nil, + nil, + ), + MemShares: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "mem_shares"), + "(MemShares)", + nil, + nil, + ), + MemSwapped: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "mem_swapped_bytes"), + "(MemSwappedMB)", + nil, + nil, + ), + MemTargetSize: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "mem_target_size_bytes"), + "(MemTargetSizeMB)", + nil, + nil, + ), + MemUsed: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "mem_used_bytes"), + "(MemUsedMB)", + nil, + nil, + ), + + CpuLimitMHz: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "cpu_limit_mhz"), + "(CpuLimitMHz)", + nil, + nil, + ), + CpuReservationMHz: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "cpu_reservation_mhz"), + "(CpuReservationMHz)", + nil, + nil, + ), + CpuShares: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "cpu_shares"), + "(CpuShares)", + nil, + nil, + ), + CpuStolenTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "cpu_stolen_seconds_total"), + "(CpuStolenMs)", + nil, + nil, + ), + CpuTimeTotal: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "cpu_time_seconds_total"), + "(CpuTimePercents)", + nil, + nil, + ), + EffectiveVMSpeedMHz: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "effective_vm_speed_mhz"), + "(EffectiveVMSpeedMHz)", + nil, + nil, + ), + HostProcessorSpeedMHz: prometheus.NewDesc( + prometheus.BuildFQName(Namespace, subsystem, "host_processor_speed_mhz"), + "(HostProcessorSpeedMHz)", + nil, + nil, + ), + }, nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *VmwareCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collectMem(ch); err != nil { + log.Error("failed collecting vmware memory metrics:", desc, err) + return err + } + if desc, err := c.collectCpu(ch); err != nil { + log.Error("failed collecting vmware cpu metrics:", desc, err) + return err + } + return nil +} + +type Win32_PerfRawData_vmGuestLib_VMem struct { + MemActiveMB uint64 + MemBalloonedMB uint64 + MemLimitMB uint64 + MemMappedMB uint64 + MemOverheadMB uint64 + MemReservationMB uint64 + MemSharedMB uint64 + MemSharedSavedMB uint64 + MemShares uint64 + MemSwappedMB uint64 + MemTargetSizeMB uint64 + MemUsedMB uint64 +} + +type Win32_PerfRawData_vmGuestLib_VCPU struct { + CpuLimitMHz uint64 + CpuReservationMHz uint64 + CpuShares uint64 + CpuStolenMs uint64 + CpuTimePercents uint64 + EffectiveVMSpeedMHz uint64 + HostProcessorSpeedMHz uint64 +} + +func (c *VmwareCollector) collectMem(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_vmGuestLib_VMem + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + if len(dst) == 0 { + return nil, errors.New("WMI query returned empty result set") + } + + ch <- prometheus.MustNewConstMetric( + c.MemActive, + prometheus.GaugeValue, + mbToBytes(dst[0].MemActiveMB), + ) + + ch <- prometheus.MustNewConstMetric( + c.MemBallooned, + prometheus.GaugeValue, + mbToBytes(dst[0].MemBalloonedMB), + ) + + ch <- prometheus.MustNewConstMetric( + c.MemLimit, + prometheus.GaugeValue, + mbToBytes(dst[0].MemLimitMB), + ) + + ch <- prometheus.MustNewConstMetric( + c.MemMapped, + prometheus.GaugeValue, + mbToBytes(dst[0].MemMappedMB), + ) + + ch <- prometheus.MustNewConstMetric( + c.MemOverhead, + prometheus.GaugeValue, + mbToBytes(dst[0].MemOverheadMB), + ) + + ch <- prometheus.MustNewConstMetric( + c.MemReservation, + prometheus.GaugeValue, + mbToBytes(dst[0].MemReservationMB), + ) + + ch <- prometheus.MustNewConstMetric( + c.MemShared, + prometheus.GaugeValue, + mbToBytes(dst[0].MemSharedMB), + ) + + ch <- prometheus.MustNewConstMetric( + c.MemSharedSaved, + prometheus.GaugeValue, + mbToBytes(dst[0].MemSharedSavedMB), + ) + + ch <- prometheus.MustNewConstMetric( + c.MemShares, + prometheus.GaugeValue, + float64(dst[0].MemShares), + ) + + ch <- prometheus.MustNewConstMetric( + c.MemSwapped, + prometheus.GaugeValue, + mbToBytes(dst[0].MemSwappedMB), + ) + + ch <- prometheus.MustNewConstMetric( + c.MemTargetSize, + prometheus.GaugeValue, + mbToBytes(dst[0].MemTargetSizeMB), + ) + + ch <- prometheus.MustNewConstMetric( + c.MemUsed, + prometheus.GaugeValue, + mbToBytes(dst[0].MemUsedMB), + ) + + return nil, nil +} + +func mbToBytes(mb uint64) float64 { + return float64(mb * 1024 * 1024) +} + +func (c *VmwareCollector) collectCpu(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_vmGuestLib_VCPU + q := queryAll(&dst) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + if len(dst) == 0 { + return nil, errors.New("WMI query returned empty result set") + } + + ch <- prometheus.MustNewConstMetric( + c.CpuLimitMHz, + prometheus.GaugeValue, + float64(dst[0].CpuLimitMHz), + ) + + ch <- prometheus.MustNewConstMetric( + c.CpuReservationMHz, + prometheus.GaugeValue, + float64(dst[0].CpuReservationMHz), + ) + + ch <- prometheus.MustNewConstMetric( + c.CpuShares, + prometheus.GaugeValue, + float64(dst[0].CpuShares), + ) + + ch <- prometheus.MustNewConstMetric( + c.CpuStolenTotal, + prometheus.CounterValue, + float64(dst[0].CpuStolenMs)*ticksToSecondsScaleFactor, + ) + + ch <- prometheus.MustNewConstMetric( + c.CpuTimeTotal, + prometheus.CounterValue, + float64(dst[0].CpuTimePercents)*ticksToSecondsScaleFactor, + ) + + ch <- prometheus.MustNewConstMetric( + c.EffectiveVMSpeedMHz, + prometheus.GaugeValue, + float64(dst[0].EffectiveVMSpeedMHz), + ) + + ch <- prometheus.MustNewConstMetric( + c.HostProcessorSpeedMHz, + prometheus.GaugeValue, + float64(dst[0].HostProcessorSpeedMHz), + ) + + return nil, nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/collector/wmi.go b/vendor/github.com/prometheus-community/windows_exporter/collector/wmi.go new file mode 100644 index 000000000000..615db1f78a2b --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/collector/wmi.go @@ -0,0 +1,63 @@ +package collector + +import ( + "bytes" + "reflect" + + "github.com/prometheus/common/log" +) + +func className(src interface{}) string { + s := reflect.Indirect(reflect.ValueOf(src)) + t := s.Type() + if s.Kind() == reflect.Slice { + t = t.Elem() + } + return t.Name() +} + +func queryAll(src interface{}) string { + var b bytes.Buffer + b.WriteString("SELECT * FROM ") + b.WriteString(className(src)) + + log.Debugf("Generated WMI query %s", b.String()) + return b.String() +} + +func queryAllForClass(src interface{}, class string) string { + var b bytes.Buffer + b.WriteString("SELECT * FROM ") + b.WriteString(class) + + log.Debugf("Generated WMI query %s", b.String()) + return b.String() +} + +func queryAllWhere(src interface{}, where string) string { + var b bytes.Buffer + b.WriteString("SELECT * FROM ") + b.WriteString(className(src)) + + if where != "" { + b.WriteString(" WHERE ") + b.WriteString(where) + } + + log.Debugf("Generated WMI query %s", b.String()) + return b.String() +} + +func queryAllForClassWhere(src interface{}, class string, where string) string { + var b bytes.Buffer + b.WriteString("SELECT * FROM ") + b.WriteString(class) + + if where != "" { + b.WriteString(" WHERE ") + b.WriteString(where) + } + + log.Debugf("Generated WMI query %s", b.String()) + return b.String() +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/config/config.go b/vendor/github.com/prometheus-community/windows_exporter/config/config.go new file mode 100644 index 000000000000..195858429d4d --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/config/config.go @@ -0,0 +1,107 @@ +// Copyright 2018 Prometheus Team +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package config + +import ( + "io/ioutil" + "os" + + "github.com/prometheus/common/log" + "gopkg.in/alecthomas/kingpin.v2" + "gopkg.in/yaml.v2" +) + +type getFlagger interface { + GetFlag(name string) *kingpin.FlagClause +} + +// Resolver represents a configuration file resolver for kingpin. +type Resolver struct { + flags map[string]string +} + +// NewResolver returns a Resolver structure. +func NewResolver(file string) (*Resolver, error) { + flags := map[string]string{} + log.Infof("Loading configuration file: %v", file) + if _, err := os.Stat(file); err != nil { + return nil, err + } + b, err := ioutil.ReadFile(file) + if err != nil { + return nil, err + } + + var rawValues map[string]interface{} + err = yaml.Unmarshal(b, &rawValues) + if err != nil { + return nil, err + } + // Flatten nested YAML values + flattenedValues := flatten(rawValues) + for k, v := range flattenedValues { + if _, ok := flags[k]; !ok { + flags[k] = v + } + } + return &Resolver{flags: flags}, nil +} + +// NewResolver returns a Resolver structure. +func NewResolverFromString(config string) (*Resolver, error) { + flags := map[string]string{} + var rawValues map[string]interface{} + err := yaml.Unmarshal([]byte(config), &rawValues) + if err != nil { + return nil, err + } + // Flatten nested YAML values + flattenedValues := flatten(rawValues) + for k, v := range flattenedValues { + if _, ok := flags[k]; !ok { + flags[k] = v + } + } + return &Resolver{flags: flags}, nil +} + +// NewResolver returns a Resolver structure. +func NewResolverFromMap(config map[string]string) (*Resolver, error) { + return &Resolver{flags: config}, nil +} + +func (c *Resolver) setDefault(v getFlagger) { + for name, value := range c.flags { + f := v.GetFlag(name) + if f != nil { + f.Default(value) + } + } +} + +// Bind sets active flags with their default values from the configuration file(s). +func (c *Resolver) Bind(app *kingpin.Application, args []string) error { + // Parse the command line arguments to get the selected command. + pc, err := app.ParseContext(args) + if err != nil { + return err + } + + c.setDefault(app) + if pc.SelectedCommand != nil { + c.setDefault(pc.SelectedCommand) + } + + return nil +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/config/flatten.go b/vendor/github.com/prometheus-community/windows_exporter/config/flatten.go new file mode 100644 index 000000000000..382f22d91409 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/config/flatten.go @@ -0,0 +1,61 @@ +package config + +import "fmt" + +// flatten flattens the nested struct. +// +// All keys will be joined by dot +// e.g. {"a": {"b":"c"}} => {"a.b":"c"} +// or {"a": {"b":[1,2]}} => {"a.b.0":1, "a.b.1": 2} +func flatten(data map[string]interface{}) map[string]string { + ret := make(map[string]string) + for k, v := range data { + switch typed := v.(type) { + case map[interface{}]interface{}: + for fk, fv := range flatten(convertMap(typed)) { + ret[fmt.Sprintf("%s.%s", k, fk)] = fv + } + case map[string]interface{}: + for fk, fv := range flatten(typed) { + ret[fmt.Sprintf("%s.%s", k, fk)] = fv + } + case []interface{}: + for fk, fv := range flattenSlice(typed) { + ret[fmt.Sprintf("%s.%s", k, fk)] = fv + } + default: + ret[k] = fmt.Sprint(typed) + } + } + return ret +} +func flattenSlice(data []interface{}) map[string]string { + ret := make(map[string]string) + for idx, v := range data { + switch typed := v.(type) { + case map[interface{}]interface{}: + for fk, fv := range flatten(convertMap(typed)) { + ret[fmt.Sprintf("%d,%s", idx, fk)] = fv + } + case map[string]interface{}: + for fk, fv := range flatten(typed) { + ret[fmt.Sprintf("%d,%s", idx, fk)] = fv + } + case []interface{}: + for fk, fv := range flattenSlice(typed) { + ret[fmt.Sprintf("%d,%s", idx, fk)] = fv + } + default: + ret[fmt.Sprint(idx)] = fmt.Sprint(typed) + } + } + return ret +} + +func convertMap(originalMap map[interface{}]interface{}) map[string]interface{} { + convertedMap := map[string]interface{}{} + for key, value := range originalMap { + convertedMap[key.(string)] = value + } + return convertedMap +} diff --git a/vendor/github.com/prometheus-community/windows_exporter/exporter/exporter.go b/vendor/github.com/prometheus-community/windows_exporter/exporter/exporter.go new file mode 100644 index 000000000000..5828f2d2d627 --- /dev/null +++ b/vendor/github.com/prometheus-community/windows_exporter/exporter/exporter.go @@ -0,0 +1,546 @@ +package exporter + +import ( + "encoding/json" + "fmt" + "net/http" + "os" + "sort" + "strconv" + "strings" + "sync" + "time" + + "github.com/StackExchange/wmi" + "github.com/prometheus-community/windows_exporter/collector" + "github.com/prometheus-community/windows_exporter/config" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/prometheus/common/log" + "github.com/prometheus/common/version" + "golang.org/x/sys/windows/svc" + "gopkg.in/alecthomas/kingpin.v2" +) + +type WindowsCollector struct { + MaxScrapeDuration time.Duration + Collectors map[string]collector.Collector +} + +// Same struct prometheus uses for their /version endpoint. +// Separate copy to avoid pulling all of prometheus as a dependency +type prometheusVersion struct { + Version string `json:"version"` + Revision string `json:"revision"` + Branch string `json:"branch"` + BuildUser string `json:"buildUser"` + BuildDate string `json:"buildDate"` + GoVersion string `json:"goVersion"` +} + +const ( + defaultCollectors = "cpu,cs,logical_disk,net,os,service,system,textfile" + defaultCollectorsPlaceholder = "[defaults]" + serviceName = "windows_exporter" +) + +var ( + scrapeDurationDesc = prometheus.NewDesc( + prometheus.BuildFQName(collector.Namespace, "exporter", "collector_duration_seconds"), + "windows_exporter: Duration of a collection.", + []string{"collector"}, + nil, + ) + scrapeSuccessDesc = prometheus.NewDesc( + prometheus.BuildFQName(collector.Namespace, "exporter", "collector_success"), + "windows_exporter: Whether the collector was successful.", + []string{"collector"}, + nil, + ) + scrapeTimeoutDesc = prometheus.NewDesc( + prometheus.BuildFQName(collector.Namespace, "exporter", "collector_timeout"), + "windows_exporter: Whether the collector timed out.", + []string{"collector"}, + nil, + ) + snapshotDuration = prometheus.NewDesc( + prometheus.BuildFQName(collector.Namespace, "exporter", "perflib_snapshot_duration_seconds"), + "Duration of perflib snapshot capture", + nil, + nil, + ) +) + +// Describe sends all the descriptors of the collectors included to +// the provided channel. +func (coll WindowsCollector) Describe(ch chan<- *prometheus.Desc) { + ch <- scrapeDurationDesc + ch <- scrapeSuccessDesc +} + +type collectorOutcome int + +const ( + pending collectorOutcome = iota + success + failed +) + +// Collect sends the collected metrics from each of the collectors to +// prometheus. +func (coll WindowsCollector) Collect(ch chan<- prometheus.Metric) { + t := time.Now() + cs := make([]string, 0, len(coll.Collectors)) + for name := range coll.Collectors { + cs = append(cs, name) + } + + scrapeContext, err := collector.PrepareScrapeContext(cs) + ch <- prometheus.MustNewConstMetric( + snapshotDuration, + prometheus.GaugeValue, + time.Since(t).Seconds(), + ) + if err != nil { + ch <- prometheus.NewInvalidMetric(scrapeSuccessDesc, fmt.Errorf("failed to prepare scrape: %v", err)) + return + } + + wg := sync.WaitGroup{} + wg.Add(len(coll.Collectors)) + collectorOutcomes := make(map[string]collectorOutcome) + for name := range coll.Collectors { + collectorOutcomes[name] = pending + } + + metricsBuffer := make(chan prometheus.Metric) + l := sync.Mutex{} + finished := false + go func() { + for m := range metricsBuffer { + l.Lock() + if !finished { + ch <- m + } + l.Unlock() + } + }() + + for name, c := range coll.Collectors { + go func(name string, c collector.Collector) { + defer wg.Done() + outcome := execute(name, c, scrapeContext, metricsBuffer) + l.Lock() + if !finished { + collectorOutcomes[name] = outcome + } + l.Unlock() + }(name, c) + } + + allDone := make(chan struct{}) + go func() { + wg.Wait() + close(allDone) + close(metricsBuffer) + }() + + // Wait until either all collectors finish, or timeout expires + select { + case <-allDone: + case <-time.After(coll.MaxScrapeDuration): + } + + l.Lock() + finished = true + + remainingCollectorNames := make([]string, 0) + for name, outcome := range collectorOutcomes { + var successValue, timeoutValue float64 + if outcome == pending { + timeoutValue = 1.0 + remainingCollectorNames = append(remainingCollectorNames, name) + } + if outcome == success { + successValue = 1.0 + } + + ch <- prometheus.MustNewConstMetric( + scrapeSuccessDesc, + prometheus.GaugeValue, + successValue, + name, + ) + ch <- prometheus.MustNewConstMetric( + scrapeTimeoutDesc, + prometheus.GaugeValue, + timeoutValue, + name, + ) + } + + if len(remainingCollectorNames) > 0 { + log.Warn("Collection timed out, still waiting for ", remainingCollectorNames) + } + + l.Unlock() +} + +func execute(name string, c collector.Collector, ctx *collector.ScrapeContext, ch chan<- prometheus.Metric) collectorOutcome { + t := time.Now() + err := c.Collect(ctx, ch) + duration := time.Since(t).Seconds() + ch <- prometheus.MustNewConstMetric( + scrapeDurationDesc, + prometheus.GaugeValue, + duration, + name, + ) + + if err != nil { + log.Errorf("collector %s failed after %fs: %s", name, duration, err) + return failed + } + log.Debugf("collector %s succeeded after %fs.", name, duration) + return success +} + +func expandEnabledCollectors(enabled string) []string { + expanded := strings.Replace(enabled, defaultCollectorsPlaceholder, defaultCollectors, -1) + separated := strings.Split(expanded, ",") + unique := map[string]bool{} + for _, s := range separated { + if s != "" { + unique[s] = true + } + } + result := make([]string, 0, len(unique)) + for s := range unique { + result = append(result, s) + } + return result +} + +func loadCollectors(list string, config map[string]collector.Config) (map[string]collector.Collector, error) { + collectors := map[string]collector.Collector{} + enabled := expandEnabledCollectors(list) + for _, name := range enabled { + // TODO this could be cleaned up if we decide to go this route + if cb, exists := config[name]; exists { + c, err := cb.Build() + if err != nil { + return nil, err + } + collectors[name] = c + } else { + c, err := collector.Build(name) + if err != nil { + return nil, err + } + collectors[name] = c + } + } + return collectors, nil +} + +func initWbem() { + // This initialization prevents a memory leak on WMF 5+. See + // https://github.com/prometheus-community/windows_exporter/issues/77 and + // linked issues for details. + log.Debugf("Initializing SWbemServices") + s, err := wmi.InitializeSWbemServices(wmi.DefaultClient) + if err != nil { + log.Fatal(err) + } + wmi.DefaultClient.AllowMissingFields = true + wmi.DefaultClient.SWbemServicesClient = s +} + +func GenerateConfigs() map[string]collector.Config { + kingpinApp := kingpin.New("windows_exporter", "") + cm := collector.GenerateConfigs(kingpinApp) + kingpinApp.Parse([]string{}) + return cm +} + +// Used to instantiate a new collector for use in a library +func NewWindowsCollector(name string, enabledCollectors string, configMap map[string]collector.Config) (*WindowsCollector, error) { + if enabledCollectors == "" { + enabledCollectors = defaultCollectors + } + initWbem() + if name == "" { + name = "windows_exporter" + } + collectors, err := loadCollectors(enabledCollectors, configMap) + if err != nil { + log.Fatalf("Couldn't load collectors: %s", err) + } + + log.Infof("Enabled collectors: %v", strings.Join(keys(collectors), ", ")) + return &WindowsCollector{ + Collectors: collectors, + MaxScrapeDuration: time.Duration(10 * float64(time.Second)), + }, nil +} + +func StartExecutable() { + + kingpinApp := kingpin.New("windows_exporter", "") + var ( + configFile = kingpinApp.Flag( + "config.file", + "YAML configuration file to use. Values set in this file will be overriden by CLI flags.", + ).String() + listenAddress = kingpinApp.Flag( + "telemetry.addr", + "host:port for exporter.", + ).Default(":9182").String() + metricsPath = kingpinApp.Flag( + "telemetry.path", + "URL path for surfacing collected metrics.", + ).Default("/metrics").String() + maxRequests = kingpinApp.Flag( + "telemetry.max-requests", + "Maximum number of concurrent requests. 0 to disable.", + ).Default("5").Int() + enabledCollectors = kingpinApp.Flag( + "collectors.enabled", + "Comma-separated list of collectors to use. Use '[defaults]' as a placeholder for all the collectors enabled by default."). + Default(defaultCollectors).String() + printCollectors = kingpinApp.Flag( + "collectors.print", + "If true, print available collectors and exit.", + ).Bool() + timeoutMargin = kingpinApp.Flag( + "scrape.timeout-margin", + "Seconds to subtract from the timeout allowed by the client. Tune to allow for overhead or high loads.", + ).Default("0.5").Float64() + ) + // We can treat loading from config as the same as kingpin + configMap := collector.GenerateConfigs(kingpinApp) + log.AddFlags(kingpin.CommandLine) + kingpinApp.Version(version.Print("windows_exporter")) + kingpinApp.HelpFlag.Short('h') + + // Load values from configuration file(s). Executable flags must first be parsed, in order + // to load the specified file(s). + if *configFile != "" { + resolver, err := config.NewResolver(*configFile) + if err != nil { + log.Fatalf("could not load config file: %v\n", err) + } + err = resolver.Bind(kingpin.CommandLine, os.Args[1:]) + if err != nil { + log.Fatalf("%v\n", err) + } + // Parse flags once more to include those discovered in configuration file(s). + kingpinApp.Parse(os.Args[1:]) + } + + kingpinApp.Parse(os.Args[1:]) + if *printCollectors { + collectors := collector.Available() + collectorNames := make(sort.StringSlice, 0, len(collectors)) + for _, n := range collectors { + collectorNames = append(collectorNames, n) + } + collectorNames.Sort() + fmt.Printf("Available collectors:\n") + for _, n := range collectorNames { + fmt.Printf(" - %s\n", n) + } + return + } + + initWbem() + + isInteractive, err := svc.IsAnInteractiveSession() + if err != nil { + log.Fatal(err) + } + + stopCh := make(chan bool) + if !isInteractive { + go func() { + err = svc.Run(serviceName, &windowsExporterService{stopCh: stopCh}) + if err != nil { + log.Errorf("Failed to start service: %v", err) + } + }() + } + + collectors, err := loadCollectors(*enabledCollectors, configMap) + if err != nil { + log.Fatalf("Couldn't load collectors: %s", err) + } + + log.Infof("Enabled collectors: %v", strings.Join(keys(collectors), ", ")) + + h := &metricsHandler{ + timeoutMargin: *timeoutMargin, + collectorFactory: func(timeout time.Duration, requestedCollectors []string) (error, *WindowsCollector) { + filteredCollectors := make(map[string]collector.Collector) + // scrape all enabled collectors if no collector is requested + if len(requestedCollectors) == 0 { + filteredCollectors = collectors + } + for _, name := range requestedCollectors { + col, exists := collectors[name] + if !exists { + return fmt.Errorf("unavailable collector: %s", name), nil + } + filteredCollectors[name] = col + } + return nil, &WindowsCollector{ + Collectors: filteredCollectors, + MaxScrapeDuration: timeout, + } + }, + } + + http.HandleFunc(*metricsPath, withConcurrencyLimit(*maxRequests, h.ServeHTTP)) + http.HandleFunc("/health", healthCheck) + http.HandleFunc("/version", func(w http.ResponseWriter, r *http.Request) { + // we can't use "version" directly as it is a package, and not an object that + // can be serialized. + err := json.NewEncoder(w).Encode(prometheusVersion{ + Version: version.Version, + Revision: version.Revision, + Branch: version.Branch, + BuildUser: version.BuildUser, + BuildDate: version.BuildDate, + GoVersion: version.GoVersion, + }) + if err != nil { + http.Error(w, fmt.Sprintf("error encoding JSON: %s", err), http.StatusInternalServerError) + } + }) + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + _, _ = w.Write([]byte(` +windows_exporter + +

windows_exporter

+

Metrics

+

` + version.Info() + `

+ +`)) + }) + + log.Infoln("Starting windows_exporter", version.Info()) + log.Infoln("Build context", version.BuildContext()) + + go func() { + log.Infoln("Starting server on", *listenAddress) + log.Fatalf("cannot start windows_exporter: %s", http.ListenAndServe(*listenAddress, nil)) + }() + + for { + if <-stopCh { + log.Info("Shutting down windows_exporter") + break + } + } +} + +func healthCheck(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + _, err := fmt.Fprintln(w, `{"status":"ok"}`) + if err != nil { + log.Debugf("Failed to write to stream: %v", err) + } +} + +func keys(m map[string]collector.Collector) []string { + ret := make([]string, 0, len(m)) + for key := range m { + ret = append(ret, key) + } + return ret +} + +func withConcurrencyLimit(n int, next http.HandlerFunc) http.HandlerFunc { + if n <= 0 { + return next + } + + sem := make(chan struct{}, n) + return func(w http.ResponseWriter, r *http.Request) { + select { + case sem <- struct{}{}: + defer func() { <-sem }() + default: + w.WriteHeader(http.StatusServiceUnavailable) + _, _ = w.Write([]byte("Too many concurrent requests")) + return + } + next(w, r) + } +} + +type windowsExporterService struct { + stopCh chan<- bool +} + +func (s *windowsExporterService) Execute(args []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (ssec bool, errno uint32) { + const cmdsAccepted = svc.AcceptStop | svc.AcceptShutdown + changes <- svc.Status{State: svc.StartPending} + changes <- svc.Status{State: svc.Running, Accepts: cmdsAccepted} +loop: + for { + select { + case c := <-r: + switch c.Cmd { + case svc.Interrogate: + changes <- c.CurrentStatus + case svc.Stop, svc.Shutdown: + s.stopCh <- true + break loop + default: + log.Error(fmt.Sprintf("unexpected control request #%d", c)) + } + } + } + changes <- svc.Status{State: svc.StopPending} + return +} + +type metricsHandler struct { + timeoutMargin float64 + collectorFactory func(timeout time.Duration, requestedCollectors []string) (error, *WindowsCollector) +} + +func (mh *metricsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + const defaultTimeout = 10.0 + + var timeoutSeconds float64 + if v := r.Header.Get("X-Prometheus-Scrape-Timeout-Seconds"); v != "" { + var err error + timeoutSeconds, err = strconv.ParseFloat(v, 64) + if err != nil { + log.Warnf("Couldn't parse X-Prometheus-Scrape-Timeout-Seconds: %q. Defaulting timeout to %f", v, defaultTimeout) + } + } + if timeoutSeconds == 0 { + timeoutSeconds = defaultTimeout + } + timeoutSeconds = timeoutSeconds - mh.timeoutMargin + + reg := prometheus.NewRegistry() + err, wc := mh.collectorFactory(time.Duration(timeoutSeconds*float64(time.Second)), r.URL.Query()["collect[]"]) + if err != nil { + log.Warnln("Couldn't create filtered metrics handler: ", err) + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(fmt.Sprintf("Couldn't create filtered metrics handler: %s", err))) + return + } + reg.MustRegister(wc) + reg.MustRegister( + prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{}), + prometheus.NewGoCollector(), + version.NewCollector("windows_exporter"), + ) + + h := promhttp.HandlerFor(reg, promhttp.HandlerOpts{}) + h.ServeHTTP(w, r) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 65ec7d2c6148..1e4cf8ab1b59 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -35,6 +35,24 @@ github.com/Azure/go-autorest/tracing # github.com/Microsoft/go-winio v0.4.16 github.com/Microsoft/go-winio github.com/Microsoft/go-winio/pkg/guid +# github.com/Microsoft/hcsshim v0.8.6 +github.com/Microsoft/hcsshim +github.com/Microsoft/hcsshim/internal/guestrequest +github.com/Microsoft/hcsshim/internal/guid +github.com/Microsoft/hcsshim/internal/hcs +github.com/Microsoft/hcsshim/internal/hcserror +github.com/Microsoft/hcsshim/internal/hns +github.com/Microsoft/hcsshim/internal/interop +github.com/Microsoft/hcsshim/internal/logfields +github.com/Microsoft/hcsshim/internal/longpath +github.com/Microsoft/hcsshim/internal/mergemaps +github.com/Microsoft/hcsshim/internal/safefile +github.com/Microsoft/hcsshim/internal/schema1 +github.com/Microsoft/hcsshim/internal/schema2 +github.com/Microsoft/hcsshim/internal/timeout +github.com/Microsoft/hcsshim/internal/wclayer +# github.com/StackExchange/wmi v0.0.0-20180725035823-b12b22c5341f +github.com/StackExchange/wmi # github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 github.com/alecthomas/template github.com/alecthomas/template/parse @@ -160,6 +178,8 @@ github.com/davecgh/go-spew/spew github.com/dgrijalva/jwt-go # github.com/digitalocean/godo v1.57.0 github.com/digitalocean/godo +# github.com/dimchansky/utfbom v1.1.0 +github.com/dimchansky/utfbom # github.com/docker/distribution v2.7.1+incompatible github.com/docker/distribution/digestset github.com/docker/distribution/reference @@ -216,6 +236,9 @@ github.com/go-kit/kit/log/level github.com/go-logfmt/logfmt # github.com/go-logr/logr v0.4.0 github.com/go-logr/logr +# github.com/go-ole/go-ole v1.2.4 +github.com/go-ole/go-ole +github.com/go-ole/go-ole/oleutil # github.com/go-sql-driver/mysql v1.5.0 github.com/go-sql-driver/mysql # github.com/godbus/dbus v0.0.0-20190402143921-271e53dc4968 @@ -458,6 +481,9 @@ github.com/justwatchcom/elasticsearch_exporter/pkg/clusterinfo # github.com/leodido/ragel-machinery v0.0.0-20181214104525-299bdde78165 github.com/leodido/ragel-machinery github.com/leodido/ragel-machinery/parser +# github.com/leoluk/perflib_exporter v0.1.0 +github.com/leoluk/perflib_exporter/collector +github.com/leoluk/perflib_exporter/perflib # github.com/lib/pq v1.3.0 github.com/lib/pq github.com/lib/pq/oid @@ -544,6 +570,11 @@ github.com/pmezard/go-difflib/difflib # github.com/pquerna/cachecontrol v0.0.0-20200819021114-67c6ae64274f github.com/pquerna/cachecontrol github.com/pquerna/cachecontrol/cacheobject +# github.com/prometheus-community/windows_exporter v0.0.0-00010101000000-000000000000 => github.com/grafana/windows_exporter v0.15.1-0.20210325142439-9e8f66d53433 +## explicit +github.com/prometheus-community/windows_exporter/collector +github.com/prometheus-community/windows_exporter/config +github.com/prometheus-community/windows_exporter/exporter # github.com/prometheus/client_golang v1.9.0 ## explicit github.com/prometheus/client_golang/prometheus @@ -1338,6 +1369,7 @@ sigs.k8s.io/yaml # gopkg.in/yaml.v2 => github.com/rfratto/go-yaml v0.0.0-20200521142311-984fc90c8a04 # github.com/google/dnsmasq_exporter => github.com/grafana/dnsmasq_exporter v0.2.1-0.20201029182940-e5169b835a23 # github.com/ncabatoff/process-exporter => github.com/grafana/process-exporter v0.7.3-0.20210106202358-831154072e2a +# github.com/prometheus-community/windows_exporter => github.com/grafana/windows_exporter v0.15.1-0.20210325142439-9e8f66d53433 # github.com/prometheus/mysqld_exporter => github.com/grafana/mysqld_exporter v0.12.2-0.20201015182516-5ac885b2d38a # github.com/wrouesnel/postgres_exporter => github.com/grafana/postgres_exporter v0.8.1-0.20201106170118-5eedee00c1db # github.com/gomodule/redigo => github.com/gomodule/redigo v1.8.2