Documentation ¶
Index ¶
- Constants
- Variables
- func GetBackendNames() []string
- func NbdError(err error) uint32
- func RegisterBackend(name string, ...)
- func Run(control *Control)
- func RunConfig(control *Control)
- func StartServer(parentCtx context.Context, sessionParentCtx context.Context, ...)
- type AioFileBackend
- func (afb *AioFileBackend) Close(ctx context.Context) error
- func (afb *AioFileBackend) Flush(ctx context.Context) error
- func (afb *AioFileBackend) Geometry(ctx context.Context) (uint64, uint64, uint64, uint64, error)
- func (afb *AioFileBackend) HasFlush(ctx context.Context) bool
- func (afb *AioFileBackend) HasFua(ctx context.Context) bool
- func (afb *AioFileBackend) ReadAt(ctx context.Context, b []byte, offset int64) (int, error)
- func (afb *AioFileBackend) TrimAt(ctx context.Context, length int, offset int64) (int, error)
- func (afb *AioFileBackend) WriteAt(ctx context.Context, b []byte, offset int64, fua bool) (int, error)
- type Backend
- type Config
- type Connection
- func (c *Connection) Dispatch(ctx context.Context, n int)
- func (c *Connection) FreeMemory(ctx context.Context, mem [][]byte)
- func (c *Connection) GetMemory(ctx context.Context, length uint64) [][]byte
- func (c *Connection) Kill(ctx context.Context)
- func (c *Connection) Negotiate(ctx context.Context) error
- func (c *Connection) Receive(ctx context.Context)
- func (c *Connection) ReturnMemory(ctx context.Context)
- func (c *Connection) Serve(parentCtx context.Context)
- func (c *Connection) Transmit(ctx context.Context)
- func (c *Connection) ZeroMemory(ctx context.Context, mem [][]byte)
- type ConnectionParameters
- type Control
- type DeadlineListener
- type DriverParametersConfig
- type Export
- type ExportConfig
- type FileBackend
- func (fb *FileBackend) Close(ctx context.Context) error
- func (fb *FileBackend) Flush(ctx context.Context) error
- func (fb *FileBackend) Geometry(ctx context.Context) (uint64, uint64, uint64, uint64, error)
- func (fb *FileBackend) HasFlush(ctx context.Context) bool
- func (fb *FileBackend) HasFua(ctx context.Context) bool
- func (fb *FileBackend) ReadAt(ctx context.Context, b []byte, offset int64) (int, error)
- func (fb *FileBackend) TrimAt(ctx context.Context, length int, offset int64) (int, error)
- func (fb *FileBackend) WriteAt(ctx context.Context, b []byte, offset int64, fua bool) (int, error)
- type Listener
- type LogConfig
- type RbdBackend
- func (rb *RbdBackend) Close(ctx context.Context) error
- func (rb *RbdBackend) Flush(ctx context.Context) error
- func (rb *RbdBackend) Geometry(ctx context.Context) (uint64, uint64, uint64, uint64, error)
- func (rb *RbdBackend) HasFlush(ctx context.Context) bool
- func (rb *RbdBackend) HasFua(ctx context.Context) bool
- func (rb *RbdBackend) ReadAt(ctx context.Context, b []byte, offset int64) (int, error)
- func (rb *RbdBackend) TrimAt(ctx context.Context, length int, offset int64) (int, error)
- func (rb *RbdBackend) WriteAt(ctx context.Context, b []byte, offset int64, fua bool) (int, error)
- type Request
- type ServerConfig
- type SyslogWriter
- type TlsConfig
Constants ¶
const ( ENV_CONFFILE = "_GONBDSERVER_CONFFILE" ENV_PIDFILE = "_GONBDSERVER_PIDFILE" )
const ( NBD_CMD_READ = 0 NBD_CMD_WRITE = 1 NBD_CMD_DISC = 2 NBD_CMD_FLUSH = 3 NBD_CMD_TRIM = 4 NBD_CMD_WRITE_ZEROES = 5 NBD_CMD_CLOSE = 7 )
NBD commands
const ( NBD_CMD_FLAG_FUA = uint16(1 << 0) NBD_CMD_MAY_TRIM = uint16(1 << 1) NBD_CMD_FLAG_DF = uint16(1 << 2) )
NBD command flags
const ( NBD_FLAG_HAS_FLAGS = uint16(1 << 0) NBD_FLAG_READ_ONLY = uint16(1 << 1) NBD_FLAG_SEND_FLUSH = uint16(1 << 2) NBD_FLAG_SEND_FUA = uint16(1 << 3) NBD_FLAG_ROTATIONAL = uint16(1 << 4) NBD_FLAG_SEND_TRIM = uint16(1 << 5) NBD_FLAG_SEND_WRITE_ZEROES = uint16(1 << 6) NBD_FLAG_SEND_DF = uint16(1 << 7) NBD_FLAG_SEND_CLOSE = uint16(1 << 8) )
NBD negotiation flags
const ( NBD_MAGIC = 0x4e42444d41474943 NBD_REQUEST_MAGIC = 0x25609513 NBD_REPLY_MAGIC = 0x67446698 NBD_CLISERV_MAGIC = 0x00420281861253 NBD_OPTS_MAGIC = 0x49484156454F5054 NBD_REP_MAGIC = 0x3e889045565a9 NBD_STRUCTURED_REPLY_MAGIC = 0x668e33ef )
NBD magic numbers
const ( NBD_OPT_EXPORT_NAME = 1 NBD_OPT_ABORT = 2 NBD_OPT_LIST = 3 NBD_OPT_PEEK_EXPORT = 4 NBD_OPT_STARTTLS = 5 NBD_OPT_INFO = 6 NBD_OPT_GO = 7 NBD_OPT_STRUCTURED_REPLY = 8 )
NBD options
const ( NBD_REP_ACK = uint32(1) NBD_REP_SERVER = uint32(2) NBD_REP_INFO = uint32(3) NBD_REP_FLAG_ERROR = uint32(1 << 31) NBD_REP_ERR_UNSUP = uint32(1 | NBD_REP_FLAG_ERROR) NBD_REP_ERR_POLICY = uint32(2 | NBD_REP_FLAG_ERROR) NBD_REP_ERR_INVALID = uint32(3 | NBD_REP_FLAG_ERROR) NBD_REP_ERR_PLATFORM = uint32(4 | NBD_REP_FLAG_ERROR) NBD_REP_ERR_TLS_REQD = uint32(5 | NBD_REP_FLAG_ERROR) NBD_REP_ERR_UNKNOWN = uint32(6 | NBD_REP_FLAG_ERROR) NBD_REP_ERR_SHUTDOWN = uint32(7 | NBD_REP_FLAG_ERROR) NBD_REP_ERR_BLOCK_SIZE_REQD = uint32(8 | NBD_REP_FLAG_ERROR) )
NBD option reply types
const ( NBD_REPLY_TYPE_NONE = 0 NBD_REPLY_TYPE_ERROR = 1 NBD_REPLY_TYPE_ERROR_OFFSET = 2 NBD_REPLY_TYPE_OFFSET_DATA = 3 NBD_REPLY_TYPE_OFFSET_HOLE = 4 )
NBD reply types
const ( NBD_FLAG_FIXED_NEWSTYLE = 1 << 0 NBD_FLAG_NO_ZEROES = 1 << 1 )
NBD hanshake flags
const ( NBD_FLAG_C_FIXED_NEWSTYLE = 1 << 0 NBD_FLAG_C_NO_ZEROES = 1 << 1 )
NBD client flags
const ( NBD_EPERM = 1 NBD_EIO = 5 NBD_ENOMEM = 12 NBD_EINVAL = 22 NBD_ENOSPC = 28 NBD_EOVERFLOW = 75 )
NBD errors
const ( NBD_INFO_EXPORT = 0 NBD_INFO_NAME = 1 NBD_INFO_DESCRIPTION = 2 NBD_INFO_BLOCK_SIZE = 3 )
NBD info types
const ( CMDT_CHECK_LENGTH_OFFSET = 1 << iota // length and offset must be valid CMDT_REQ_PAYLOAD // request carries a payload CMDT_REQ_FAKE_PAYLOAD // request does not carry a payload, but we'll make a zero payload up CMDT_REP_PAYLOAD // reply carries a payload CMDT_CHECK_NOT_READ_ONLY // not valid on read-only media CMDT_SET_DISCONNECT_RECEIVED // a disconnect - don't process any further commands )
Our internal flags to characterize commands
const (
NBD_DEFAULT_PORT = 10809
)
NBD default port
const (
NBD_REPLY_FLAG_DONE = 1 << 0
)
NBD reply flags
Variables ¶
var BackendMap map[string]func(ctx context.Context, e *ExportConfig) (Backend, error) = make(map[string]func(ctx context.Context, e *ExportConfig) (Backend, error))
BackendMap is a map between backends and the generator function for them
var CmdTypeMap = map[int]uint64{ NBD_CMD_READ: CMDT_CHECK_LENGTH_OFFSET | CMDT_REP_PAYLOAD, NBD_CMD_WRITE: CMDT_CHECK_LENGTH_OFFSET | CMDT_CHECK_NOT_READ_ONLY | CMDT_REQ_PAYLOAD, NBD_CMD_DISC: CMDT_SET_DISCONNECT_RECEIVED, NBD_CMD_FLUSH: CMDT_CHECK_NOT_READ_ONLY, NBD_CMD_TRIM: CMDT_CHECK_LENGTH_OFFSET | CMDT_CHECK_NOT_READ_ONLY, NBD_CMD_WRITE_ZEROES: CMDT_CHECK_LENGTH_OFFSET | CMDT_CHECK_NOT_READ_ONLY | CMDT_REQ_FAKE_PAYLOAD, NBD_CMD_CLOSE: CMDT_SET_DISCONNECT_RECEIVED, }
A map specifying each command
var DefaultWorkers = 5
Default number of workers
Functions ¶
func GetBackendNames ¶
func GetBackendNames() []string
func NbdError ¶
NbdError translates an error returned by golang into an NBD error
This function could do with some serious work!
func RegisterBackend ¶
func RunConfig ¶
func RunConfig(control *Control)
RunConfig - this is effectively the main entry point of the program
We parse the config, then start each of the listeners, restarting them when we get SIGHUP, but being sure not to kill the sessions
func StartServer ¶
func StartServer(parentCtx context.Context, sessionParentCtx context.Context, sessionWaitGroup *sync.WaitGroup, logger *log.Logger, s ServerConfig)
Startserver starts a single server.
A parent context is given in which the listener runs, as well as a session context in which the sessions (connections) themselves run. This enables the sessions to be retained when the listener is cancelled on a SIGHUP
Types ¶
type AioFileBackend ¶
type AioFileBackend struct {
// contains filtered or unexported fields
}
AioFileBackend implements Backend
func (*AioFileBackend) Close ¶
func (afb *AioFileBackend) Close(ctx context.Context) error
Close implements Backend.Close
func (*AioFileBackend) Flush ¶
func (afb *AioFileBackend) Flush(ctx context.Context) error
Flush implements Backend.Flush
func (*AioFileBackend) HasFlush ¶
func (afb *AioFileBackend) HasFlush(ctx context.Context) bool
Size implements Backend.HasFua
func (*AioFileBackend) HasFua ¶
func (afb *AioFileBackend) HasFua(ctx context.Context) bool
Size implements Backend.HasFua
type Backend ¶
type Backend interface { WriteAt(ctx context.Context, b []byte, offset int64, fua bool) (int, error) // write data b at offset, with force unit access optional ReadAt(ctx context.Context, b []byte, offset int64) (int, error) // read to b at offset TrimAt(ctx context.Context, length int, offset int64) (int, error) // trim Flush(ctx context.Context) error // flush Close(ctx context.Context) error // close Geometry(ctx context.Context) (uint64, uint64, uint64, uint64, error) // size, minimum BS, preferred BS, maximum BS HasFua(ctx context.Context) bool // does the driver support FUA? HasFlush(ctx context.Context) bool // does the driver support flush? }
Backend is an interface implemented by the various backend drivers
func NewAioFileBackend ¶
func NewAioFileBackend(ctx context.Context, ec *ExportConfig) (Backend, error)
Generate a new aio backend
func NewFileBackend ¶
func NewFileBackend(ctx context.Context, ec *ExportConfig) (Backend, error)
Generate a new file backend
func NewRbdBackend ¶
func NewRbdBackend(ctx context.Context, ec *ExportConfig) (Backend, error)
Generate a new file backend
type Config ¶
type Config struct { Servers []ServerConfig // array of server configs Logging LogConfig // Configuration for logging }
Config holds the config that applies to all servers (currently just logging), and an array of server configs
func ParseConfig ¶
ParseConfig parses the YAML configuration provided
type Connection ¶
type Connection struct {
// contains filtered or unexported fields
}
Connection holds the details for each connection
func (*Connection) Dispatch ¶
func (c *Connection) Dispatch(ctx context.Context, n int)
Dispatch is the goroutine used to process received items, passing the reply to the transmit goroutine
one of these is run for each worker
func (*Connection) FreeMemory ¶
func (c *Connection) FreeMemory(ctx context.Context, mem [][]byte)
Get memory for a particular length
func (*Connection) GetMemory ¶
func (c *Connection) GetMemory(ctx context.Context, length uint64) [][]byte
Get memory for a particular length
func (*Connection) Kill ¶
func (c *Connection) Kill(ctx context.Context)
Kill kills a connection. This safely ensures the kill channel is closed if it isn't already, which will kill all the goroutines
func (*Connection) Negotiate ¶
func (c *Connection) Negotiate(ctx context.Context) error
Negotiate negotiates a connection
func (*Connection) Receive ¶
func (c *Connection) Receive(ctx context.Context)
Receive is the goroutine that handles decoding conncetion data from the socket
func (*Connection) ReturnMemory ¶
func (c *Connection) ReturnMemory(ctx context.Context)
periodically return all memory under the low water mark back to the OS
func (*Connection) Serve ¶
func (c *Connection) Serve(parentCtx context.Context)
Serve negotiates, then starts all the goroutines for processing a connection, then waits for them to be ended
func (*Connection) Transmit ¶
func (c *Connection) Transmit(ctx context.Context)
Transmit is the goroutine run to transmit the processed requests (now replies)
func (*Connection) ZeroMemory ¶
func (c *Connection) ZeroMemory(ctx context.Context, mem [][]byte)
Zero memory
type ConnectionParameters ¶
type ConnectionParameters struct {
ConnectionTimeout time.Duration // maximum time to complete negotiation
}
ConnectionParameters holds parameters for each inbound connection
type DeadlineListener ¶
An listener type that does what we want
type DriverParametersConfig ¶
DriverConfig is an arbitrary map of other parameters in string format
type ExportConfig ¶
type ExportConfig struct { Name string // name of the export Description string // description of export Driver string // name of the driver ReadOnly bool // true of the export should be opened readonly Workers int // number of concurrent workers TlsOnly bool // true if the export should only be served over TLS MinimumBlockSize uint64 // minimum block size PreferredBlockSize uint64 // preferred block size MaximumBlockSize uint64 // maximum block size DriverParameters DriverParametersConfig `yaml:",inline"` // driver parameters. These are an arbitrary map. Inline means they go aside teh foregoing }
ExportConfig holds the config for one exported item
type FileBackend ¶
type FileBackend struct {
// contains filtered or unexported fields
}
FileBackend implements Backend
func (*FileBackend) Close ¶
func (fb *FileBackend) Close(ctx context.Context) error
Close implements Backend.Close
func (*FileBackend) Flush ¶
func (fb *FileBackend) Flush(ctx context.Context) error
Flush implements Backend.Flush
func (*FileBackend) HasFlush ¶
func (fb *FileBackend) HasFlush(ctx context.Context) bool
Size implements Backend.HasFua
func (*FileBackend) HasFua ¶
func (fb *FileBackend) HasFua(ctx context.Context) bool
Size implements Backend.HasFua
type Listener ¶
type Listener struct {
// contains filtered or unexported fields
}
A single listener on a given net.Conn address
func NewListener ¶
func NewListener(logger *log.Logger, s ServerConfig) (*Listener, error)
NewListener returns a new listener object
func (*Listener) Listen ¶
func (l *Listener) Listen(parentCtx context.Context, sessionParentCtx context.Context, sessionWaitGroup *sync.WaitGroup)
Listen listens on an given address for incoming connections
When sessions come in they are started on a separate context (sessionParentCtx), so that the listener can be killed without killing the sessions
type LogConfig ¶
type LogConfig struct { File string // a file to log to FileMode string // file mode SyslogFacility string // a syslog facility name - set to enable syslog Date bool // log the date - i.e. log.Ldate Time bool // log the time - i.e. log.Ltime Microseconds bool // log microseconds - i.e. log.Lmicroseconds UTC bool // log time in URC - i.e. LUTC SourceFile bool // log source file - i.e. Lshortfile }
LogConfig specifies configuration for logging
type RbdBackend ¶
type RbdBackend struct {
// contains filtered or unexported fields
}
RbdBackend implements Backend
func (*RbdBackend) Close ¶
func (rb *RbdBackend) Close(ctx context.Context) error
Close implements Backend.Close
func (*RbdBackend) Flush ¶
func (rb *RbdBackend) Flush(ctx context.Context) error
Flush implements Backend.Flush
func (*RbdBackend) HasFlush ¶
func (rb *RbdBackend) HasFlush(ctx context.Context) bool
Size implements Backend.HasFua
func (*RbdBackend) HasFua ¶
func (rb *RbdBackend) HasFua(ctx context.Context) bool
Size implements Backend.HasFua
type Request ¶
type Request struct {
// contains filtered or unexported fields
}
Request is an internal structure for propagating requests through the channels
type ServerConfig ¶
type ServerConfig struct { Protocol string // protocol it should listen on (in net.Conn form) Address string // address to listen on DefaultExport string // name of default export Exports []ExportConfig // array of configurations of exported items Tls TlsConfig // TLS configuration DisableNoZeroes bool // Disable NoZereos extension }
ServerConfig holds the config that applies to each server (i.e. listener)
type SyslogWriter ¶
type SyslogWriter struct {
// contains filtered or unexported fields
}
SyslogWriter is a WriterCloser that logs to syslog with an extracted priority
func NewSyslogWriter ¶
func NewSyslogWriter(facility string) (*SyslogWriter, error)
Create a new syslog writer
type TlsConfig ¶
type TlsConfig struct { KeyFile string // path to TLS key file CertFile string // path to TLS cert file ServerName string // server name CaCertFile string // path to certificate file ClientAuth string // client authentication strategy MinVersion string // minimum TLS version MaxVersion string // maximum TLS version }
TlsConfig has the configuration for TLS