diff --git a/cmd/control/service/service.go b/cmd/control/service/service.go index d6a4871a..3915dd8b 100644 --- a/cmd/control/service/service.go +++ b/cmd/control/service/service.go @@ -208,9 +208,17 @@ func IsLocalOrURL(service string) bool { return isLocal(service) || strings.HasPrefix(service, "http:/") || strings.HasPrefix(service, "https:/") } -func validateService(service string, cfg *config.CloudConfig) { +// ValidService checks to see if the service definition exists +func ValidService(service string, cfg *config.CloudConfig) bool { services := availableService(cfg) if !IsLocalOrURL(service) && !util.Contains(services, service) { + return false + } + return true +} + +func validateService(service string, cfg *config.CloudConfig) { + if !ValidService(service, cfg) { log.Fatalf("%s is not a valid service", service) } } diff --git a/cmd/systemdocker/system-docker.go b/cmd/systemdocker/system-docker.go index b9e9907a..5ef6a6e8 100644 --- a/cmd/systemdocker/system-docker.go +++ b/cmd/systemdocker/system-docker.go @@ -9,7 +9,8 @@ import ( ) func Main() { - log.InitLogger() + log.SetLevel(log.DebugLevel) + if os.Geteuid() != 0 { log.Fatalf("%s: Need to be root", os.Args[0]) } @@ -18,5 +19,5 @@ func Main() { os.Setenv("DOCKER_HOST", config.SystemDockerHost) } - docker.Main() + docker.RancherOSMain() } diff --git a/compose/reload.go b/compose/reload.go index 32b4ed8c..92f31a5c 100644 --- a/compose/reload.go +++ b/compose/reload.go @@ -15,23 +15,30 @@ import ( func LoadService(p *project.Project, cfg *config.CloudConfig, useNetwork bool, service string) error { bytes, err := network.LoadServiceResource(service, useNetwork, cfg) if err != nil { + log.Error(err) return err } m := map[interface{}]interface{}{} if err = yaml.Unmarshal(bytes, &m); err != nil { - return fmt.Errorf("Failed to parse YAML configuration for %s: %v", service, err) + e := fmt.Errorf("Failed to parse YAML configuration for %s: %v", service, err) + log.Error(e) + return e } m = adjustContainerNames(m) bytes, err = yaml.Marshal(m) if err != nil { - return fmt.Errorf("Failed to marshal YAML configuration for %s: %v", service, err) + e := fmt.Errorf("Failed to marshal YAML configuration for %s: %v", service, err) + log.Error(e) + return e } if err = p.Load(bytes); err != nil { - return fmt.Errorf("Failed to load %s: %v", service, err) + e := fmt.Errorf("Failed to load %s: %v", service, err) + log.Error(e) + return e } return nil @@ -85,7 +92,7 @@ func projectReload(p *project.Project, useNetwork *bool, loadConsole bool, envir if err := LoadService(p, cfg, *useNetwork, service); err != nil { if err != network.ErrNoNetwork { - log.Error(err) + log.Errorf("Failed to load service(%s): %v", service, err) } continue } @@ -99,12 +106,12 @@ func projectReload(p *project.Project, useNetwork *bool, loadConsole bool, envir if loadConsole { if err := loadConsoleService(cfg, p); err != nil { - log.Errorf("Failed to load console: %v", err) + log.Errorf("Failed to load gancher.console=(%s): %v", cfg.Rancher.Console, err) } } if err := loadEngineService(cfg, p); err != nil { - log.Errorf("Failed to load engine: %v", err) + log.Errorf("Failed to load rancher.docker.engine=(%s): %v", cfg.Rancher.Docker.Engine, err) } return nil diff --git a/config/disk.go b/config/disk.go index c1458267..31df5a7f 100755 --- a/config/disk.go +++ b/config/disk.go @@ -55,7 +55,15 @@ func loadRawConfig(dirPrefix string, full bool) map[interface{}]interface{} { } func LoadConfig() *CloudConfig { - return LoadConfigWithPrefix("") + cfg := LoadConfigWithPrefix("") + + if cfg.Rancher.Debug { + log.SetDefaultLevel(log.DebugLevel) + } else { + log.SetDefaultLevel(log.InfoLevel) + } + + return cfg } func LoadConfigWithPrefix(dirPrefix string) *CloudConfig { diff --git a/init/init.go b/init/init.go index ab49e6e0..3b3444b3 100755 --- a/init/init.go +++ b/init/init.go @@ -13,6 +13,7 @@ import ( "syscall" "github.com/docker/docker/pkg/mount" + "github.com/rancher/os/cmd/control/service" "github.com/rancher/os/config" "github.com/rancher/os/dfs" "github.com/rancher/os/log" @@ -92,8 +93,8 @@ func sysInit(c *config.CloudConfig) (*config.CloudConfig, error) { } func MainInit() { - log.InitLogger() - log.Infof("MainInit() start") + log.InitDeferedLogger() + if err := RunInit(); err != nil { log.Fatal(err) } @@ -223,6 +224,7 @@ func RunInit() error { boot2DockerEnvironment := false var shouldSwitchRoot bool + hypervisor := "" configFiles := make(map[string][]byte) @@ -235,7 +237,15 @@ func RunInit() error { cmdLineArgs := strings.Join(os.Args, " ") config.SaveInitCmdline(cmdLineArgs) - return c, nil + cfg := config.LoadConfig() + log.Debugf("Cmdline debug = %s", cfg.Rancher.Debug) + if cfg.Rancher.Debug { + log.SetLevel(log.DebugLevel) + } else { + log.SetLevel(log.InfoLevel) + } + + return cfg, nil }}, config.CfgFuncData{"mount OEM", mountOem}, config.CfgFuncData{"debug save cfg", func(_ *config.CloudConfig) (*config.CloudConfig, error) { @@ -254,9 +264,10 @@ func RunInit() error { }}, config.CfgFuncData{"load modules", loadModules}, config.CfgFuncData{"b2d env", func(cfg *config.CloudConfig) (*config.CloudConfig, error) { - if util.ResolveDevice("LABEL=B2D_STATE") != "" { + if dev := util.ResolveDevice("LABEL=B2D_STATE"); dev != "" { boot2DockerEnvironment = true cfg.Rancher.State.Dev = "LABEL=B2D_STATE" + log.Infof("boot2DockerEnvironment %s: %s", cfg.Rancher.State.Dev, dev) return cfg, nil } @@ -273,6 +284,8 @@ func RunInit() error { boot2DockerEnvironment = true cfg.Rancher.State.Dev = "LABEL=B2D_STATE" cfg.Rancher.State.Autoformat = []string{device} + log.Infof("boot2DockerEnvironment %s: Autoformat %s", cfg.Rancher.State.Dev, cfg.Rancher.State.Autoformat[0]) + break } } @@ -293,6 +306,7 @@ func RunInit() error { config.CfgFuncData{"mount and bootstrap", func(cfg *config.CloudConfig) (*config.CloudConfig, error) { var err error cfg, shouldSwitchRoot, err = tryMountAndBootstrap(cfg) + if err != nil { return nil, err } @@ -300,13 +314,13 @@ func RunInit() error { }}, config.CfgFuncData{"cloud-init", func(cfg *config.CloudConfig) (*config.CloudConfig, error) { cfg.Rancher.CloudInit.Datasources = config.LoadConfigWithPrefix(state).Rancher.CloudInit.Datasources - hypervisor := checkHypervisor(cfg) + hypervisor = checkHypervisor(cfg) if hypervisor == "vmware" { // add vmware to the end - we don't want to over-ride an choices the user has made cfg.Rancher.CloudInit.Datasources = append(cfg.Rancher.CloudInit.Datasources, hypervisor) - } - if err := config.Set("rancher.cloud_init.datasources", cfg.Rancher.CloudInit.Datasources); err != nil { - log.Error(err) + if err := config.Set("rancher.cloud_init.datasources", cfg.Rancher.CloudInit.Datasources); err != nil { + log.Error(err) + } } log.Debug("init, runCloudInitServices()") @@ -314,10 +328,7 @@ func RunInit() error { log.Error(err) } - // return any newly detected network config. - cfg = config.LoadConfig() - - return cfg, nil + return config.LoadConfig(), nil }}, config.CfgFuncData{"read cfg files", func(cfg *config.CloudConfig) (*config.CloudConfig, error) { filesToCopy := []string{ @@ -350,6 +361,7 @@ func RunInit() error { }}, config.CfgFuncData{"mount OEM2", mountOem}, config.CfgFuncData{"write cfg files", func(cfg *config.CloudConfig) (*config.CloudConfig, error) { + log.FsReady() for name, content := range configFiles { if err := os.MkdirAll(filepath.Dir(name), os.ModeDir|0700); err != nil { log.Error(err) @@ -368,7 +380,6 @@ func RunInit() error { return cfg, nil }}, config.CfgFuncData{"b2d Env", func(cfg *config.CloudConfig) (*config.CloudConfig, error) { - if boot2DockerEnvironment { if err := config.Set("rancher.state.dev", cfg.Rancher.State.Dev); err != nil { log.Errorf("Failed to update rancher.state.dev: %v", err) @@ -380,13 +391,18 @@ func RunInit() error { return config.LoadConfig(), nil }}, - config.CfgFuncData{"preparefs2", func(c *config.CloudConfig) (*config.CloudConfig, error) { - return c, dfs.PrepareFs(&mountConfig) + config.CfgFuncData{"hypervisor tools", func(cfg *config.CloudConfig) (*config.CloudConfig, error) { + // Maybe we could set `rancher.hypervisor_service`, and defer this further? + enableHypervisorService(cfg, hypervisor) + return config.LoadConfig(), nil + }}, + config.CfgFuncData{"preparefs2", func(cfg *config.CloudConfig) (*config.CloudConfig, error) { + return cfg, dfs.PrepareFs(&mountConfig) }}, config.CfgFuncData{"load modules2", loadModules}, - config.CfgFuncData{"set proxy env", func(c *config.CloudConfig) (*config.CloudConfig, error) { - network.SetProxyEnvironmentVariables(c) - return c, nil + config.CfgFuncData{"set proxy env", func(cfg *config.CloudConfig) (*config.CloudConfig, error) { + network.SetProxyEnvironmentVariables(cfg) + return cfg, nil }}, config.CfgFuncData{"init SELinux", initializeSelinux}, config.CfgFuncData{"setupSharedRoot", setupSharedRoot}, @@ -400,27 +416,44 @@ func RunInit() error { launchConfig, args := getLaunchConfig(cfg, &cfg.Rancher.SystemDocker) launchConfig.Fork = !cfg.Rancher.SystemDocker.Exec + //launchConfig.NoLog = true log.Info("Launching System Docker") _, err = dfs.LaunchDocker(launchConfig, config.SystemDockerBin, args...) if err != nil { + log.Errorf("Error Launching System Docker: %s", err) return err } + // Code never gets here - rancher.system_docker.exec=true return pidOne() } func checkHypervisor(cfg *config.CloudConfig) string { - hvtools := cpuid.CPU.HypervisorName - if hvtools != "" { - log.Infof("Detected Hypervisor: %s", cpuid.CPU.HypervisorName) - if hvtools == "vmware" { - hvtools = "open" - } - log.Infof("Setting rancher.services_include." + hvtools + "-vm-tools=true") - if err := config.Set("rancher.services_include."+hvtools+"-vm-tools", "true"); err != nil { - log.Error(err) - } + if cpuid.CPU.HypervisorName == "" { + log.Infof("ros init: No Detected Hypervisor") + } else { + log.Infof("ros init: Detected Hypervisor: %s", cpuid.CPU.HypervisorName) } return cpuid.CPU.HypervisorName } + +func enableHypervisorService(cfg *config.CloudConfig, hypervisorName string) { + if hypervisorName == "" { + return + } + + if hypervisorName == "vmware" { + hypervisorName = "open" + } + serviceName := hypervisorName + "-vm-tools" + // check quickly to see if there is a yml file available + if service.ValidService(serviceName, cfg) { + log.Infof("Setting rancher.services_include. %s=true", serviceName) + if err := config.Set("rancher.services_include."+serviceName, "true"); err != nil { + log.Error(err) + } + } else { + log.Infof("Skipping %s, can't get %s.yml file", serviceName, serviceName) + } +} diff --git a/log/log.go b/log/log.go index b9339e91..dacea7d0 100755 --- a/log/log.go +++ b/log/log.go @@ -3,13 +3,16 @@ package log import ( "io" "os" + "path/filepath" + + "io/ioutil" "github.com/Sirupsen/logrus" ) -// Default to using the logrus standard logger until log.InitLogger(logLevel) is called -var appLog = logrus.StandardLogger() var userHook *ShowuserlogHook +var defaultLogLevel logrus.Level +var debugThisLogger = false type Fields logrus.Fields type Level logrus.Level @@ -35,13 +38,15 @@ const ( ) func SetOutput(out io.Writer) { - appLog.Out = out + logrus.SetOutput(out) +} +func SetDefaultLevel(level Level) { + defaultLogLevel = logrus.Level(level) } func SetLevel(level Level) { if userHook != nil { userHook.Level = logrus.Level(level) } else { - appLog.Level = logrus.Level(level) logrus.SetLevel(logrus.Level(level)) } } @@ -50,101 +55,160 @@ func GetLevel() Level { if userHook != nil { return Level(userHook.Level) } - return Level(appLog.Level) + return Level(logrus.GetLevel()) } func Debugf(format string, args ...interface{}) { - appLog.Debugf(format, args...) + logrus.Debugf(format, args...) } func Infof(format string, args ...interface{}) { - appLog.Infof(format, args...) + logrus.Infof(format, args...) } func Printf(format string, args ...interface{}) { - appLog.Printf(format, args...) + logrus.Printf(format, args...) } func Warnf(format string, args ...interface{}) { - appLog.Warnf(format, args...) + logrus.Warnf(format, args...) } func Warningf(format string, args ...interface{}) { - appLog.Warningf(format, args...) + logrus.Warningf(format, args...) } func Errorf(format string, args ...interface{}) { - appLog.Errorf(format, args...) + logrus.Errorf(format, args...) } func Fatalf(format string, args ...interface{}) { - appLog.Fatalf(format, args...) + logrus.Fatalf(format, args...) } func Panicf(format string, args ...interface{}) { - appLog.Panicf(format, args...) + logrus.Panicf(format, args...) } func Debug(args ...interface{}) { - appLog.Debug(args...) + logrus.Debug(args...) } func Info(args ...interface{}) { - appLog.Info(args...) + logrus.Info(args...) } func Print(args ...interface{}) { - appLog.Print(args...) + logrus.Print(args...) } func Warn(args ...interface{}) { - appLog.Warn(args...) + logrus.Warn(args...) } func Warning(args ...interface{}) { - appLog.Warning(args...) + logrus.Warning(args...) } func Error(args ...interface{}) { - appLog.Error(args...) + logrus.Error(args...) } func Fatal(args ...interface{}) { - appLog.Fatal(args...) + logrus.Fatal(args...) } func Panic(args ...interface{}) { - appLog.Panic(args...) + logrus.Panic(args...) } func WithField(key string, value interface{}) *logrus.Entry { - return appLog.WithField(key, value) + return logrus.WithField(key, value) } func WithFields(fields Fields) *logrus.Entry { - return appLog.WithFields(logrus.Fields(fields)) + return logrus.WithFields(logrus.Fields(fields)) } +// InitLogger sets up Logging to log to /dev/kmsg and to Syslog func InitLogger() { + if logTheseApps() { + innerInit(false) + FsReady() + + pwd, err := os.Getwd() + if err != nil { + logrus.Error(err) + } + logrus.Debugf("START: %v in %s", os.Args, pwd) + } +} + +func logTheseApps() bool { + // TODO: mmm, not very functional. + if filepath.Base(os.Args[0]) == "ros" || + filepath.Base(os.Args[0]) == "host_ros" || + filepath.Base(os.Args[0]) == "system-docker" { + return false + } + return true +} + +// InitDeferedLogger stores the log messages until FsReady() is called +// TODO: actually store them :) +// TODO: need to work out how to pass entries from a binary run before we switchfs back to init and have it store and write it later +func InitDeferedLogger() { + if logTheseApps() { + innerInit(true) + logrus.SetOutput(ioutil.Discard) + + pwd, err := os.Getwd() + if err != nil { + logrus.Error(err) + } + logrus.Debugf("START: %v in %s", os.Args, pwd) + } +} + +func innerInit(deferedHook bool) { if userHook != nil { return // we've already initialised it } - thisLog := logrus.New() - // Filter what the user sees (info level, unless they set --debug) - stdLogger := logrus.StandardLogger() - showuserHook, err := NewShowuserlogHook(stdLogger.Level) - if err != nil { - logrus.Errorf("hook failure %s", err) - return + // All logs go through the Hooks, and they choose what to do with them. + logrus.StandardLogger().Level = logrus.DebugLevel + + if logTheseApps() { + AddUserHook(deferedHook) } - - filename := "/dev/kmsg" - f, err := os.OpenFile(filename, os.O_WRONLY, 0644) - if err != nil { - logrus.Debugf("error opening %s: %s", filename, err) - } else { - // We're all set up, now we can make it global - appLog = thisLog - userHook = showuserHook - - thisLog.Hooks.Add(showuserHook) - logrus.StandardLogger().Hooks.Add(showuserHook) - - thisLog.Out = f - logrus.SetOutput(f) - thisLog.Level = logrus.DebugLevel - } - - pwd, err := os.Getwd() - if err != nil { - thisLog.Error(err) - } - - thisLog.Debugf("START: %v in %s", os.Args, pwd) +} + +func FsReady() { + filename := "/var/log/boot/" + filepath.Base(os.Args[0]) + ".log" + if err := os.MkdirAll(filepath.Dir(filename), os.ModeDir|0755); debugThisLogger && err != nil { + logrus.Errorf("FsReady mkdir(%s): %s", filename, err) + } + f, err := os.OpenFile(filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644) + if err != nil { + if debugThisLogger { + logrus.Errorf("FsReady opening %s: %s", filename, err) + } + } else { + if debugThisLogger { + logrus.Infof("Setting log output for %s to: %s", os.Args[0], filename) + } + logrus.SetOutput(f) + } +} + +// AddUserHook is used to filter what log messages are written to the screen +func AddUserHook(deferedHook bool) error { + if userHook != nil { + return nil + } + + printLogLevel := logrus.InfoLevel + + uh, err := NewShowuserlogHook(printLogLevel, filepath.Base(os.Args[0])) + if err != nil { + logrus.Errorf("error creating userHook(%s): %s", os.Args[0], err) + return err + } + userHook = uh + logrus.StandardLogger().Hooks.Add(uh) + + if debugThisLogger { + if deferedHook { + logrus.Debugf("------------info Starting defered User Hook (%s)", os.Args[0]) + } else { + logrus.Debugf("------------info Starting User Hook (%s)", os.Args[0]) + } + } + + return nil } diff --git a/log/showuserlog.go b/log/showuserlog.go index 7e6fa2be..eae27215 100644 --- a/log/showuserlog.go +++ b/log/showuserlog.go @@ -2,32 +2,52 @@ 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 + appName string } -func NewShowuserlogHook(l logrus.Level) (*ShowuserlogHook, error) { - return &ShowuserlogHook{l}, nil +// NewShowuserlogHook creates a new hook for use +func NewShowuserlogHook(l logrus.Level, app string) (*ShowuserlogHook, error) { + return &ShowuserlogHook{l, nil, []*logrus.Entry{}, app}, 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 { + //if f, err := os.OpenFile("/dev/kmsg", os.O_WRONLY, 0644); err != nil { + // fmt.Fprintf(f, "%s:%s: %s\n", hook.appName, entry.Level, entry.Message) + // f.Close() + //} else { + fmt.Printf("[ ] %s:%s: %s\n", hook.appName, entry.Level, entry.Message) + //} } - if entry.Level <= hook.Level { - fmt.Printf("> %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 syslog.Fire %v, %v", entry, 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 +58,23 @@ func (hook *ShowuserlogHook) Levels() []logrus.Level { logrus.PanicLevel, } } + +// NotUsedYetLogSystemReady Set up Syslog Hook, and replay any stored entries. +func (hook *ShowuserlogHook) NotUsedYetLogSystemReady() 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 { + line, _ := entry.String() + fmt.Printf("---- CATCHUP %s\n", line) + hook.syslogHook.Fire(entry) + } + } + + return nil +} diff --git a/os-config.tpl.yml b/os-config.tpl.yml index 65982b91..eece9d67 100644 --- a/os-config.tpl.yml +++ b/os-config.tpl.yml @@ -170,6 +170,7 @@ rancher: io.rancher.os.before: system-cron cron.schedule: "@hourly" uts: host + net: none privileged: true volumes_from: - command-volumes @@ -245,6 +246,7 @@ rancher: labels: io.rancher.os.scope: system uts: host + net: none privileged: true restart: always volumes: 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 b9db5a29..e1535625 100755 --- a/scripts/global.cfg +++ b/scripts/global.cfg @@ -1 +1,2 @@ -APPEND rancher.autologin=tty1 rancher.autologin=ttyS0 console=tty0 rancher.autologin=ttyS1 rancher.console=ttyS1 console=ttyS0 printk.devkmsg=on ${APPEND} +APPEND rancher.autologin=tty1 rancher.autologin=ttyS0 rancher.autologin=ttyS1 rancher.autologin=ttyS1 console=tty1 console=ttyS0 console=ttyS1 printk.devkmsg=on ${APPEND} + diff --git a/scripts/integration-test b/scripts/integration-test index 3c5b2c83..1b27cf6e 100755 --- a/scripts/integration-test +++ b/scripts/integration-test @@ -18,4 +18,4 @@ if [ "$RUNTEST" != "" ]; then RUNTEST="-check.f ${RUNTEST}" fi -go test -v -timeout 9999m $RUNTEST +time go test -v -timeout 9999m $RUNTEST diff --git a/scripts/layout b/scripts/layout index 40d52d8a..ddfa567d 100755 --- a/scripts/layout +++ b/scripts/layout @@ -11,7 +11,7 @@ INITRD_DIR=${BUILD}/initrd echo Create initrd layout in $INITRD_DIR rm -rf ${INITRD_DIR} -mkdir -p ${INITRD_DIR}/usr/{etc,bin,share/ros,var/lib/cni/bin} +mkdir -p ${INITRD_DIR}/usr/{etc,lib,bin,share/ros,var/lib/cni/bin} ./scripts/template @@ -39,6 +39,8 @@ SUPPORT_URL="https://forums.rancher.com/c/rancher-os" BUG_REPORT_URL="https://github.com/rancher/os/issues" BUILD_ID= HERE +# TODO: usr/lib dir is overwritten by the kernel modules and firmware +ln -s ../share/ros/os-release ${INITRD_DIR}/usr/lib/ # Support upgrades from old persistent consoles that bind mount these touch ${INITRD_DIR}/usr/bin/docker-containerd 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/tests/installer_test.go b/tests/installer_test.go index cd76edd7..71172ac3 100755 --- a/tests/installer_test.go +++ b/tests/installer_test.go @@ -201,7 +201,7 @@ sudo ros service start network sleep 1 ip a echo "===================" -sudo ros install --force --no-reboot --device /dev/vda -c config.yml -a "console=ttyS0 rancher.console=ttyS0 rancher.autologin=ttyS0 rancher.console=ttyS1 rancher.autologin=ttyS1 rancher.debug=true" +sudo ros install --force --no-reboot --device /dev/vda -c config.yml -a "console=ttyS0 rancher.autologin=ttyS0 console=ttyS1 rancher.autologin=ttyS1 rancher.debug=true" sync `) time.Sleep(500 * time.Millisecond) diff --git a/tests/network_test.go b/tests/network_test.go index 6e2c5286..306a59bc 100755 --- a/tests/network_test.go +++ b/tests/network_test.go @@ -59,7 +59,7 @@ func (s *QemuSuite) TestNetworkBootCfg(c *C) { " valid_lft forever preferred_lft forever\n"+ "4: eth2: mtu 1500 qdisc noop state DOWN group default qlen 1000\n"+ "5: eth3: mtu 1500 qdisc noop state DOWN group default qlen 1000\n"+ - "6: docker-sys: mtu 1500 qdisc noqueue state DOWN group default qlen 1000\n"+ + "6: docker-sys: XXXXXXX......\n"+ " inet 172.18.42.2/16 scope global docker-sys\n"+ " valid_lft forever preferred_lft forever\n"+ " inet6 XX::XX:XX:XX:XX/64 scope link \n"+ @@ -73,6 +73,7 @@ func (s *QemuSuite) TestNetworkBootCfg(c *C) { // TODO: figure out why sometimes loopback is scope global "sed 's/scope host lo/scope XXXX lo/g' | sed 's/scope global lo/scope XXXX lo/g' | "+ "sed 's/inet 10\\.0\\.2\\..*\\/24 brd/inet XX.XX.XX.XX\\/24 brd/' | "+ + "sed 's/6: docker-sys: .*/6: docker-sys: XXXXXXX....../g' | "+ "sed 's/8: docker0: .*/8: docker0: XXXXXXX....../g' | "+ "sed '/inet6 fe80::5054:ff:fe12:.*\\/64/!s/inet6 .*\\/64 scope/inet6 XX::XX:XX:XX:XX\\/64 scope/'", // fe80::18b6:9ff:fef5:be33 diff --git a/tests/ros_config_test.go b/tests/ros_config_test.go index 367d480f..e81b20a7 100644 --- a/tests/ros_config_test.go +++ b/tests/ros_config_test.go @@ -84,9 +84,4 @@ sudo ros config export --full | grep "labels" sudo ros config export --private --full | grep "PRIVATE KEY"`) - s.CheckCall(c, ` -set -x -e -sudo ros config get rancher.services_include | grep kvm-vm-tools -`) - } 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/util/network/network.go b/util/network/network.go index 6223c339..c00f741e 100644 --- a/util/network/network.go +++ b/util/network/network.go @@ -7,7 +7,6 @@ import ( "net/http" "os" "strings" - "time" yaml "github.com/cloudfoundry-incubator/candiedyaml" @@ -89,29 +88,33 @@ func loadFromNetwork(location string) ([]byte, error) { SetProxyEnvironmentVariables(cfg) var err error - for i := 0; i < 300; i++ { - updateDNSCache() + // Sven thinks that the dhcpcd --wait we added makes this less necessary + //for i := 0; i < 300; i++ { + updateDNSCache() - var resp *http.Response - resp, err = http.Get(location) - if err == nil { - defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("non-200 http response: %d", resp.StatusCode) - } - - bytes, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, err - } - - cacheAdd(location, bytes) - return bytes, nil + var resp *http.Response + log.Debugf("LoadFromNetwork(%s)", location) + resp, err = http.Get(location) + log.Debugf("LoadFromNetwork(%s) returned %v", location, resp) + log.Debugf("LoadFromNetwork(%s) error %v", location, err) + if err == nil { + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("non-200 http response: %d", resp.StatusCode) } - time.Sleep(100 * time.Millisecond) + bytes, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + cacheAdd(location, bytes) + return bytes, nil } + // time.Sleep(100 * time.Millisecond) + //} + return nil, err } 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/docker/docker/docker/docker.go b/vendor/github.com/docker/docker/docker/docker.go index cbb1e4cf..c66eeca1 100644 --- a/vendor/github.com/docker/docker/docker/docker.go +++ b/vendor/github.com/docker/docker/docker/docker.go @@ -7,10 +7,9 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/docker/api/client" "github.com/docker/docker/cli" - "github.com/docker/docker/dockerversion" flag "github.com/docker/docker/pkg/mflag" "github.com/docker/docker/pkg/term" - "github.com/docker/docker/utils" + "github.com/rancher/os/config" ) func Main() { @@ -68,10 +67,60 @@ func Main() { } } -func showVersion() { - if utils.ExperimentalBuild() { - fmt.Printf("Docker version %s, build %s, experimental\n", dockerversion.Version, dockerversion.GitCommit) - } else { - fmt.Printf("Docker version %s, build %s\n", dockerversion.Version, dockerversion.GitCommit) +// RancherOSMain lets us set the logger, instead of hardcoding it to Stderr +func RancherOSMain() { + // Set terminal emulation based on platform as required. + stdin, stdout, stderr := term.StdStreams() + + flag.Merge(flag.CommandLine, clientFlags.FlagSet, commonFlags.FlagSet) + + flag.Usage = func() { + fmt.Fprint(stdout, "Usage: system-docker [OPTIONS] COMMAND [arg...]\n"+daemonUsage+" docker [ --help | -v | --version ]\n\n") + fmt.Fprint(stdout, "A self-sufficient runtime for containers.\n\nOptions:\n") + + flag.CommandLine.SetOutput(stdout) + flag.PrintDefaults() + + help := "\nCommands:\n" + + for _, cmd := range dockerCommands { + help += fmt.Sprintf(" %-10.10s%s\n", cmd.Name, cmd.Description) + } + + help += "\nRun 'system-docker COMMAND --help' for more information on a command." + fmt.Fprintf(stdout, "%s\n", help) + } + + flag.Parse() + + if *flVersion { + showVersion() + return + } + + if *flHelp { + // if global flag --help is present, regardless of what other options and commands there are, + // just print the usage. + flag.Usage() + return + } + + clientCli := client.NewDockerCli(stdin, stdout, stderr, clientFlags) + + c := cli.New(clientCli, daemonCli) + if err := c.Run(flag.Args()...); err != nil { + if sterr, ok := err.(cli.StatusError); ok { + if sterr.Status != "" { + fmt.Fprintln(stderr, sterr.Status) + os.Exit(1) + } + os.Exit(sterr.StatusCode) + } + fmt.Fprintln(stderr, err) + os.Exit(1) } } + +func showVersion() { + fmt.Printf("RancherOS System-Docker version %s\n", config.Version) +} 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 {