tether

package
v1.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 4, 2018 License: Apache-2.0 Imports: 49 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// MaxDeathRecords The maximum number of records to keep for restarting processes
	MaxDeathRecords = 5
)

Variables

View Source
var (
	// Used to access the acutal system paths and files
	Sys = shared.Sys
	// Used to access and manipulate the tether modified bind sources
	// that are mounted over the system ones.
	BindSys = system.NewWithRoot("/.tether")
)

Sys is used to configure where the target system files are

Functions

func ApplyEndpoint

func ApplyEndpoint(nl Netlink, t *BaseOperations, endpoint *NetworkEndpoint) error

func Mkdev

func Mkdev(majorNumber int, minorNumber int) int

Mkdev will hopefully get rolled into go.sys at some point

func ReloadConfig

func ReloadConfig() error

ReloadConfig signals the current process, which triggers the signal handler to reload the config.

Types

type BaseOperations

type BaseOperations struct {
	// contains filtered or unexported fields
}

func (*BaseOperations) AddrAdd

func (t *BaseOperations) AddrAdd(link netlink.Link, addr *netlink.Addr) error

func (*BaseOperations) AddrDel

func (t *BaseOperations) AddrDel(link netlink.Link, addr *netlink.Addr) error

func (*BaseOperations) AddrList

func (t *BaseOperations) AddrList(link netlink.Link, family int) ([]netlink.Addr, error)

func (*BaseOperations) Apply

func (t *BaseOperations) Apply(endpoint *NetworkEndpoint) error

func (*BaseOperations) Cleanup

func (t *BaseOperations) Cleanup() error

func (*BaseOperations) CopyExistingContent

func (t *BaseOperations) CopyExistingContent(source string) error

CopyExistingContent copies the underlying files shadowed by a mount on a directory to the volume mounted on the directory see bug https://github.com/vmware/vic/issues/3482

func (*BaseOperations) Fork

func (t *BaseOperations) Fork() error

Fork triggers vmfork and handles the necessary pre/post OS level operations

func (*BaseOperations) HandleUtilityExit

func (t *BaseOperations) HandleUtilityExit(pid, exitCode int) bool

func (*BaseOperations) LaunchUtility

func (t *BaseOperations) LaunchUtility(fn UtilityFn) (<-chan int, error)

LaunchUtility allows for starting, blocking on, and receiving the exit code of a process while in the presence of an embedded child reaper. The function passed in will be launched under lock and MUST NOT wait for the process to exit. It's expected the function be a closure wrapped around StartProcess or similar.

func (*BaseOperations) LinkByName

func (t *BaseOperations) LinkByName(name string) (netlink.Link, error)

func (*BaseOperations) LinkBySlot

func (t *BaseOperations) LinkBySlot(slot int32) (netlink.Link, error)

func (*BaseOperations) LinkSetAlias

func (t *BaseOperations) LinkSetAlias(link netlink.Link, alias string) error

func (*BaseOperations) LinkSetDown

func (t *BaseOperations) LinkSetDown(link netlink.Link) error

func (*BaseOperations) LinkSetName

func (t *BaseOperations) LinkSetName(link netlink.Link, name string) error

func (*BaseOperations) LinkSetUp

func (t *BaseOperations) LinkSetUp(link netlink.Link) error

func (*BaseOperations) MountLabel

func (t *BaseOperations) MountLabel(ctx context.Context, label, target string) error

MountLabel performs a mount with the label and target being absolute paths

func (*BaseOperations) MountTarget

func (t *BaseOperations) MountTarget(ctx context.Context, source url.URL, target string, mountOptions string) error

MountTarget performs a mount based on the target path from the source url This assumes that the source url is valid and available.

func (*BaseOperations) ProcessEnv

func (t *BaseOperations) ProcessEnv(session *SessionConfig) []string

ProcessEnv does OS specific checking and munging on the process environment prior to launch

func (*BaseOperations) RouteAdd

func (t *BaseOperations) RouteAdd(route *netlink.Route) error

func (*BaseOperations) RouteDel

func (t *BaseOperations) RouteDel(route *netlink.Route) error

func (*BaseOperations) RuleList

func (t *BaseOperations) RuleList(family int) ([]netlink.Rule, error)

func (*BaseOperations) SetHostname

func (t *BaseOperations) SetHostname(hostname string, aliases ...string) error

SetHostname sets both the kernel hostname and /etc/hostname to the specified string

func (*BaseOperations) Setup

func (t *BaseOperations) Setup(config Config) error

type Config

type Config interface {
	UpdateNetworkEndpoint(e *NetworkEndpoint) error
	Flush() error
}

type ContainerSigner

type ContainerSigner struct {
	// contains filtered or unexported fields
}

func NewSigner

func NewSigner(id string) *ContainerSigner

func (ContainerSigner) Marshal

func (c ContainerSigner) Marshal() []byte

func (*ContainerSigner) PublicKey

func (c *ContainerSigner) PublicKey() ssh.PublicKey

func (*ContainerSigner) Sign

func (c *ContainerSigner) Sign(rand io.Reader, data []byte) (*ssh.Signature, error)

we're going to ignore everything for the moment as we're repurposing the host key for the id. later we may use a genuine host key and an SSH out-of-band request to get the container id.

func (ContainerSigner) Type

func (c ContainerSigner) Type() string

func (ContainerSigner) Verify

func (c ContainerSigner) Verify(data []byte, sig *ssh.Signature) error

type DHCPInfo

type DHCPInfo struct {
	Assigned    net.IPNet
	Nameservers []net.IP
	Gateway     net.IPNet
}

type ExecutorConfig

type ExecutorConfig struct {
	// allow us to lock the maps when config is being updated
	// subelements tend to have their own locks
	sync.Mutex

	// The name of the system
	Name string `vic:"0.1" scope:"read-only" key:"common/name"`

	// ID corresponds to that of the primary session
	ID string `vic:"0.1" scope:"read-only" key:"common/id"`

	// Debug is a numeric level that controls extent of debugging
	DebugLevel int `vic:"0.1" scope:"read-only" key:"diagnostics/debug"`

	// Sessions is the set of sessions currently hosted by this executor
	// These are keyed by session ID
	Sessions map[string]*SessionConfig `vic:"0.1" scope:"read-only" key:"sessions"`

	// Execs is the set of non-persistent sessions hosted by this executor
	Execs map[string]*SessionConfig `vic:"0.1" scope:"read-only,non-persistent" key:"execs"`

	// Maps the mount name to the detail mount specification
	Mounts map[string]executor.MountSpec `vic:"0.1" scope:"read-only" key:"mounts"`

	// This describes an executors presence on a network, and contains sufficient
	// information to configure the interface in the guest.
	Networks map[string]*NetworkEndpoint `vic:"0.1" scope:"read-only" key:"networks"`

	// Key is the host key used during communicate back with the Interaction endpoint if any
	// Used if the in-guest tether is responsible for authenticating the connection
	Key []byte `vic:"0.1" scope:"read-only" key:"key"`

	// AsymmetricRouting is set to true if the VCH needs to be setup for asymmetric routing
	AsymmetricRouting bool `vic:"0.1" scope:"read-only" key:"asymrouting"`

	// Hostname and domainname provided by personality
	Hostname   string `vic:"0.1" scope:"read-only" key:"hostname"`
	Domainname string `vic:"0.1" scope:"read-only" key:"domainname"`
	// contains filtered or unexported fields
}

type Extension

type Extension interface {
	Start(System) error
	Reload(config *ExecutorConfig) error
	Stop() error
}

Extension is a very simple extension interface for supporting code that need to be notified when the configuration is reloaded.

type MockHosts

type MockHosts struct{}

func (MockHosts) Copy

func (h MockHosts) Copy(conf etcconf.Conf) error

func (MockHosts) HostIP

func (h MockHosts) HostIP(_ string) []net.IP

func (MockHosts) Load

func (h MockHosts) Load() error

func (MockHosts) Path

func (h MockHosts) Path() string

func (MockHosts) RemoveAll

func (h MockHosts) RemoveAll()

func (MockHosts) RemoveHost

func (h MockHosts) RemoveHost(_ string)

func (MockHosts) Save

func (h MockHosts) Save() error

func (MockHosts) SetHost

func (h MockHosts) SetHost(_ string, _ net.IP)

type MockResolvConf

type MockResolvConf struct{}

func (MockResolvConf) AddNameservers

func (h MockResolvConf) AddNameservers(...net.IP)

func (MockResolvConf) Attempts

func (h MockResolvConf) Attempts() uint

func (MockResolvConf) Copy

func (h MockResolvConf) Copy(conf etcconf.Conf) error

func (MockResolvConf) Load

func (h MockResolvConf) Load() error

func (MockResolvConf) Nameservers

func (h MockResolvConf) Nameservers() []net.IP

func (MockResolvConf) Path

func (h MockResolvConf) Path() string

func (MockResolvConf) RemoveNameservers

func (h MockResolvConf) RemoveNameservers(...net.IP)

func (MockResolvConf) Save

func (h MockResolvConf) Save() error

func (MockResolvConf) SetAttempts

func (h MockResolvConf) SetAttempts(uint)

func (MockResolvConf) SetTimeout

func (h MockResolvConf) SetTimeout(time.Duration)

func (MockResolvConf) Timeout

func (h MockResolvConf) Timeout() time.Duration

type MockSyscall

type MockSyscall struct{}

func (MockSyscall) Mount

func (m MockSyscall) Mount(source string, target string, fstype string, flags uintptr, data string) error

func (MockSyscall) Sethostname

func (m MockSyscall) Sethostname(_ []byte) error
func (m MockSyscall) Symlink(_, _ string) error

func (MockSyscall) Unmount

func (m MockSyscall) Unmount(_ string, _ int) error
type Netlink interface {
	LinkByName(string) (netlink.Link, error)
	LinkSetName(netlink.Link, string) error
	LinkSetDown(netlink.Link) error
	LinkSetUp(netlink.Link) error
	LinkSetAlias(netlink.Link, string) error
	AddrList(netlink.Link, int) ([]netlink.Addr, error)
	AddrAdd(netlink.Link, *netlink.Addr) error
	AddrDel(netlink.Link, *netlink.Addr) error
	RouteAdd(*netlink.Route) error
	RouteDel(*netlink.Route) error
	RuleList(family int) ([]netlink.Rule, error)

	LinkBySlot(slot int32) (netlink.Link, error)
}

NetLink gives us an interface to the netlink calls used so that we can test the calling code.

type NetworkEndpoint

type NetworkEndpoint struct {
	// Common.Name - the nic alias requested (only one name and one alias possible in linux)
	// Common.ID - pci slot of the vnic allowing for interface identifcation in-guest
	executor.Common

	// Whether this endpoint's IP was specified by the client (true if it was)
	Static bool `vic:"0.1" scope:"read-only" key:"static"`

	// IP address to assign
	IP *net.IPNet `vic:"0.1" scope:"read-only" key:"ip"`

	// Actual IP address assigned
	Assigned net.IPNet `vic:"0.1" scope:"read-write" key:"assigned"`

	// The network in which this information should be interpreted. This is embedded directly rather than
	// as a pointer so that we can ensure the data is consistent
	Network executor.ContainerNetwork `vic:"0.1" scope:"read-only" key:"network"`

	// DHCP runtime info
	DHCP *DHCPInfo `vic:"0.1" scope:"read-only" recurse:"depth=0"`

	Ports []string `vic:"0.1" scope:"read-only" key:"ports"`

	// is this endpoint connected to an internal network?
	Internal bool `vic:"0.1" scope:"read-only" key:"internal"`
	// contains filtered or unexported fields
}

func (*NetworkEndpoint) IsDynamic

func (e *NetworkEndpoint) IsDynamic() bool

type Operations

type Operations interface {
	Setup(Config) error
	Cleanup() error
	// Log returns the tether debug log writer
	Log() (io.Writer, error)

	SetHostname(hostname string, aliases ...string) error
	SetupFirewall(ctx context.Context, config *ExecutorConfig) error
	Apply(endpoint *NetworkEndpoint) error
	MountLabel(ctx context.Context, label, target string) error
	MountTarget(ctx context.Context, source url.URL, target string, mountOptions string) error
	CopyExistingContent(source string) error
	Fork() error
	// Returns two DynamicMultiWriters for stdout and stderr
	SessionLog(session *SessionConfig) (dio.DynamicMultiWriter, dio.DynamicMultiWriter, error)
	// Returns a function to invoke after the session state has been persisted
	HandleSessionExit(config *ExecutorConfig, session *SessionConfig) func()
	ProcessEnv(session *SessionConfig) []string
	// LaunchUtility starts a process and provides a way to block on completion and retrieve
	// it's exit code. This is needed to co-exist with a childreaper.
	LaunchUtility(UtilityFn) (<-chan int, error)
	// HandleUtilityExit will process the utility exit. If the pid cannot be matched to a launched
	// utility process then this returns false and does nothing.
	HandleUtilityExit(pid, exitCode int) bool
}

Operations defines the set of operations that Tether depends upon. These are split out for: * portability * dependency injection (primarily for testing) * behavioural control (e.g. what behaviour is required when a session exits)

type SessionConfig

type SessionConfig struct {
	// Protects the structure
	sync.Mutex `vic:"0.1" scope:"read-only" recurse:"depth=0"`

	// The primary session may have the same ID as the executor owning it
	executor.Common `vic:"0.1" scope:"read-only" key:"common"`
	executor.Detail `vic:"0.1" scope:"read-write" key:"detail"`

	// Diagnostics holds basic diagnostics data
	Diagnostics executor.Diagnostics `vic:"0.1" scope:"read-write" key:"diagnostics"`

	// The primary process for the session
	Cmd exec.Cmd `vic:"0.1" scope:"read-only" key:"cmd" recurse:"depth=2,nofollow"`

	// The exit status of the process, if any
	ExitStatus int `vic:"0.1" scope:"read-write" key:"status"`

	Started string `vic:"0.1" scope:"read-write" key:"started"`

	// Allow attach
	Attach bool `vic:"0.1" scope:"read-only" key:"attach"`

	OpenStdin bool `vic:"0.1" scope:"read-only" key:"openstdin"`

	// Delay launching the Cmd until an attach request comes
	RunBlock bool `vic:"0.1" scope:"read-write" key:"runblock"`

	// Should this config be activated or not
	Active bool `vic:"0.1" scope:"read-only" key:"active"`

	// Allocate a tty or not
	Tty bool `vic:"0.1" scope:"read-only" key:"tty"`

	// Restart controls whether a process gets relaunched if it exists
	Restart bool `vic:"0.1" scope:"read-only" key:"restart"`

	// StopSignal is the signal name or number used to stop a container
	StopSignal string `vic:"0.1" scope:"read-only" key:"stopSignal"`

	// User and group for setuid programs
	User  string `vic:"0.1" scope:"read-only" key:"user"`
	Group string `vic:"0.1" scope:"read-only" key:"group"`

	// if there's a pty then we need additional management data
	Pty       *os.File               `vic:"0.1" scope:"read-only" recurse:"depth=0"`
	Outwriter dio.DynamicMultiWriter `vic:"0.1" scope:"read-only" recurse:"depth=0"`
	Errwriter dio.DynamicMultiWriter `vic:"0.1" scope:"read-only" recurse:"depth=0"`
	Reader    dio.DynamicMultiReader `vic:"0.1" scope:"read-only" recurse:"depth=0"`

	StdinPipe  io.WriteCloser `vic:"0.1" scope:"read-only" recurse:"depth=0"`
	StdoutPipe io.ReadCloser  `vic:"0.1" scope:"read-only" recurse:"depth=0"`
	StderrPipe io.ReadCloser  `vic:"0.1" scope:"read-only" recurse:"depth=0"`

	// Blocks launching the process.
	// The channel contains no value; we’re only interested in its closed property.
	ClearToLaunch chan struct{} `vic:"0.1" scope:"read-only" recurse:"depth=0"`
	// contains filtered or unexported fields
}

SessionConfig defines the content of a session - this maps to the root of a process tree inside an executor This is close to but not perfectly aligned with the new docker/docker/daemon/execdriver/driver:CommonProcessConfig

func (*SessionConfig) Unblock

func (session *SessionConfig) Unblock() func()

Unblock takes a lock and constructs a function to call for releasing an explicit block. Does NOT take a session lock

type System

type System interface {
	// LaunchUtility starts a process and provides a way to block on completion and retrieve
	// it's exit code. This is needed to co-exist with a childreaper.
	LaunchUtility(UtilityFn) (<-chan int, error)

	MountLabel(ctx context.Context, label, target string) error
}

System is a very preliminary interface that provides extensions with a means by which to perform system style operations. This should be designed with intent to provide sufficient abstraction that vic-init, tether can be run by vcsim. Odds are that a significant portion of the methods on this interface will be defined in vcsim and this interface will simply embed the vcsim interface. There may well be overlap with shared.Sys that needs to be resolved

For now its sole purpose is to allow extensions access to the specific portions of BaseOperations that they actively use.

type Tether

type Tether interface {
	Start() error
	Stop() error
	Reload()
	Register(name string, ext Extension)
}

Tether presents the consumption interface for code needing to run a tether

type TetherKey

type TetherKey struct{}

type Toolbox

type Toolbox struct {
	*toolbox.Service
	// contains filtered or unexported fields
}

Toolbox is a tether extension that wraps toolbox.Service

func NewToolbox

func NewToolbox() *Toolbox

NewToolbox returns a tether.Extension that wraps the vsphere/toolbox service

func (*Toolbox) InContainer

func (t *Toolbox) InContainer() *Toolbox

InContainer configures the toolbox to run within a container VM

func (*Toolbox) Reload

func (t *Toolbox) Reload(config *ExecutorConfig) error

Reload implementation of the tether.Extension interface

func (*Toolbox) Start

func (t *Toolbox) Start(system System) error

Start implementation of the tether.Extension interface

func (*Toolbox) Stop

func (t *Toolbox) Stop() error

Stop implementation of the tether.Extension interface

type UtilityFn

type UtilityFn func() (*os.Process, error)

UtilityFn is the sigature of a function that can be used to launch a utility process

Directories

Path Synopsis
Package shared is intended for isolating constants and minor functions required to be consistent across packages so as to avoid transitive package includes
Package shared is intended for isolating constants and minor functions required to be consistent across packages so as to avoid transitive package includes

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL