diff --git a/init/init.go b/init/init.go index 921b6802..183a5487 100755 --- a/init/init.go +++ b/init/init.go @@ -93,7 +93,7 @@ func sysInit(c *config.CloudConfig) (*config.CloudConfig, error) { } func MainInit() { - log.InitLogger() + log.InitDeferedLogger() log.Infof("MainInit() start") if err := RunInit(); err != nil { log.Fatal(err) @@ -414,6 +414,8 @@ func RunInit() error { return err } + log.SyslogReady(true) + return pidOne() } diff --git a/log/log.go b/log/log.go index b9339e91..f7310e5c 100755 --- a/log/log.go +++ b/log/log.go @@ -4,6 +4,8 @@ import ( "io" "os" + "fmt" + "github.com/Sirupsen/logrus" ) @@ -110,7 +112,15 @@ func WithFields(fields Fields) *logrus.Entry { return appLog.WithFields(logrus.Fields(fields)) } +// InitLogger sets up Logging to log to /dev/kmsg and to Syslog func InitLogger() { + InitDeferedLogger() + SyslogReady(false) +} + +// InitDeferedLogger sets up logging to /dev/kmsg and to an internal buffer +// which is then written to Syslog when signaled by SyslogReady() +func InitDeferedLogger() { if userHook != nil { return // we've already initialised it } @@ -148,3 +158,17 @@ func InitLogger() { thisLog.Debugf("START: %v in %s", os.Args, pwd) } + +// SyslogReady tells the storeing User hook to start writing to syslog +func SyslogReady(logHook bool) error { + if userHook != nil { + if logHook { + logrus.Infof("Starting Syslog Hook") + fmt.Fprintf(appLog.Out, "------------ Starting defered Syslog Hook (%s) ----------------\n", os.Args[0]) + } else { + fmt.Fprintf(appLog.Out, "------------ Starting Syslog Hook (%s) ----------------\n", os.Args[0]) + } + return userHook.LogSystemReady() + } + return nil +} diff --git a/log/showuserlog.go b/log/showuserlog.go index 7e6fa2be..2e1c6de7 100644 --- a/log/showuserlog.go +++ b/log/showuserlog.go @@ -2,32 +2,51 @@ package log import ( "fmt" - "github.com/Sirupsen/logrus" + "log/syslog" "os" + + "github.com/Sirupsen/logrus" + logrus_syslog "github.com/Sirupsen/logrus/hooks/syslog" ) -// ShowuserlogHook writes all levels of logrus entries to a file for later analysis +// ShowuserlogHook stores all levels of logrus entries in memory until its told the RancherOS logging system is ready +// then it replays them to be logged type ShowuserlogHook struct { - Level logrus.Level + Level logrus.Level + syslogHook *logrus_syslog.SyslogHook + storedEntries []*logrus.Entry } +// NewShowuserlogHook creates a new hook for use func NewShowuserlogHook(l logrus.Level) (*ShowuserlogHook, error) { - return &ShowuserlogHook{l}, nil + return &ShowuserlogHook{l, nil, []*logrus.Entry{}}, nil } +// Fire is called by logrus when the Hook is active func (hook *ShowuserlogHook) Fire(entry *logrus.Entry) error { line, err := entry.String() if err != nil { fmt.Fprintf(os.Stderr, "Unable to read entry, %v", err) return err } - if entry.Level <= hook.Level { - fmt.Printf("> %s", line) + fmt.Printf("SVEN %s", line) } + + if hook.syslogHook == nil { + hook.storedEntries = append(hook.storedEntries, entry) + } else { + err := hook.syslogHook.Fire(entry) + if err != nil { + fmt.Fprintf(os.Stderr, "LOGERR: Unable to write %s, %v", line, err) + return err + } + } + return nil } +// Levels returns all log levels, so we can process them ourselves func (hook *ShowuserlogHook) Levels() []logrus.Level { return []logrus.Level{ logrus.DebugLevel, @@ -38,3 +57,21 @@ func (hook *ShowuserlogHook) Levels() []logrus.Level { logrus.PanicLevel, } } + +// Set up Syslog Hook, and replay any stored entries. +func (hook *ShowuserlogHook) LogSystemReady() error { + if hook.syslogHook == nil { + h, err := logrus_syslog.NewSyslogHook("", "", syslog.LOG_INFO, "") + if err != nil { + logrus.Debugf("error creating SyslogHook: %s", err) + return err + } + hook.syslogHook = h + + for _, entry := range hook.storedEntries { + hook.syslogHook.Fire(entry) + } + } + + return nil +} diff --git a/scripts/build-images b/scripts/build-images index 8353870e..478256a9 100755 --- a/scripts/build-images +++ b/scripts/build-images @@ -1,5 +1,5 @@ #!/bin/bash -set -e +set -ex export ARCH=${ARCH:-"amd64"} BASE=images diff --git a/scripts/global.cfg b/scripts/global.cfg index def6e2bd..efffcbd9 100755 --- a/scripts/global.cfg +++ b/scripts/global.cfg @@ -1 +1 @@ -APPEND rancher.autologin=tty1 rancher.autologin=ttyS0 rancher.autologin=ttyS1 console=tty0 console=ttyS0 console=ttyS1 printk.devkmsg=on ${APPEND} +APPEND rancher.debug=true rancher.autologin=tty1 rancher.autologin=ttyS0 rancher.autologin=ttyS1 console=tty0 console=ttyS0 console=ttyS1 printk.devkmsg=on ${APPEND} diff --git a/scripts/prepare b/scripts/prepare index a05c292b..776ea59b 100755 --- a/scripts/prepare +++ b/scripts/prepare @@ -1,5 +1,5 @@ #!/bin/bash -set -e +set -ex source $(dirname $0)/version diff --git a/scripts/tar-images b/scripts/tar-images index dc1b0563..b0f84d2e 100755 --- a/scripts/tar-images +++ b/scripts/tar-images @@ -1,5 +1,5 @@ #!/bin/bash -set -e +set -ex cd $(dirname $0)/.. diff --git a/trash.conf b/trash.conf index 847c94fc..e1aa549f 100644 --- a/trash.conf +++ b/trash.conf @@ -1,6 +1,6 @@ github.com/Microsoft/go-winio v0.1.0 github.com/RackSec/srslog 259aed10dfa74ea2961eddd1d9847619f6e98837 -github.com/Sirupsen/logrus v0.11.0 +github.com/Sirupsen/logrus v0.11.5 github.com/boltdb/bolt v1.2.0 github.com/cloudfoundry-incubator/candiedyaml 01cbc92901719f599b11f3a7e3b1768d7002b0bb https://github.com/rancher/candiedyaml github.com/cloudfoundry/gosigar 3ed7c74352dae6dc00bdc8c74045375352e3ec05 @@ -53,7 +53,7 @@ github.com/vishvananda/netns 54f0e4339ce73702a0607f49922aaa1e749b418d github.com/xeipuuv/gojsonpointer e0fe6f68307607d540ed8eac07a342c33fa1b54a github.com/xeipuuv/gojsonreference e02fc20de94c78484cd5ffb007f8af96be030a45 github.com/xeipuuv/gojsonschema ac452913faa25c08bb78810d3e6f88b8a39f8f25 -github.com/SvenDowideit/cpuid 399bf479aea1edfbfe0b686c514631b511f44641 +github.com/SvenDowideit/cpuid dfdb6dba69f48dd44c5cd831950be648f71162ca golang.org/x/crypto 2f3083f6163ef51179ad42ed523a18c9a1141467 golang.org/x/net 991d3e32f76f19ee6d9caadb3a22eae8d23315f7 https://github.com/golang/net.git golang.org/x/sys eb2c74142fd19a79b3f237334c7384d5167b1b46 https://github.com/golang/sys.git diff --git a/vendor/github.com/Sirupsen/logrus/.travis.yml b/vendor/github.com/Sirupsen/logrus/.travis.yml index dee4eb2c..804c5694 100644 --- a/vendor/github.com/Sirupsen/logrus/.travis.yml +++ b/vendor/github.com/Sirupsen/logrus/.travis.yml @@ -1,9 +1,7 @@ language: go go: - - 1.3 - - 1.4 - - 1.5 - 1.6 + - 1.7 - tip install: - go get -t ./... diff --git a/vendor/github.com/Sirupsen/logrus/CHANGELOG.md b/vendor/github.com/Sirupsen/logrus/CHANGELOG.md index f2c2bc21..747e4d89 100644 --- a/vendor/github.com/Sirupsen/logrus/CHANGELOG.md +++ b/vendor/github.com/Sirupsen/logrus/CHANGELOG.md @@ -1,3 +1,31 @@ +# 0.11.5 + +* feature: add writer and writerlevel to entry (#372) + +# 0.11.4 + +* bug: fix undefined variable on solaris (#493) + +# 0.11.3 + +* formatter: configure quoting of empty values (#484) +* formatter: configure quoting character (default is `"`) (#484) +* bug: fix not importing io correctly in non-linux environments (#481) + +# 0.11.2 + +* bug: fix windows terminal detection (#476) + +# 0.11.1 + +* bug: fix tty detection with custom out (#471) + +# 0.11.0 + +* performance: Use bufferpool to allocate (#370) +* terminal: terminal detection for app-engine (#343) +* feature: exit handler (#375) + # 0.10.0 * feature: Add a test hook (#180) diff --git a/vendor/github.com/Sirupsen/logrus/README.md b/vendor/github.com/Sirupsen/logrus/README.md index 126cd1fc..640cf61f 100644 --- a/vendor/github.com/Sirupsen/logrus/README.md +++ b/vendor/github.com/Sirupsen/logrus/README.md @@ -1,5 +1,11 @@ # Logrus :walrus: [![Build Status](https://travis-ci.org/Sirupsen/logrus.svg?branch=master)](https://travis-ci.org/Sirupsen/logrus) [![GoDoc](https://godoc.org/github.com/Sirupsen/logrus?status.svg)](https://godoc.org/github.com/Sirupsen/logrus) +**Seeing weird case-sensitive problems?** See [this +issue](https://github.com/sirupsen/logrus/issues/451#issuecomment-264332021). +This change has been reverted. I apologize for causing this. I greatly +underestimated the impact this would have. Logrus strives for stability and +backwards compatibility and failed to provide that. + Logrus is a structured logger for Go (golang), completely API compatible with the standard library logger. [Godoc][godoc]. **Please note the Logrus API is not yet stable (pre 1.0). Logrus itself is completely stable and has been used in @@ -81,8 +87,9 @@ func init() { // Log as JSON instead of the default ASCII formatter. log.SetFormatter(&log.JSONFormatter{}) - // Output to stderr instead of stdout, could also be a file. - log.SetOutput(os.Stderr) + // Output to stdout instead of the default stderr + // Can be any io.Writer, see below for File example + log.SetOutput(os.Stdout) // Only log the warning severity or above. log.SetLevel(log.WarnLevel) @@ -132,7 +139,15 @@ var log = logrus.New() func main() { // The API for setting attributes is a little different than the package level // exported logger. See Godoc. - log.Out = os.Stderr + log.Out = os.Stdout + + // You could set this to any `io.Writer` such as a file + // file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY, 0666) + // if err == nil { + // log.Out = file + // } else { + // log.Info("Failed to log to file, using default stderr") + // } log.WithFields(logrus.Fields{ "animal": "walrus", @@ -165,6 +180,20 @@ In general, with Logrus using any of the `printf`-family functions should be seen as a hint you should add a field, however, you can still use the `printf`-family functions with Logrus. +#### Default Fields + +Often it's helpful to have fields _always_ attached to log statements in an +application or parts of one. For example, you may want to always log the +`request_id` and `user_ip` in the context of a request. Instead of writing +`log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip})` on +every line, you can create a `logrus.Entry` to pass around instead: + +```go +requestLogger := log.WithFields(log.Fields{"request_id": request_id, user_ip: user_ip}) +requestLogger.Info("something happened on that request") # will log request_id and user_ip +requestLogger.Warn("something not great happened") +``` + #### Hooks You can add hooks for logging levels. For example to send errors to an exception @@ -200,40 +229,47 @@ Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/v | Hook | Description | | ----- | ----------- | -| [Airbrake](https://github.com/gemnasium/logrus-airbrake-hook) | Send errors to the Airbrake API V3. Uses the official [`gobrake`](https://github.com/airbrake/gobrake) behind the scenes. | | [Airbrake "legacy"](https://github.com/gemnasium/logrus-airbrake-legacy-hook) | Send errors to an exception tracking service compatible with the Airbrake API V2. Uses [`airbrake-go`](https://github.com/tobi/airbrake-go) behind the scenes. | -| [Papertrail](https://github.com/polds/logrus-papertrail-hook) | Send errors to the [Papertrail](https://papertrailapp.com) hosted logging service via UDP. | -| [Syslog](https://github.com/Sirupsen/logrus/blob/master/hooks/syslog/syslog.go) | Send errors to remote syslog server. Uses standard library `log/syslog` behind the scenes. | -| [Bugsnag](https://github.com/Shopify/logrus-bugsnag/blob/master/bugsnag.go) | Send errors to the Bugsnag exception tracking service. | -| [Sentry](https://github.com/evalphobia/logrus_sentry) | Send errors to the Sentry error logging and aggregation service. | -| [Hiprus](https://github.com/nubo/hiprus) | Send errors to a channel in hipchat. | -| [Logrusly](https://github.com/sebest/logrusly) | Send logs to [Loggly](https://www.loggly.com/) | -| [Slackrus](https://github.com/johntdyer/slackrus) | Hook for Slack chat. | -| [Journalhook](https://github.com/wercker/journalhook) | Hook for logging to `systemd-journald` | -| [Graylog](https://github.com/gemnasium/logrus-graylog-hook) | Hook for logging to [Graylog](http://graylog2.org/) | -| [Raygun](https://github.com/squirkle/logrus-raygun-hook) | Hook for logging to [Raygun.io](http://raygun.io/) | -| [LFShook](https://github.com/rifflock/lfshook) | Hook for logging to the local filesystem | -| [Honeybadger](https://github.com/agonzalezro/logrus_honeybadger) | Hook for sending exceptions to Honeybadger | -| [Mail](https://github.com/zbindenren/logrus_mail) | Hook for sending exceptions via mail | -| [Rollrus](https://github.com/heroku/rollrus) | Hook for sending errors to rollbar | -| [Fluentd](https://github.com/evalphobia/logrus_fluent) | Hook for logging to fluentd | -| [Mongodb](https://github.com/weekface/mgorus) | Hook for logging to mongodb | -| [Influxus] (http://github.com/vlad-doru/influxus) | Hook for concurrently logging to [InfluxDB] (http://influxdata.com/) | -| [InfluxDB](https://github.com/Abramovic/logrus_influxdb) | Hook for logging to influxdb | -| [Octokit](https://github.com/dorajistyle/logrus-octokit-hook) | Hook for logging to github via octokit | -| [DeferPanic](https://github.com/deferpanic/dp-logrus) | Hook for logging to DeferPanic | -| [Redis-Hook](https://github.com/rogierlommers/logrus-redis-hook) | Hook for logging to a ELK stack (through Redis) | +| [Airbrake](https://github.com/gemnasium/logrus-airbrake-hook) | Send errors to the Airbrake API V3. Uses the official [`gobrake`](https://github.com/airbrake/gobrake) behind the scenes. | +| [Amazon Kinesis](https://github.com/evalphobia/logrus_kinesis) | Hook for logging to [Amazon Kinesis](https://aws.amazon.com/kinesis/) | | [Amqp-Hook](https://github.com/vladoatanasov/logrus_amqp) | Hook for logging to Amqp broker (Like RabbitMQ) | -| [KafkaLogrus](https://github.com/goibibo/KafkaLogrus) | Hook for logging to kafka | -| [Typetalk](https://github.com/dragon3/logrus-typetalk-hook) | Hook for logging to [Typetalk](https://www.typetalk.in/) | +| [Bugsnag](https://github.com/Shopify/logrus-bugsnag/blob/master/bugsnag.go) | Send errors to the Bugsnag exception tracking service. | +| [DeferPanic](https://github.com/deferpanic/dp-logrus) | Hook for logging to DeferPanic | | [ElasticSearch](https://github.com/sohlich/elogrus) | Hook for logging to ElasticSearch| -| [Sumorus](https://github.com/doublefree/sumorus) | Hook for logging to [SumoLogic](https://www.sumologic.com/)| -| [Scribe](https://github.com/sagar8192/logrus-scribe-hook) | Hook for logging to [Scribe](https://github.com/facebookarchive/scribe)| -| [Logstash](https://github.com/bshuster-repo/logrus-logstash-hook) | Hook for logging to [Logstash](https://www.elastic.co/products/logstash) | -| [logz.io](https://github.com/ripcurld00d/logrus-logzio-hook) | Hook for logging to [logz.io](https://logz.io), a Log as a Service using Logstash | +| [Fluentd](https://github.com/evalphobia/logrus_fluent) | Hook for logging to fluentd | +| [Go-Slack](https://github.com/multiplay/go-slack) | Hook for logging to [Slack](https://slack.com) | +| [Graylog](https://github.com/gemnasium/logrus-graylog-hook) | Hook for logging to [Graylog](http://graylog2.org/) | +| [Hiprus](https://github.com/nubo/hiprus) | Send errors to a channel in hipchat. | +| [Honeybadger](https://github.com/agonzalezro/logrus_honeybadger) | Hook for sending exceptions to Honeybadger | +| [InfluxDB](https://github.com/Abramovic/logrus_influxdb) | Hook for logging to influxdb | +| [Influxus] (http://github.com/vlad-doru/influxus) | Hook for concurrently logging to [InfluxDB] (http://influxdata.com/) | +| [Journalhook](https://github.com/wercker/journalhook) | Hook for logging to `systemd-journald` | +| [KafkaLogrus](https://github.com/goibibo/KafkaLogrus) | Hook for logging to kafka | +| [LFShook](https://github.com/rifflock/lfshook) | Hook for logging to the local filesystem | +| [Logentries](https://github.com/jcftang/logentriesrus) | Hook for logging to [Logentries](https://logentries.com/) | +| [Logentrus](https://github.com/puddingfactory/logentrus) | Hook for logging to [Logentries](https://logentries.com/) | | [Logmatic.io](https://github.com/logmatic/logmatic-go) | Hook for logging to [Logmatic.io](http://logmatic.io/) | +| [Logrusly](https://github.com/sebest/logrusly) | Send logs to [Loggly](https://www.loggly.com/) | +| [Logstash](https://github.com/bshuster-repo/logrus-logstash-hook) | Hook for logging to [Logstash](https://www.elastic.co/products/logstash) | +| [Mail](https://github.com/zbindenren/logrus_mail) | Hook for sending exceptions via mail | +| [Mongodb](https://github.com/weekface/mgorus) | Hook for logging to mongodb | +| [NATS-Hook](https://github.com/rybit/nats_logrus_hook) | Hook for logging to [NATS](https://nats.io) | +| [Octokit](https://github.com/dorajistyle/logrus-octokit-hook) | Hook for logging to github via octokit | +| [Papertrail](https://github.com/polds/logrus-papertrail-hook) | Send errors to the [Papertrail](https://papertrailapp.com) hosted logging service via UDP. | +| [PostgreSQL](https://github.com/gemnasium/logrus-postgresql-hook) | Send logs to [PostgreSQL](http://postgresql.org) | | [Pushover](https://github.com/toorop/logrus_pushover) | Send error via [Pushover](https://pushover.net) | - +| [Raygun](https://github.com/squirkle/logrus-raygun-hook) | Hook for logging to [Raygun.io](http://raygun.io/) | +| [Redis-Hook](https://github.com/rogierlommers/logrus-redis-hook) | Hook for logging to a ELK stack (through Redis) | +| [Rollrus](https://github.com/heroku/rollrus) | Hook for sending errors to rollbar | +| [Scribe](https://github.com/sagar8192/logrus-scribe-hook) | Hook for logging to [Scribe](https://github.com/facebookarchive/scribe)| +| [Sentry](https://github.com/evalphobia/logrus_sentry) | Send errors to the Sentry error logging and aggregation service. | +| [Slackrus](https://github.com/johntdyer/slackrus) | Hook for Slack chat. | +| [Stackdriver](https://github.com/knq/sdhook) | Hook for logging to [Google Stackdriver](https://cloud.google.com/logging/) | +| [Sumorus](https://github.com/doublefree/sumorus) | Hook for logging to [SumoLogic](https://www.sumologic.com/)| +| [Syslog](https://github.com/Sirupsen/logrus/blob/master/hooks/syslog/syslog.go) | Send errors to remote syslog server. Uses standard library `log/syslog` behind the scenes. | +| [TraceView](https://github.com/evalphobia/logrus_appneta) | Hook for logging to [AppNeta TraceView](https://www.appneta.com/products/traceview/) | +| [Typetalk](https://github.com/dragon3/logrus-typetalk-hook) | Hook for logging to [Typetalk](https://www.typetalk.in/) | +| [logz.io](https://github.com/ripcurld00d/logrus-logzio-hook) | Hook for logging to [logz.io](https://logz.io), a Log as a Service using Logstash | #### Level logging @@ -309,8 +345,11 @@ The built-in logging formatters are: without colors. * *Note:* to force colored output when there is no TTY, set the `ForceColors` field to `true`. To force no colored output even if there is a TTY set the - `DisableColors` field to `true` + `DisableColors` field to `true`. For Windows, see + [github.com/mattn/go-colorable](https://github.com/mattn/go-colorable). + * All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#TextFormatter). * `logrus.JSONFormatter`. Logs fields as JSON. + * All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#JSONFormatter). Third party logging formatters: @@ -359,6 +398,18 @@ srv := http.Server{ Each line written to that writer will be printed the usual way, using formatters and hooks. The level for those entries is `info`. +This means that we can override the standard library logger easily: + +```go +logger := logrus.New() +logger.Formatter = &logrus.JSONFormatter{} + +// Use logrus for standard log output +// Note that `log` here references stdlib's log +// Not logrus imported under the name `log`. +log.SetOutput(logger.Writer()) +``` + #### Rotation Log rotation is not provided with Logrus. Log rotation should be done by an @@ -407,7 +458,7 @@ logrus.RegisterExitHandler(handler) ... ``` -#### Thread safty +#### Thread safety By default Logger is protected by mutex for concurrent writes, this mutex is invoked when calling hooks and writing logs. If you are sure such locking is not needed, you can call logger.SetNoLock() to disable the locking. diff --git a/vendor/github.com/Sirupsen/logrus/hooks/syslog/README.md b/vendor/github.com/Sirupsen/logrus/hooks/syslog/README.md new file mode 100644 index 00000000..066704b3 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/hooks/syslog/README.md @@ -0,0 +1,39 @@ +# Syslog Hooks for Logrus :walrus: + +## Usage + +```go +import ( + "log/syslog" + "github.com/Sirupsen/logrus" + logrus_syslog "github.com/Sirupsen/logrus/hooks/syslog" +) + +func main() { + log := logrus.New() + hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "") + + if err == nil { + log.Hooks.Add(hook) + } +} +``` + +If you want to connect to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). Just assign empty string to the first two parameters of `NewSyslogHook`. It should look like the following. + +```go +import ( + "log/syslog" + "github.com/Sirupsen/logrus" + logrus_syslog "github.com/Sirupsen/logrus/hooks/syslog" +) + +func main() { + log := logrus.New() + hook, err := logrus_syslog.NewSyslogHook("", "", syslog.LOG_INFO, "") + + if err == nil { + log.Hooks.Add(hook) + } +} +``` \ No newline at end of file diff --git a/vendor/github.com/Sirupsen/logrus/hooks/syslog/syslog.go b/vendor/github.com/Sirupsen/logrus/hooks/syslog/syslog.go new file mode 100644 index 00000000..a36e2003 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/hooks/syslog/syslog.go @@ -0,0 +1,54 @@ +// +build !windows,!nacl,!plan9 + +package logrus_syslog + +import ( + "fmt" + "github.com/Sirupsen/logrus" + "log/syslog" + "os" +) + +// SyslogHook to send logs via syslog. +type SyslogHook struct { + Writer *syslog.Writer + SyslogNetwork string + SyslogRaddr string +} + +// Creates a hook to be added to an instance of logger. This is called with +// `hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_DEBUG, "")` +// `if err == nil { log.Hooks.Add(hook) }` +func NewSyslogHook(network, raddr string, priority syslog.Priority, tag string) (*SyslogHook, error) { + w, err := syslog.Dial(network, raddr, priority, tag) + return &SyslogHook{w, network, raddr}, err +} + +func (hook *SyslogHook) Fire(entry *logrus.Entry) error { + line, err := entry.String() + if err != nil { + fmt.Fprintf(os.Stderr, "Unable to read entry, %v", err) + return err + } + + switch entry.Level { + case logrus.PanicLevel: + return hook.Writer.Crit(line) + case logrus.FatalLevel: + return hook.Writer.Crit(line) + case logrus.ErrorLevel: + return hook.Writer.Err(line) + case logrus.WarnLevel: + return hook.Writer.Warning(line) + case logrus.InfoLevel: + return hook.Writer.Info(line) + case logrus.DebugLevel: + return hook.Writer.Debug(line) + default: + return nil + } +} + +func (hook *SyslogHook) Levels() []logrus.Level { + return logrus.AllLevels +} diff --git a/vendor/github.com/Sirupsen/logrus/json_formatter.go b/vendor/github.com/Sirupsen/logrus/json_formatter.go index 2ad6dc5c..266554e9 100644 --- a/vendor/github.com/Sirupsen/logrus/json_formatter.go +++ b/vendor/github.com/Sirupsen/logrus/json_formatter.go @@ -5,9 +5,40 @@ import ( "fmt" ) +type fieldKey string +type FieldMap map[fieldKey]string + +const ( + FieldKeyMsg = "msg" + FieldKeyLevel = "level" + FieldKeyTime = "time" +) + +func (f FieldMap) resolve(key fieldKey) string { + if k, ok := f[key]; ok { + return k + } + + return string(key) +} + type JSONFormatter struct { // TimestampFormat sets the format used for marshaling timestamps. TimestampFormat string + + // DisableTimestamp allows disabling automatic timestamps in output + DisableTimestamp bool + + // FieldMap allows users to customize the names of keys for various fields. + // As an example: + // formatter := &JSONFormatter{ + // FieldMap: FieldMap{ + // FieldKeyTime: "@timestamp", + // FieldKeyLevel: "@level", + // FieldKeyLevel: "@message", + // }, + // } + FieldMap FieldMap } func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) { @@ -29,9 +60,11 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) { timestampFormat = DefaultTimestampFormat } - data["time"] = entry.Time.Format(timestampFormat) - data["msg"] = entry.Message - data["level"] = entry.Level.String() + if !f.DisableTimestamp { + data[f.FieldMap.resolve(FieldKeyTime)] = entry.Time.Format(timestampFormat) + } + data[f.FieldMap.resolve(FieldKeyMsg)] = entry.Message + data[f.FieldMap.resolve(FieldKeyLevel)] = entry.Level.String() serialized, err := json.Marshal(data) if err != nil { diff --git a/vendor/github.com/Sirupsen/logrus/terminal_appengine.go b/vendor/github.com/Sirupsen/logrus/terminal_appengine.go index 1960169e..e011a869 100644 --- a/vendor/github.com/Sirupsen/logrus/terminal_appengine.go +++ b/vendor/github.com/Sirupsen/logrus/terminal_appengine.go @@ -2,7 +2,9 @@ package logrus +import "io" + // IsTerminal returns true if stderr's file descriptor is a terminal. -func IsTerminal() bool { +func IsTerminal(f io.Writer) bool { return true } diff --git a/vendor/github.com/Sirupsen/logrus/terminal_notwindows.go b/vendor/github.com/Sirupsen/logrus/terminal_notwindows.go index 329038f6..190297ab 100644 --- a/vendor/github.com/Sirupsen/logrus/terminal_notwindows.go +++ b/vendor/github.com/Sirupsen/logrus/terminal_notwindows.go @@ -9,14 +9,20 @@ package logrus import ( + "io" + "os" "syscall" "unsafe" ) // IsTerminal returns true if stderr's file descriptor is a terminal. -func IsTerminal() bool { - fd := syscall.Stderr +func IsTerminal(f io.Writer) bool { var termios Termios - _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) - return err == 0 + switch v := f.(type) { + case *os.File: + _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(v.Fd()), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) + return err == 0 + default: + return false + } } diff --git a/vendor/github.com/Sirupsen/logrus/terminal_solaris.go b/vendor/github.com/Sirupsen/logrus/terminal_solaris.go index a3c6f6e7..3c86b1ab 100644 --- a/vendor/github.com/Sirupsen/logrus/terminal_solaris.go +++ b/vendor/github.com/Sirupsen/logrus/terminal_solaris.go @@ -3,13 +3,19 @@ package logrus import ( + "io" "os" "golang.org/x/sys/unix" ) // IsTerminal returns true if the given file descriptor is a terminal. -func IsTerminal() bool { - _, err := unix.IoctlGetTermios(int(os.Stdout.Fd()), unix.TCGETA) - return err == nil +func IsTerminal(f io.Writer) bool { + switch v := f.(type) { + case *os.File: + _, err := unix.IoctlGetTermios(int(v.Fd()), unix.TCGETA) + return err == nil + default: + return false + } } diff --git a/vendor/github.com/Sirupsen/logrus/terminal_windows.go b/vendor/github.com/Sirupsen/logrus/terminal_windows.go index 3727e8ad..05d2f91f 100644 --- a/vendor/github.com/Sirupsen/logrus/terminal_windows.go +++ b/vendor/github.com/Sirupsen/logrus/terminal_windows.go @@ -8,6 +8,8 @@ package logrus import ( + "io" + "os" "syscall" "unsafe" ) @@ -19,9 +21,13 @@ var ( ) // IsTerminal returns true if stderr's file descriptor is a terminal. -func IsTerminal() bool { - fd := syscall.Stderr - var st uint32 - r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) - return r != 0 && e == 0 +func IsTerminal(f io.Writer) bool { + switch v := f.(type) { + case *os.File: + var st uint32 + r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(v.Fd()), uintptr(unsafe.Pointer(&st)), 0) + return r != 0 && e == 0 + default: + return false + } } diff --git a/vendor/github.com/Sirupsen/logrus/text_formatter.go b/vendor/github.com/Sirupsen/logrus/text_formatter.go index 9114b3ca..ba888540 100644 --- a/vendor/github.com/Sirupsen/logrus/text_formatter.go +++ b/vendor/github.com/Sirupsen/logrus/text_formatter.go @@ -3,9 +3,9 @@ package logrus import ( "bytes" "fmt" - "runtime" "sort" "strings" + "sync" "time" ) @@ -20,16 +20,10 @@ const ( var ( baseTimestamp time.Time - isTerminal bool ) func init() { baseTimestamp = time.Now() - isTerminal = IsTerminal() -} - -func miniTS() int { - return int(time.Since(baseTimestamp) / time.Second) } type TextFormatter struct { @@ -54,11 +48,32 @@ type TextFormatter struct { // that log extremely frequently and don't use the JSON formatter this may not // be desired. DisableSorting bool + + // QuoteEmptyFields will wrap empty fields in quotes if true + QuoteEmptyFields bool + + // QuoteCharacter can be set to the override the default quoting character " + // with something else. For example: ', or `. + QuoteCharacter string + + // Whether the logger's out is to a terminal + isTerminal bool + + sync.Once +} + +func (f *TextFormatter) init(entry *Entry) { + if len(f.QuoteCharacter) == 0 { + f.QuoteCharacter = "\"" + } + if entry.Logger != nil { + f.isTerminal = IsTerminal(entry.Logger.Out) + } } func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { var b *bytes.Buffer - var keys []string = make([]string, 0, len(entry.Data)) + keys := make([]string, 0, len(entry.Data)) for k := range entry.Data { keys = append(keys, k) } @@ -74,8 +89,9 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { prefixFieldClashes(entry.Data) - isColorTerminal := isTerminal && (runtime.GOOS != "windows") - isColored := (f.ForceColors || isColorTerminal) && !f.DisableColors + f.Do(func() { f.init(entry) }) + + isColored := (f.ForceColors || f.isTerminal) && !f.DisableColors timestampFormat := f.TimestampFormat if timestampFormat == "" { @@ -115,8 +131,10 @@ func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []strin levelText := strings.ToUpper(entry.Level.String())[0:4] - if !f.FullTimestamp { - fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, miniTS(), entry.Message) + if f.DisableTimestamp { + fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m %-44s ", levelColor, levelText, entry.Message) + } else if !f.FullTimestamp { + fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, int(entry.Time.Sub(baseTimestamp)/time.Second), entry.Message) } else { fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), entry.Message) } @@ -127,7 +145,10 @@ func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []strin } } -func needsQuoting(text string) bool { +func (f *TextFormatter) needsQuoting(text string) bool { + if f.QuoteEmptyFields && len(text) == 0 { + return true + } for _, ch := range text { if !((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || @@ -150,17 +171,17 @@ func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interf func (f *TextFormatter) appendValue(b *bytes.Buffer, value interface{}) { switch value := value.(type) { case string: - if !needsQuoting(value) { + if !f.needsQuoting(value) { b.WriteString(value) } else { - fmt.Fprintf(b, "%q", value) + fmt.Fprintf(b, "%s%v%s", f.QuoteCharacter, value, f.QuoteCharacter) } case error: errmsg := value.Error() - if !needsQuoting(errmsg) { + if !f.needsQuoting(errmsg) { b.WriteString(errmsg) } else { - fmt.Fprintf(b, "%q", errmsg) + fmt.Fprintf(b, "%s%v%s", f.QuoteCharacter, errmsg, f.QuoteCharacter) } default: fmt.Fprint(b, value) diff --git a/vendor/github.com/Sirupsen/logrus/writer.go b/vendor/github.com/Sirupsen/logrus/writer.go index f74d2aa5..7bdebedc 100644 --- a/vendor/github.com/Sirupsen/logrus/writer.go +++ b/vendor/github.com/Sirupsen/logrus/writer.go @@ -11,39 +11,48 @@ func (logger *Logger) Writer() *io.PipeWriter { } func (logger *Logger) WriterLevel(level Level) *io.PipeWriter { + return NewEntry(logger).WriterLevel(level) +} + +func (entry *Entry) Writer() *io.PipeWriter { + return entry.WriterLevel(InfoLevel) +} + +func (entry *Entry) WriterLevel(level Level) *io.PipeWriter { reader, writer := io.Pipe() var printFunc func(args ...interface{}) + switch level { case DebugLevel: - printFunc = logger.Debug + printFunc = entry.Debug case InfoLevel: - printFunc = logger.Info + printFunc = entry.Info case WarnLevel: - printFunc = logger.Warn + printFunc = entry.Warn case ErrorLevel: - printFunc = logger.Error + printFunc = entry.Error case FatalLevel: - printFunc = logger.Fatal + printFunc = entry.Fatal case PanicLevel: - printFunc = logger.Panic + printFunc = entry.Panic default: - printFunc = logger.Print + printFunc = entry.Print } - go logger.writerScanner(reader, printFunc) + go entry.writerScanner(reader, printFunc) runtime.SetFinalizer(writer, writerFinalizer) return writer } -func (logger *Logger) writerScanner(reader *io.PipeReader, printFunc func(args ...interface{})) { +func (entry *Entry) writerScanner(reader *io.PipeReader, printFunc func(args ...interface{})) { scanner := bufio.NewScanner(reader) for scanner.Scan() { printFunc(scanner.Text()) } if err := scanner.Err(); err != nil { - logger.Errorf("Error while reading from Writer: %s", err) + entry.Errorf("Error while reading from Writer: %s", err) } reader.Close() } diff --git a/vendor/github.com/SvenDowideit/cpuid/cpuid.go b/vendor/github.com/SvenDowideit/cpuid/cpuid.go index 91ea9763..ac4c5b01 100644 --- a/vendor/github.com/SvenDowideit/cpuid/cpuid.go +++ b/vendor/github.com/SvenDowideit/cpuid/cpuid.go @@ -12,7 +12,6 @@ package cpuid import ( "strings" - "unsafe" ) // Vendor is a representation of a CPU vendor. @@ -565,9 +564,8 @@ func isHypervisorActive() bool { } func getHypervisorCpuid(ax uint32) string { - a, b, c, d := cpuid(ax) - var info [4]uint32 = [4]uint32{a, b, c, d} - name := strings.TrimRight(string((*[12]byte)(unsafe.Pointer(&info[1]))[:]), "\000") + _, b, c, d := cpuid(ax) + name := strings.TrimRight(string(valAsString(b, c, d)), "\000") return name } @@ -584,10 +582,7 @@ func hypervisorName() string { // return hv //} - if hv := getHypervisorCpuid(0x40000000); hv != "" { - return hv - } - return "" + return getHypervisorCpuid(0x40000000) } // https://en.wikipedia.org/wiki/CPUID#EAX.3D0:_Get_vendor_ID diff --git a/vendor/github.com/vmware/vmw-guestinfo/bdoor/bdoor.go b/vendor/github.com/vmware/vmw-guestinfo/bdoor/bdoor.go index 56beb8cf..43ee14cf 100644 --- a/vendor/github.com/vmware/vmw-guestinfo/bdoor/bdoor.go +++ b/vendor/github.com/vmware/vmw-guestinfo/bdoor/bdoor.go @@ -1,4 +1,4 @@ -// Copyright 2016 VMware, Inc. All Rights Reserved. +// Copyright 2016-2017 VMware, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,7 +15,6 @@ package bdoor const ( - BackdoorMagic = uint64(0x564D5868) BackdoorPort = uint16(0x5658) BackdoorHighBWPort = uint16(0x5659) @@ -26,109 +25,80 @@ const ( CommandFlagCookie = uint32(0x80000000) ) -type BackdoorProto struct { - // typedef union { - // struct { - // DECLARE_REG_NAMED_STRUCT(ax); - // size_t size; /* Register bx. */ - // DECLARE_REG_NAMED_STRUCT(cx); - // DECLARE_REG_NAMED_STRUCT(dx); - // DECLARE_REG_NAMED_STRUCT(si); - // DECLARE_REG_NAMED_STRUCT(di); - // } in; - // struct { - // DECLARE_REG_NAMED_STRUCT(ax); - // DECLARE_REG_NAMED_STRUCT(bx); - // DECLARE_REG_NAMED_STRUCT(cx); - // DECLARE_REG_NAMED_STRUCT(dx); - // DECLARE_REG_NAMED_STRUCT(si); - // DECLARE_REG_NAMED_STRUCT(di); - // } out; - // } proto; - - AX, BX, CX, DX, SI, DI, BP UInt64 - size uint32 -} - -func bdoor_inout(ax, bx, cx, dx, si, di, bp uint64) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint64) -func bdoor_hbout(ax, bx, cx, dx, si, di, bp uint64) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint64) -func bdoor_hbin(ax, bx, cx, dx, si, di, bp uint64) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint64) -func bdoor_inout_test(ax, bx, cx, dx, si, di, bp uint64) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint64) - func (p *BackdoorProto) InOut() *BackdoorProto { - p.DX.Low.Low = BackdoorPort - p.AX.SetQuad(BackdoorMagic) + p.DX.AsUInt32().Low = BackdoorPort + p.AX.SetValue(BackdoorMagic) retax, retbx, retcx, retdx, retsi, retdi, retbp := bdoor_inout( - p.AX.Quad(), - p.BX.Quad(), - p.CX.Quad(), - p.DX.Quad(), - p.SI.Quad(), - p.DI.Quad(), - p.BP.Quad(), + p.AX.Value(), + p.BX.Value(), + p.CX.Value(), + p.DX.Value(), + p.SI.Value(), + p.DI.Value(), + p.BP.Value(), ) ret := &BackdoorProto{} - ret.AX.SetQuad(retax) - ret.BX.SetQuad(retbx) - ret.CX.SetQuad(retcx) - ret.DX.SetQuad(retdx) - ret.SI.SetQuad(retsi) - ret.DI.SetQuad(retdi) - ret.BP.SetQuad(retbp) + ret.AX.SetValue(retax) + ret.BX.SetValue(retbx) + ret.CX.SetValue(retcx) + ret.DX.SetValue(retdx) + ret.SI.SetValue(retsi) + ret.DI.SetValue(retdi) + ret.BP.SetValue(retbp) return ret } func (p *BackdoorProto) HighBandwidthOut() *BackdoorProto { - p.DX.Low.Low = BackdoorHighBWPort - p.AX.SetQuad(BackdoorMagic) + p.DX.AsUInt32().Low = BackdoorHighBWPort + p.AX.SetValue(BackdoorMagic) retax, retbx, retcx, retdx, retsi, retdi, retbp := bdoor_hbout( - p.AX.Quad(), - p.BX.Quad(), - p.CX.Quad(), - p.DX.Quad(), - p.SI.Quad(), - p.DI.Quad(), - p.BP.Quad(), + p.AX.Value(), + p.BX.Value(), + p.CX.Value(), + p.DX.Value(), + p.SI.Value(), + p.DI.Value(), + p.BP.Value(), ) ret := &BackdoorProto{} - ret.AX.SetQuad(retax) - ret.BX.SetQuad(retbx) - ret.CX.SetQuad(retcx) - ret.DX.SetQuad(retdx) - ret.SI.SetQuad(retsi) - ret.DI.SetQuad(retdi) - ret.BP.SetQuad(retbp) + ret.AX.SetValue(retax) + ret.BX.SetValue(retbx) + ret.CX.SetValue(retcx) + ret.DX.SetValue(retdx) + ret.SI.SetValue(retsi) + ret.DI.SetValue(retdi) + ret.BP.SetValue(retbp) return ret } func (p *BackdoorProto) HighBandwidthIn() *BackdoorProto { - p.DX.Low.Low = BackdoorHighBWPort - p.AX.SetQuad(BackdoorMagic) + p.DX.AsUInt32().Low = BackdoorHighBWPort + p.AX.SetValue(BackdoorMagic) retax, retbx, retcx, retdx, retsi, retdi, retbp := bdoor_hbin( - p.AX.Quad(), - p.BX.Quad(), - p.CX.Quad(), - p.DX.Quad(), - p.SI.Quad(), - p.DI.Quad(), - p.BP.Quad(), + p.AX.Value(), + p.BX.Value(), + p.CX.Value(), + p.DX.Value(), + p.SI.Value(), + p.DI.Value(), + p.BP.Value(), ) ret := &BackdoorProto{} - ret.AX.SetQuad(retax) - ret.BX.SetQuad(retbx) - ret.CX.SetQuad(retcx) - ret.DX.SetQuad(retdx) - ret.SI.SetQuad(retsi) - ret.DI.SetQuad(retdi) - ret.BP.SetQuad(retbp) + ret.AX.SetValue(retax) + ret.BX.SetValue(retbx) + ret.CX.SetValue(retcx) + ret.DX.SetValue(retdx) + ret.SI.SetValue(retsi) + ret.DI.SetValue(retdi) + ret.BP.SetValue(retbp) return ret } diff --git a/vendor/github.com/vmware/vmw-guestinfo/bdoor/bdoor_386.go b/vendor/github.com/vmware/vmw-guestinfo/bdoor/bdoor_386.go new file mode 100644 index 00000000..ea9a2f25 --- /dev/null +++ b/vendor/github.com/vmware/vmw-guestinfo/bdoor/bdoor_386.go @@ -0,0 +1,48 @@ +// Copyright 2016-2017 VMware, Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bdoor + +const ( + BackdoorMagic = uint32(0x564D5868) +) + +type BackdoorProto struct { + // typedef union { + // struct { + // DECLARE_REG_NAMED_STRUCT(ax); + // size_t size; /* Register bx. */ + // DECLARE_REG_NAMED_STRUCT(cx); + // DECLARE_REG_NAMED_STRUCT(dx); + // DECLARE_REG_NAMED_STRUCT(si); + // DECLARE_REG_NAMED_STRUCT(di); + // } in; + // struct { + // DECLARE_REG_NAMED_STRUCT(ax); + // DECLARE_REG_NAMED_STRUCT(bx); + // DECLARE_REG_NAMED_STRUCT(cx); + // DECLARE_REG_NAMED_STRUCT(dx); + // DECLARE_REG_NAMED_STRUCT(si); + // DECLARE_REG_NAMED_STRUCT(di); + // } out; + // } proto; + + AX, BX, CX, DX, SI, DI, BP UInt32 + size uint32 +} + +func bdoor_inout(ax, bx, cx, dx, si, di, bp uint32) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint32) +func bdoor_hbout(ax, bx, cx, dx, si, di, bp uint32) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint32) +func bdoor_hbin(ax, bx, cx, dx, si, di, bp uint32) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint32) +func bdoor_inout_test(ax, bx, cx, dx, si, di, bp uint32) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint32) diff --git a/vendor/github.com/vmware/vmw-guestinfo/bdoor/bdoor_386.s b/vendor/github.com/vmware/vmw-guestinfo/bdoor/bdoor_386.s new file mode 100644 index 00000000..a6e11b11 --- /dev/null +++ b/vendor/github.com/vmware/vmw-guestinfo/bdoor/bdoor_386.s @@ -0,0 +1,112 @@ +#include "textflag.h" + +// Doc of the golang plan9 assembler +// http://p9.nyx.link/labs/sys/doc/asm.html +// +// A good primer of how to write golang with some plan9 flavored assembly +// http://www.doxsey.net/blog/go-and-assembly +// +// Some x86 references +// http://www.eecg.toronto.edu/~amza/www.mindsec.com/files/x86regs.html +// https://cseweb.ucsd.edu/classes/sp10/cse141/pdf/02/S01_x86_64.key.pdf +// https://en.wikibooks.org/wiki/X86_Assembly/Other_Instructions +// +// (This one is invaluable. Has a working example of how a standard function +// call looks on the stack with the associated assembly.) +// https://www.recurse.com/blog/7-understanding-c-by-learning-assembly +// +// Reference with raw form of the Opcode +// http://x86.renejeschke.de/html/file_module_x86_id_139.html +// +// Massive x86_64 reference +// http://ref.x86asm.net/coder64.html#xED +// +// Adding instructions to the go assembler +// https://blog.klauspost.com/adding-unsupported-instructions-in-golang-assembler/ +// +// Backdoor commands +// https://sites.google.com/site/chitchatvmback/backdoor + +// func bdoor_inout(ax, bx, cx, dx, si, di, bp uint32) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint32) +TEXT ·bdoor_inout(SB), NOSPLIT|WRAPPER, $0 + MOVL ax+0(FP), AX + MOVL bx+4(FP), BX + MOVL cx+8(FP), CX + MOVL dx+12(FP), DX + MOVL si+16(FP), SI + MOVL di+20(FP), DI + MOVL bp+24(FP), BP + + // IN to DX from EAX + INL + + MOVL AX, retax+28(FP) + MOVL BX, retbx+32(FP) + MOVL CX, retcx+36(FP) + MOVL DX, retdx+40(FP) + MOVL SI, retsi+44(FP) + MOVL DI, retdi+48(FP) + MOVL BP, retbp+52(FP) + RET + +// func bdoor_hbout(ax, bx, cx, dx, si, di, bp uint32) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint32) +TEXT ·bdoor_hbout(SB), NOSPLIT|WRAPPER, $0 + MOVL ax+0(FP), AX + MOVL bx+4(FP), BX + MOVL cx+8(FP), CX + MOVL dx+12(FP), DX + MOVL si+16(FP), SI + MOVL di+20(FP), DI + MOVL bp+24(FP), BP + + CLD; REP; OUTSB + + MOVL AX, retax+28(FP) + MOVL BX, retbx+32(FP) + MOVL CX, retcx+36(FP) + MOVL DX, retdx+40(FP) + MOVL SI, retsi+44(FP) + MOVL DI, retdi+48(FP) + MOVL BP, retbp+52(FP) + RET + +// func bdoor_hbin(ax, bx, cx, dx, si, di, bp uint32) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint32) +TEXT ·bdoor_hbin(SB), NOSPLIT|WRAPPER, $0 + MOVL ax+0(FP), AX + MOVL bx+4(FP), BX + MOVL cx+8(FP), CX + MOVL dx+12(FP), DX + MOVL si+16(FP), SI + MOVL di+20(FP), DI + MOVL bp+24(FP), BP + + CLD; REP; INSB + + MOVL AX, retax+28(FP) + MOVL BX, retbx+32(FP) + MOVL CX, retcx+40(FP) + MOVL DX, retdx+44(FP) + MOVL SI, retsi+48(FP) + MOVL DI, retdi+52(FP) + MOVL BP, retbp+56(FP) + RET + +// func bdoor_inout_test(ax, bx, cx, dx, si, di, bp uint32) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint32) +TEXT ·bdoor_inout_test(SB), NOSPLIT|WRAPPER, $0 + MOVL ax+0(FP), AX + MOVL bx+4(FP), BX + MOVL cx+8(FP), CX + MOVL dx+12(FP), DX + MOVL si+16(FP), SI + MOVL di+20(FP), DI + MOVL bp+24(FP), BP + + MOVL AX, retax+28(FP) + MOVL BX, retbx+32(FP) + MOVL CX, retcx+36(FP) + MOVL DX, retdx+40(FP) + MOVL SI, retsi+44(FP) + MOVL DI, retdi+48(FP) + MOVL BP, retbp+52(FP) + RET + diff --git a/vendor/github.com/vmware/vmw-guestinfo/bdoor/bdoor_amd64.go b/vendor/github.com/vmware/vmw-guestinfo/bdoor/bdoor_amd64.go new file mode 100644 index 00000000..0793c699 --- /dev/null +++ b/vendor/github.com/vmware/vmw-guestinfo/bdoor/bdoor_amd64.go @@ -0,0 +1,48 @@ +// Copyright 2016-2017 VMware, Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bdoor + +const ( + BackdoorMagic = uint64(0x564D5868) +) + +type BackdoorProto struct { + // typedef union { + // struct { + // DECLARE_REG_NAMED_STRUCT(ax); + // size_t size; /* Register bx. */ + // DECLARE_REG_NAMED_STRUCT(cx); + // DECLARE_REG_NAMED_STRUCT(dx); + // DECLARE_REG_NAMED_STRUCT(si); + // DECLARE_REG_NAMED_STRUCT(di); + // } in; + // struct { + // DECLARE_REG_NAMED_STRUCT(ax); + // DECLARE_REG_NAMED_STRUCT(bx); + // DECLARE_REG_NAMED_STRUCT(cx); + // DECLARE_REG_NAMED_STRUCT(dx); + // DECLARE_REG_NAMED_STRUCT(si); + // DECLARE_REG_NAMED_STRUCT(di); + // } out; + // } proto; + + AX, BX, CX, DX, SI, DI, BP UInt64 + size uint32 +} + +func bdoor_inout(ax, bx, cx, dx, si, di, bp uint64) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint64) +func bdoor_hbout(ax, bx, cx, dx, si, di, bp uint64) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint64) +func bdoor_hbin(ax, bx, cx, dx, si, di, bp uint64) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint64) +func bdoor_inout_test(ax, bx, cx, dx, si, di, bp uint64) (retax, retbx, retcx, retdx, retsi, retdi, retbp uint64) diff --git a/vendor/github.com/vmware/vmw-guestinfo/bdoor/word.go b/vendor/github.com/vmware/vmw-guestinfo/bdoor/word.go index c72d8d20..ec1ee13b 100644 --- a/vendor/github.com/vmware/vmw-guestinfo/bdoor/word.go +++ b/vendor/github.com/vmware/vmw-guestinfo/bdoor/word.go @@ -1,4 +1,4 @@ -// Copyright 2016 VMware, Inc. All Rights Reserved. +// Copyright 2016-2017 VMware, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,6 +14,8 @@ package bdoor +import "unsafe" + type UInt32 struct { High uint16 Low uint16 @@ -28,6 +30,22 @@ func (u *UInt32) SetWord(w uint32) { u.Low = uint16(w) } +func (u *UInt32) AsUInt32() *UInt32 { + return u +} + +func (u *UInt32) Value() uint32 { + return u.Word() +} + +func (u *UInt32) SetValue(val uint32) { + u.SetWord(val) +} + +func (u *UInt32) SetPointer(p unsafe.Pointer) { + u.SetWord(uint32(uintptr(p))) +} + type UInt64 struct { High UInt32 Low UInt32 @@ -41,3 +59,19 @@ func (u *UInt64) SetQuad(w uint64) { u.High.SetWord(uint32(w >> 32)) u.Low.SetWord(uint32(w)) } + +func (u *UInt64) AsUInt32() *UInt32 { + return &u.Low +} + +func (u *UInt64) Value() uint64 { + return u.Quad() +} + +func (u *UInt64) SetValue(val uint64) { + u.SetQuad(val) +} + +func (u *UInt64) SetPointer(p unsafe.Pointer) { + u.SetQuad(uint64(uintptr(p))) +} diff --git a/vendor/github.com/vmware/vmw-guestinfo/message/message.go b/vendor/github.com/vmware/vmw-guestinfo/message/message.go index 95f27fa3..a6261920 100644 --- a/vendor/github.com/vmware/vmw-guestinfo/message/message.go +++ b/vendor/github.com/vmware/vmw-guestinfo/message/message.go @@ -1,4 +1,4 @@ -// Copyright 2016 VMware, Inc. All Rights Reserved. +// Copyright 2016-2017 VMware, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -66,12 +66,12 @@ func NewChannel(proto uint32) (*Channel, error) { retry: bp := &bdoor.BackdoorProto{} - bp.BX.Low.SetWord(proto | flags) - bp.CX.Low.High = messageTypeOpen - bp.CX.Low.Low = bdoor.CommandMessage + bp.BX.AsUInt32().SetWord(proto | flags) + bp.CX.AsUInt32().High = messageTypeOpen + bp.CX.AsUInt32().Low = bdoor.CommandMessage out := bp.InOut() - if (out.CX.Low.High & messageStatusSuccess) == 0 { + if (out.CX.AsUInt32().High & messageStatusSuccess) == 0 { if flags != 0 { flags = 0 goto retry @@ -82,9 +82,9 @@ retry: } ch := &Channel{} - ch.id = out.DX.Low.High - ch.cookie.High.SetWord(out.SI.Low.Word()) - ch.cookie.Low.SetWord(out.DI.Low.Word()) + ch.id = out.DX.AsUInt32().High + ch.cookie.High.SetWord(out.SI.AsUInt32().Word()) + ch.cookie.Low.SetWord(out.DI.AsUInt32().Word()) Debugf("Opened channel %d", ch.id) return ch, nil @@ -93,15 +93,15 @@ retry: func (c *Channel) Close() error { bp := &bdoor.BackdoorProto{} - bp.CX.Low.High = messageTypeClose - bp.CX.Low.Low = bdoor.CommandMessage + bp.CX.AsUInt32().High = messageTypeClose + bp.CX.AsUInt32().Low = bdoor.CommandMessage - bp.DX.Low.High = c.id - bp.SI.Low.SetWord(c.cookie.High.Word()) - bp.DI.Low.SetWord(c.cookie.Low.Word()) + bp.DX.AsUInt32().High = c.id + bp.SI.AsUInt32().SetWord(c.cookie.High.Word()) + bp.DI.AsUInt32().SetWord(c.cookie.Low.Word()) out := bp.InOut() - if (out.CX.Low.High & messageStatusSuccess) == 0 { + if (out.CX.AsUInt32().High & messageStatusSuccess) == 0 { Errorf("Message: Unable to close communication channel %d", c.id) return ErrChannelClose } @@ -113,18 +113,18 @@ func (c *Channel) Close() error { func (c *Channel) Send(buf []byte) error { retry: bp := &bdoor.BackdoorProto{} - bp.CX.Low.High = messageTypeSendSize - bp.CX.Low.Low = bdoor.CommandMessage + bp.CX.AsUInt32().High = messageTypeSendSize + bp.CX.AsUInt32().Low = bdoor.CommandMessage - bp.DX.Low.High = c.id - bp.SI.Low.SetWord(c.cookie.High.Word()) - bp.DI.Low.SetWord(c.cookie.Low.Word()) + bp.DX.AsUInt32().High = c.id + bp.SI.AsUInt32().SetWord(c.cookie.High.Word()) + bp.DI.AsUInt32().SetWord(c.cookie.Low.Word()) - bp.BX.Low.SetWord(uint32(len(buf))) + bp.BX.AsUInt32().SetWord(uint32(len(buf))) // send the size out := bp.InOut() - if (out.CX.Low.High & messageStatusSuccess) == 0 { + if (out.CX.AsUInt32().High & messageStatusSuccess) == 0 { Errorf("Message: Unable to send a message over the communication channel %d", c.id) return ErrRpciSend } @@ -134,20 +134,20 @@ retry: return nil } - if !c.forceLowBW && (out.CX.Low.High&messageStatusHighBW) == messageStatusHighBW { + if !c.forceLowBW && (out.CX.AsUInt32().High&messageStatusHighBW) == messageStatusHighBW { hbbp := &bdoor.BackdoorProto{} - hbbp.BX.Low.Low = bdoor.CommandHighBWMessage - hbbp.BX.Low.High = messageStatusSuccess - hbbp.DX.Low.High = c.id - hbbp.BP.Low.SetWord(c.cookie.High.Word()) - hbbp.DI.Low.SetWord(c.cookie.Low.Word()) - hbbp.CX.Low.SetWord(uint32(len(buf))) - hbbp.SI.SetQuad(uint64(uintptr(unsafe.Pointer(&buf[0])))) + hbbp.BX.AsUInt32().Low = bdoor.CommandHighBWMessage + hbbp.BX.AsUInt32().High = messageStatusSuccess + hbbp.DX.AsUInt32().High = c.id + hbbp.BP.AsUInt32().SetWord(c.cookie.High.Word()) + hbbp.DI.AsUInt32().SetWord(c.cookie.Low.Word()) + hbbp.CX.AsUInt32().SetWord(uint32(len(buf))) + hbbp.SI.SetPointer(unsafe.Pointer(&buf[0])) out := hbbp.HighBandwidthOut() - if (out.BX.Low.High & messageStatusSuccess) == 0 { - if (out.BX.Low.High & messageStatusCheckPoint) != 0 { + if (out.BX.AsUInt32().High & messageStatusSuccess) == 0 { + if (out.BX.AsUInt32().High & messageStatusCheckPoint) != 0 { Debugf("A checkpoint occurred. Retrying the operation") goto retry } @@ -156,7 +156,7 @@ retry: return ErrRpciSend } } else { - bp.CX.Low.High = messageTypeSendPayload + bp.CX.AsUInt32().High = messageTypeSendPayload bbuf := bytes.NewBuffer(buf) for { @@ -169,17 +169,17 @@ retry: Debugf("sending %q over %d", string(words), c.id) switch len(words) { case 3: - bp.BX.Low.SetWord(binary.LittleEndian.Uint32([]byte{0x0, words[2], words[1], words[0]})) + bp.BX.AsUInt32().SetWord(binary.LittleEndian.Uint32([]byte{0x0, words[2], words[1], words[0]})) case 2: - bp.BX.Low.SetWord(uint32(binary.LittleEndian.Uint16(words))) + bp.BX.AsUInt32().SetWord(uint32(binary.LittleEndian.Uint16(words))) case 1: - bp.BX.Low.SetWord(uint32(words[0])) + bp.BX.AsUInt32().SetWord(uint32(words[0])) default: - bp.BX.Low.SetWord(binary.LittleEndian.Uint32(words)) + bp.BX.AsUInt32().SetWord(binary.LittleEndian.Uint32(words)) } out = bp.InOut() - if (out.CX.Low.High & messageStatusSuccess) == 0 { + if (out.CX.AsUInt32().High & messageStatusSuccess) == 0 { Errorf("Message: Unable to send a message over the communication channel %d", c.id) return ErrRpciSend } @@ -193,50 +193,50 @@ func (c *Channel) Receive() ([]byte, error) { retry: var err error bp := &bdoor.BackdoorProto{} - bp.CX.Low.High = messageTypeReceiveSize - bp.CX.Low.Low = bdoor.CommandMessage + bp.CX.AsUInt32().High = messageTypeReceiveSize + bp.CX.AsUInt32().Low = bdoor.CommandMessage - bp.DX.Low.High = c.id - bp.SI.Low.SetWord(c.cookie.High.Word()) - bp.DI.Low.SetWord(c.cookie.Low.Word()) + bp.DX.AsUInt32().High = c.id + bp.SI.AsUInt32().SetWord(c.cookie.High.Word()) + bp.DI.AsUInt32().SetWord(c.cookie.Low.Word()) out := bp.InOut() - if (out.CX.Low.High & messageStatusSuccess) == 0 { + if (out.CX.AsUInt32().High & messageStatusSuccess) == 0 { Errorf("Message: Unable to poll for messages over the communication channel %d", c.id) return nil, ErrRpciReceive } - if (out.CX.Low.High & messageStatusDoRecieve) == 0 { + if (out.CX.AsUInt32().High & messageStatusDoRecieve) == 0 { Debugf("No message to retrieve") return nil, nil } // Receive the size. - if out.DX.Low.High != messageTypeSendSize { + if out.DX.AsUInt32().High != messageTypeSendSize { Errorf("Message: Protocol error. Expected a MESSAGE_TYPE_SENDSIZE request from vmware") return nil, ErrRpciReceive } - size := out.BX.Quad() + size := out.BX.Value() var buf []byte if size != 0 { - if !c.forceLowBW && (out.CX.Low.High&messageStatusHighBW == messageStatusHighBW) { + if !c.forceLowBW && (out.CX.AsUInt32().High&messageStatusHighBW == messageStatusHighBW) { buf = make([]byte, size) hbbp := &bdoor.BackdoorProto{} - hbbp.BX.Low.Low = bdoor.CommandHighBWMessage - hbbp.BX.Low.High = messageStatusSuccess - hbbp.DX.Low.High = c.id - hbbp.SI.Low.SetWord(c.cookie.High.Word()) - hbbp.BP.Low.SetWord(c.cookie.Low.Word()) - hbbp.CX.Low.SetWord(uint32(len(buf))) - hbbp.DI.SetQuad(uint64(uintptr(unsafe.Pointer(&buf[0])))) + hbbp.BX.AsUInt32().Low = bdoor.CommandHighBWMessage + hbbp.BX.AsUInt32().High = messageStatusSuccess + hbbp.DX.AsUInt32().High = c.id + hbbp.SI.AsUInt32().SetWord(c.cookie.High.Word()) + hbbp.BP.AsUInt32().SetWord(c.cookie.Low.Word()) + hbbp.CX.AsUInt32().SetWord(uint32(len(buf))) + hbbp.DI.SetPointer(unsafe.Pointer(&buf[0])) out := hbbp.HighBandwidthIn() - if (out.BX.Low.High & messageStatusSuccess) == 0 { + if (out.BX.AsUInt32().High & messageStatusSuccess) == 0 { Errorf("Message: Unable to send a message over the communication channel %d", c.id) c.reply(messageTypeReceivePayload, messageStatusFail) return nil, ErrRpciReceive @@ -249,12 +249,12 @@ retry: break } - bp.CX.Low.High = messageTypeReceivePayload - bp.BX.Low.Low = messageStatusSuccess + bp.CX.AsUInt32().High = messageTypeReceivePayload + bp.BX.AsUInt32().Low = messageStatusSuccess out = bp.InOut() - if (out.CX.Low.High & messageStatusSuccess) == 0 { - if (out.CX.Low.High & messageStatusCheckPoint) != 0 { + if (out.CX.AsUInt32().High & messageStatusSuccess) == 0 { + if (out.CX.AsUInt32().High & messageStatusCheckPoint) != 0 { Debugf("A checkpoint occurred. Retrying the operation") goto retry } @@ -264,34 +264,34 @@ retry: return nil, ErrRpciReceive } - if out.DX.Low.High != messageTypeSendPayload { + if out.DX.AsUInt32().High != messageTypeSendPayload { Errorf("Message: Protocol error. Expected a MESSAGE_TYPE_SENDPAYLOAD from vmware") c.reply(messageTypeReceivePayload, messageStatusFail) return nil, ErrRpciReceive } - Debugf("Received %#v", out.BX.Low.Word()) + Debugf("Received %#v", out.BX.AsUInt32().Word()) switch size { case 1: - err = binary.Write(b, binary.LittleEndian, uint8(out.BX.Low.Low)) + err = binary.Write(b, binary.LittleEndian, uint8(out.BX.AsUInt32().Low)) size = size - 1 case 2: - err = binary.Write(b, binary.LittleEndian, uint16(out.BX.Low.Low)) + err = binary.Write(b, binary.LittleEndian, uint16(out.BX.AsUInt32().Low)) size = size - 2 case 3: - err = binary.Write(b, binary.LittleEndian, uint16(out.BX.Low.Low)) + err = binary.Write(b, binary.LittleEndian, uint16(out.BX.AsUInt32().Low)) if err != nil { c.reply(messageTypeReceivePayload, messageStatusFail) return nil, ErrRpciReceive } - err = binary.Write(b, binary.LittleEndian, uint8(out.BX.Low.High)) + err = binary.Write(b, binary.LittleEndian, uint8(out.BX.AsUInt32().High)) size = size - 3 default: - err = binary.Write(b, binary.LittleEndian, out.BX.Low.Word()) + err = binary.Write(b, binary.LittleEndian, out.BX.AsUInt32().Word()) size = size - 4 } @@ -314,17 +314,17 @@ retry: func (c *Channel) reply(messageType, messageStatus uint16) { bp := &bdoor.BackdoorProto{} - bp.BX.Low.Low = messageStatus - bp.CX.Low.High = messageType - bp.CX.Low.Low = bdoor.CommandMessage - bp.DX.Low.High = c.id - bp.SI.Low.SetWord(c.cookie.High.Word()) - bp.DI.Low.SetWord(c.cookie.Low.Word()) + bp.BX.AsUInt32().Low = messageStatus + bp.CX.AsUInt32().High = messageType + bp.CX.AsUInt32().Low = bdoor.CommandMessage + bp.DX.AsUInt32().High = c.id + bp.SI.AsUInt32().SetWord(c.cookie.High.Word()) + bp.DI.AsUInt32().SetWord(c.cookie.Low.Word()) out := bp.InOut() /* OUT: Status */ - if (out.CX.Low.High & messageStatusSuccess) == 0 { + if (out.CX.AsUInt32().High & messageStatusSuccess) == 0 { if messageStatus == messageStatusSuccess { Errorf("reply Message: Unable to send a message over the communication channel %d", c.id) } else {