toolbox

package
v0.20.0 Latest Latest
Warning

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

Go to latest
Published: Feb 7, 2019 License: Apache-2.0 Imports: 29 Imported by: 0

README

toolbox - VMware guest tools library for Go

Overview

The toolbox library is a lightweight, extensible framework for implementing VMware guest tools functionality. The primary focus of the library is the implementation of VM guest RPC protocols, transport and dispatch. These protocols are undocumented for the most part, but open-vm-tools serves as a reference implementation. The toolbox provides default implementations of the supported RPCs, which can be overridden and/or extended by consumers.

Supported features

Feature list from the perspective of vSphere public API interaction. The properties, objects and methods listed are relative to the VirtualMachine managed object type.

guest.toolsVersionStatus property

The toolbox reports version as guestToolsUnmanaged.

See ToolsVersionStatus

guest.toolsRunningStatus and guest.guestState properties

The VMX determines these values based on the toolbox's response to the ping RPC.

guest.ipAddress property

The VMX requests this value via the Set_Option broadcastIP RPC.

The default value can be overridden by setting the Service.PrimaryIP function.

See vim.vm.GuestInfo

guest.net property

This data is pushed to the VMX using the SendGuestInfo(INFO_IPADDRESS_V3) RPC.

See GuestNicInfo.

ShutdownGuest and RebootGuest methods

The PowerCommandHandler provides power hooks for customized guest shutdown and reboot.

GuestAuthManager object

Not supported, but authentication can be customized.

See vim.vm.guest.AuthManager

GuestFileManager object
Method Supported Client Examples
ChangeFileAttributesInGuest Yes chmod
chown
touch
CreateTemporaryDirectoryInGuest Yes mktemp
CreateTemporaryFileInGuest Yes mktemp
DeleteDirectoryInGuest Yes rmdir
DeleteFileInGuest Yes rm
InitiateFileTransferFromGuest Yes download
InitiateFileTransferToGuest Yes upload
ListFilesInGuest Yes ls
MakeDirectoryInGuest Yes mkdir
MoveDirectoryInGuest Yes mv
MoveFileInGuest Yes mv

See vim.vm.guest.FileManager

GuestProcessManager

Currently, the ListProcessesInGuest and TerminateProcessInGuest methods only apply those processes and goroutines started by StartProgramInGuest.

Method Supported Client Examples
ListProcessesInGuest Yes ps
ReadEnvironmentVariableInGuest Yes getenv
StartProgramInGuest Yes start
TerminateProcessInGuest Yes kill

See vim.vm.guest.ProcessManager

Extensions

Authentication

Guest operations can be authenticated using the toolbox.CommandServer.Authenticate hook.

Go functions

The toolbox ProcessManager can manage both OS processes and Go functions running as go routines.

File handlers

The hgfs.FileHandler interface can be used to customize file transfer.

Process I/O

The toolbox provides support for I/O redirection without the use of disk files within the guest. Access to stdin, stdout and stderr streams is implemented as an hgfs.FileHandler within the ProcessManager.

See toolbox.Client and govc guest.run

http.RoundTripper

Building on top of the process I/O functionality, toolbox.NewProcessRoundTrip can be used to start a Go function to implement the http.RoundTripper interface over vmx guest RPC. This makes it possible to use the Go http.Client without network access to the VM or to a port that is bound to the guest's loopback address. It is intended for use with bootstrap configuration for example.

Directory archives

The toolbox provides support for transferring directories to and from guests as gzip'd tar streams, without writing the tar file itself to the guest file system. Archive supports is implemented as an hgfs.FileHandler within the hgfs package. See hgfs.NewArchiveHandler

Linux /proc file access

With standard vmware-tools, the file size is reported as returned by stat() and hence a Content-Length header of size 0. The toolbox reports /proc file size as hgfs.LargePacketMax to enable transfer of these files. Note that if the file data fits within in hgfs.LargePacketMax, the Content-Length header will be correct as it is sent after the first read by the vmx. However, if the file data exceeds hgfs.LargePacketMax, the Content-Length will be hgfs.LargePacketMax, and client side will truncate to that size.

Testing

The Go tests cover most of the toolbox code and can be run on any Linux or MacOSX machine, virtual or otherwise.

To test the toolbox with vSphere API interaction, it must be run inside a VM managed by vSphere without the standard vmtoolsd running.

The toolbox-test.sh can be used to run the full suite of toolbox tests with vSphere API interaction. Use the -s flag to start the standalone version of the toolbox and leave it running, to test vSphere interaction without running the test suite.

Consumers of the toolbox library

Supported guests

The toolbox guest RPC implementations tend to be simple and portable thanks to the Go standard library, but are only supported on Linux currently. Support for other guests, such as Windows, has been kept in mind but not yet tested.

Supported vSphere Versions

The toolbox is supported with vSphere 6.0 and 6.5, but may function with older versions.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrNotVirtualWorld = errors.New("not in a virtual world")
)
View Source
var ProcessFuncIO = struct {
	key int64
}{vix.CommandMagicWord}

ProcessFuncIO is the Context key to access optional ProcessIO

View Source
var (
	Trace = false
)

Functions

func DecodeXDR

func DecodeXDR(buf []byte, val interface{}) error

func DefaultIP

func DefaultIP() string

DefaultIP is used by default when responding to a Set_Option broadcastIP request It can be overridden with the Service.PrimaryIP field

func DefaultStartCommand

func DefaultStartCommand(m *ProcessManager, r *vix.StartProgramRequest) (int64, error)

func EncodeXDR

func EncodeXDR(val interface{}) ([]byte, error)

func GuestInfoCommand

func GuestInfoCommand(kind int, req []byte) []byte

func GuestInfoNicInfoRequest

func GuestInfoNicInfoRequest() ([]byte, error)

func Halt

func Halt() error

func Reboot

func Reboot() error

Types

type Channel

type Channel interface {
	Start() error
	Stop() error
	Send([]byte) error
	Receive() ([]byte, error)
}

Channel abstracts the guest<->vmx RPC transport

func NewBackdoorChannelIn

func NewBackdoorChannelIn() Channel

NewBackdoorChannelIn creates a Channel for use with the TCLO protocol

func NewBackdoorChannelOut

func NewBackdoorChannelOut() Channel

NewBackdoorChannelOut creates a Channel for use with the RPCI protocol

func NewTraceChannel

func NewTraceChannel(c Channel) Channel

type ChannelOut

type ChannelOut struct {
	Channel
}

ChannelOut extends Channel to provide RPCI protocol helpers

func (*ChannelOut) Request

func (c *ChannelOut) Request(request []byte) ([]byte, error)

Request sends an RPC command to the vmx and checks the return code for success or error

type CommandHandler

type CommandHandler func(vix.CommandRequestHeader, []byte) ([]byte, error)

type CommandServer

type CommandServer struct {
	Out *ChannelOut

	ProcessManager *ProcessManager

	Authenticate func(vix.CommandRequestHeader, []byte) error

	ProcessStartCommand func(*ProcessManager, *vix.StartProgramRequest) (int64, error)

	FileServer *hgfs.Server
	// contains filtered or unexported fields
}

func (*CommandServer) CreateDirectory

func (c *CommandServer) CreateDirectory(header vix.CommandRequestHeader, data []byte) ([]byte, error)

func (*CommandServer) CreateTemporaryDirectory

func (c *CommandServer) CreateTemporaryDirectory(header vix.CommandRequestHeader, data []byte) ([]byte, error)

func (*CommandServer) CreateTemporaryFile

func (c *CommandServer) CreateTemporaryFile(header vix.CommandRequestHeader, data []byte) ([]byte, error)

func (*CommandServer) DeleteDirectory

func (c *CommandServer) DeleteDirectory(header vix.CommandRequestHeader, data []byte) ([]byte, error)

func (*CommandServer) DeleteFile

func (c *CommandServer) DeleteFile(header vix.CommandRequestHeader, data []byte) ([]byte, error)

func (*CommandServer) Dispatch

func (c *CommandServer) Dispatch(data []byte) ([]byte, error)

func (*CommandServer) GetToolsState

func (c *CommandServer) GetToolsState(_ vix.CommandRequestHeader, _ []byte) ([]byte, error)

func (*CommandServer) InitiateFileTransferFromGuest

func (c *CommandServer) InitiateFileTransferFromGuest(header vix.CommandRequestHeader, data []byte) ([]byte, error)

func (*CommandServer) InitiateFileTransferToGuest

func (c *CommandServer) InitiateFileTransferToGuest(header vix.CommandRequestHeader, data []byte) ([]byte, error)

func (*CommandServer) KillProcess

func (c *CommandServer) KillProcess(header vix.CommandRequestHeader, data []byte) ([]byte, error)

func (*CommandServer) ListFiles

func (c *CommandServer) ListFiles(header vix.CommandRequestHeader, data []byte) ([]byte, error)

func (*CommandServer) ListProcesses

func (c *CommandServer) ListProcesses(header vix.CommandRequestHeader, data []byte) ([]byte, error)

func (*CommandServer) MoveDirectory

func (c *CommandServer) MoveDirectory(header vix.CommandRequestHeader, data []byte) ([]byte, error)

func (*CommandServer) MoveFile

func (c *CommandServer) MoveFile(header vix.CommandRequestHeader, data []byte) ([]byte, error)

func (*CommandServer) ProcessHgfsPacket

func (c *CommandServer) ProcessHgfsPacket(header vix.CommandRequestHeader, data []byte) ([]byte, error)

func (*CommandServer) ReadEnvironmentVariables

func (c *CommandServer) ReadEnvironmentVariables(header vix.CommandRequestHeader, data []byte) ([]byte, error)

func (*CommandServer) RegisterHandler

func (c *CommandServer) RegisterHandler(op uint32, handler CommandHandler)

func (*CommandServer) SetGuestFileAttributes

func (c *CommandServer) SetGuestFileAttributes(header vix.CommandRequestHeader, data []byte) ([]byte, error)

func (*CommandServer) StartCommand

func (c *CommandServer) StartCommand(header vix.CommandRequestHeader, data []byte) ([]byte, error)

type DNSConfigInfo

type DNSConfigInfo struct {
	HostName   *string `xdr:"optional"`
	DomainName *string `xdr:"optional"`
	Servers    []TypedIPAddress
	Search     *string `xdr:"optional"`
}

type DhcpConfigInfo

type DhcpConfigInfo struct {
	Enabled  bool
	Settings string
}

type GuestNicInfo

type GuestNicInfo struct {
	Version int32
	V3      *NicInfoV3 `xdr:"optional"`
}

func DefaultGuestNicInfo

func DefaultGuestNicInfo() *GuestNicInfo

func NewGuestNicInfo

func NewGuestNicInfo() *GuestNicInfo

type GuestNicV3

type GuestNicV3 struct {
	MacAddress       string
	IPs              []IPAddressEntry
	DNSConfigInfo    *DNSConfigInfo  `xdr:"optional"`
	WinsConfigInfo   *WinsConfigInfo `xdr:"optional"`
	DhcpConfigInfov4 *DhcpConfigInfo `xdr:"optional"`
	DhcpConfigInfov6 *DhcpConfigInfo `xdr:"optional"`
}

func (*GuestNicV3) AddIP

func (nic *GuestNicV3) AddIP(addr net.Addr)

type Handler

type Handler func([]byte) ([]byte, error)

Handler is given the raw argument portion of an RPC request and returns a response

type IPAddressEntry

type IPAddressEntry struct {
	Address      TypedIPAddress
	PrefixLength uint32
	Origin       *int32 `xdr:"optional"`
	Status       *int32 `xdr:"optional"`
}

type InetCidrRouteEntry

type InetCidrRouteEntry struct {
	Dest         TypedIPAddress
	PrefixLength uint32
	NextHop      *TypedIPAddress `xdr:"optional"`
	IfIndex      uint32
	Type         int32
	Metric       uint32
}

type NicInfoV3

type NicInfoV3 struct {
	Nics             []GuestNicV3
	Routes           []InetCidrRouteEntry
	DNSConfigInfo    *DNSConfigInfo  `xdr:"optional"`
	WinsConfigInfo   *WinsConfigInfo `xdr:"optional"`
	DhcpConfigInfov4 *DhcpConfigInfo `xdr:"optional"`
	DhcpConfigInfov6 *DhcpConfigInfo `xdr:"optional"`
}

type PowerCommand

type PowerCommand struct {
	Handler func() error
	// contains filtered or unexported fields
}

func (*PowerCommand) Dispatch

func (c *PowerCommand) Dispatch([]byte) ([]byte, error)

type PowerCommandHandler

type PowerCommandHandler struct {
	Halt    PowerCommand
	Reboot  PowerCommand
	PowerOn PowerCommand
	Resume  PowerCommand
	Suspend PowerCommand
}

type Process

type Process struct {
	ProcessState

	Start func(*Process, *vix.StartProgramRequest) (int64, error)
	Wait  func() error
	Kill  context.CancelFunc
	// contains filtered or unexported fields
}

Process managed by the ProcessManager.

func NewProcess

func NewProcess() *Process

NewProcess creates a new Process, where the Start function use exec.CommandContext to create and start the process. The Wait function waits for the process to finish and returns the error returned by exec.Cmd.Wait(). Prior to Wait returning, the exec.Cmd.Wait() error is used to set the ProcessState.ExitCode, if error is of type exec.ExitError. The ctx param may be used to kill the process via the ProcessManager.Kill method. The VixMsgStartProgramRequest param fields are mapped to the exec.Cmd counterpart fields. Processes are started within a sub-shell, allowing for i/o redirection, just as with the C version of vmware-tools.

func NewProcessFunc

func NewProcessFunc(run func(ctx context.Context, args string) error) *Process

NewProcessFunc creates a new Process, where the Start function calls the given run function within a goroutine. The Wait function waits for the goroutine to finish and returns the error returned by run. The run ctx param may be used to return early via the ProcessManager.Kill method. The run args command is that of the VixMsgStartProgramRequest.Arguments field.

func NewProcessRoundTrip

func NewProcessRoundTrip() *Process

NewProcessRoundTrip starts a Go function to implement a toolbox backed http.RoundTripper

func (*Process) WithIO

func (p *Process) WithIO() *Process

WithIO enables toolbox Process IO without file system disk IO.

type ProcessError

type ProcessError struct {
	Err      error
	ExitCode int32
}

ProcessError can be returned by the Process.Wait function to propagate ExitCode to ProcessState.

func (*ProcessError) Error

func (e *ProcessError) Error() string

type ProcessFile

type ProcessFile struct {
	io.Reader
	io.Writer
	io.Closer
	// contains filtered or unexported fields
}

ProcessFile implements the os.FileInfo interface to enable toolbox interaction with virtual files.

func (*ProcessFile) IsDir

func (a *ProcessFile) IsDir() bool

IsDir implementation of the os.FileInfo interface method.

func (*ProcessFile) ModTime

func (a *ProcessFile) ModTime() time.Time

ModTime implementation of the os.FileInfo interface method.

func (*ProcessFile) Mode

func (a *ProcessFile) Mode() os.FileMode

Mode implementation of the os.FileInfo interface method.

func (*ProcessFile) Name

func (a *ProcessFile) Name() string

Name implementation of the os.FileInfo interface method.

func (*ProcessFile) Size

func (a *ProcessFile) Size() int64

Size implementation of the os.FileInfo interface method.

func (*ProcessFile) Sys

func (a *ProcessFile) Sys() interface{}

Sys implementation of the os.FileInfo interface method.

type ProcessIO

type ProcessIO struct {
	In struct {
		io.Writer
		io.Reader
		io.Closer // Closer for the write side of the pipe, can be closed via hgfs ops (FileTranfserToGuest)
	}

	Out *bytes.Buffer
	Err *bytes.Buffer
}

ProcessIO encapsulates IO for Go functions and OS commands such that they can interact via the OperationsManager without file system disk IO.

type ProcessManager

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

ProcessManager manages processes within the guest. See: http://pubs.vmware.com/vsphere-60/topic/com.vmware.wssdk.apiref.doc/vim.vm.guest.ProcessManager.html

func NewProcessManager

func NewProcessManager() *ProcessManager

NewProcessManager creates a new ProcessManager instance.

func (*ProcessManager) Kill

func (m *ProcessManager) Kill(pid int64) bool

Kill cancels the Process Context. Returns true if pid exists in the process table, false otherwise.

func (*ProcessManager) ListProcesses

func (m *ProcessManager) ListProcesses(pids []int64) []byte

ListProcesses marshals the ProcessState for the given pids. If no pids are specified, all current processes are included. The return value can be used for responding to a VixMsgListProcessesExRequest.

func (*ProcessManager) Open

func (m *ProcessManager) Open(u *url.URL, mode int32) (hgfs.File, error)

Open implements hgfs.FileHandler.Open

func (*ProcessManager) Start

Start calls the Process.Start function, returning the pid on success or an error. A goroutine is started that calls the Process.Wait function. After Process.Wait has returned, the ProcessState EndTime and ExitCode fields are set. The process state can be queried via ListProcessesInGuest until it is removed, 5 minutes after Wait returns.

func (*ProcessManager) Stat

func (m *ProcessManager) Stat(u *url.URL) (os.FileInfo, error)

Stat implements hgfs.FileHandler.Stat

type ProcessState

type ProcessState struct {
	StartTime int64 // (keep first to ensure 64-bit alignment)
	EndTime   int64 // (keep first to ensure 64-bit alignment)

	Name     string
	Args     string
	Owner    string
	Pid      int64
	ExitCode int32

	IO *ProcessIO
}

ProcessState is the toolbox representation of the GuestProcessInfo type

type Service

type Service struct {
	Command *CommandServer
	Power   *PowerCommandHandler

	PrimaryIP func() string
	// contains filtered or unexported fields
}

Service receives and dispatches incoming RPC requests from the vmx

func NewService

func NewService(rpcIn Channel, rpcOut Channel) *Service

NewService initializes a Service instance

func (*Service) CapabilitiesRegister

func (s *Service) CapabilitiesRegister([]byte) ([]byte, error)

func (*Service) Dispatch

func (s *Service) Dispatch(request []byte) []byte

Dispatch an incoming RPC request to a Handler

func (*Service) Ping

func (s *Service) Ping([]byte) ([]byte, error)

Ping is the default Handler for ping requests

func (*Service) RegisterHandler

func (s *Service) RegisterHandler(name string, handler Handler)

RegisterHandler for the given RPC name

func (*Service) Reset

func (s *Service) Reset([]byte) ([]byte, error)

Reset is the default Handler for reset requests

func (*Service) SendGuestInfo

func (s *Service) SendGuestInfo()

func (*Service) SetOption

func (s *Service) SetOption(args []byte) ([]byte, error)

SetOption is the default Handler for Set_Option requests

func (*Service) Start

func (s *Service) Start() error

Start initializes the RPC channels and starts a goroutine to listen for incoming RPC requests

func (*Service) Stop

func (s *Service) Stop()

Stop cancels the RPC listener routine created via Start

func (*Service) Wait

func (s *Service) Wait()

Wait blocks until Start returns, allowing any current RPC in progress to complete.

type TraceChannel

type TraceChannel struct {
	Channel
	// contains filtered or unexported fields
}

func (*TraceChannel) Receive

func (d *TraceChannel) Receive() ([]byte, error)

func (*TraceChannel) Send

func (d *TraceChannel) Send(buf []byte) error

func (*TraceChannel) Start

func (d *TraceChannel) Start() error

func (*TraceChannel) Stop

func (d *TraceChannel) Stop() error

type TypedIPAddress

type TypedIPAddress struct {
	Type    int32
	Address []byte
}

type WinsConfigInfo

type WinsConfigInfo struct {
	Primary   TypedIPAddress
	Secondary TypedIPAddress
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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