1
0
mirror of https://github.com/rancher/os.git synced 2025-08-02 07:24:28 +00:00

Merge pull request #1978 from SvenDowideit/fix-hypervisor-network-timeouts

A large number of fixes
This commit is contained in:
Sven Dowideit 2017-07-13 13:09:51 +10:00 committed by GitHub
commit f36eb70e74
39 changed files with 1059 additions and 385 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
#!/bin/bash
set -e
set -ex
export ARCH=${ARCH:-"amd64"}
BASE=images

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
#!/bin/bash
set -e
set -ex
source $(dirname $0)/version

View File

@ -1,5 +1,5 @@
#!/bin/bash
set -e
set -ex
cd $(dirname $0)/..

View File

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

View File

@ -59,7 +59,7 @@ func (s *QemuSuite) TestNetworkBootCfg(c *C) {
" valid_lft forever preferred_lft forever\n"+
"4: eth2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000\n"+
"5: eth3: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000\n"+
"6: docker-sys: <NO-CARRIER,BROADCAST,MULTICAST,UP> 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

View File

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

View File

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

View File

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

View File

@ -1,9 +1,7 @@
language: go
go:
- 1.3
- 1.4
- 1.5
- 1.6
- 1.7
- tip
install:
- go get -t ./...

View File

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

View File

@ -1,5 +1,11 @@
# Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:"/>&nbsp;[![Build Status](https://travis-ci.org/Sirupsen/logrus.svg?branch=master)](https://travis-ci.org/Sirupsen/logrus)&nbsp;[![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.

View File

@ -0,0 +1,39 @@
# Syslog Hooks for Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":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)
}
}
```

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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