client

package
v0.6.0 Latest Latest
Warning

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

Go to latest
Published: Jul 9, 2021 License: Apache-2.0 Imports: 21 Imported by: 33

Documentation

Overview

Package client connects to, monitors and interacts with OVSDB servers (RFC7047).

This package uses structs, that contain the 'ovs' field tag to determine which field goes to which column in the database. We refer to pointers to this structs as Models. Example:

type MyLogicalSwitch struct {
	UUID   string            `ovsdb:"_uuid"` // _uuid tag is mandatory
	Name   string            `ovsdb:"name"`
	Ports  []string          `ovsdb:"ports"`
	Config map[string]string `ovsdb:"other_config"`
}

Based on these Models a Database Model (see DBModel type) is built to represent the entire OVSDB:

dbModel, _ := client.NewDBModel("OVN_Northbound",
    map[string]client.Model{
	"Logical_Switch": &MyLogicalSwitch{},
})

The DBModel represents the entire Database (or the part of it we're interested in). Using it, the libovsdb.client package is able to properly encode and decode OVSDB messages and store them in Model instances. A client instance is created by simply specifying the connection information and the database model:

ovs, _ := client.Connect(contect.Background(), dbModel)

Main API

After creating a OvsdbClient using the Connect() function, we can use a number of CRUD-like to interact with the database: List(), Get(), Create(), Update(), Mutate(), Delete().

The specific database table that the operation targets is automatically determined based on the type of the parameter.

In terms of return values, some of these functions like Create(), Update(), Mutate() and Delete(), interact with the database so they return list of ovsdb.Operation objects that can be grouped together and passed to client.Transact().

Others, such as List() and Get(), interact with the client's internal cache and are able to return Model instances (or a list thereof) directly.

Conditions

Some API functions (Create() and Get()), can be run directly. Others, require us to use a ConditionalAPI. The ConditionalAPI injects RFC7047 Conditions into ovsdb Operations as well as uses the Conditions to search the internal cache.

The ConditionalAPI is created using the Where(), WhereCache() and WhereAll() functions.

Where() accepts a Model (pointer to a struct with ovs tags) and a number of Condition instances. Conditions must refer to fields of the provided Model (via pointer to fields). Example:

ls = &MyLogicalSwitch {}
ovs.Where(ls, client.Condition {
	Field: &ls.Ports,
	Function: ovsdb.ConditionIncludes,
	Value: []string{"portUUID"},
    })

If no client.Condition is provided, the client will create a default Condition based on the Model's data. The first non-null field that corresponds to a database index will be used. Therefore the following two statements are equivalent:

ls = &MyLogicalSwitch {UUID:"myUUID"}

ovs.Where(ls)

ovs.Where(ls, client.Condition {
	Field: &ls.UUID,
	Function: ovsdb.ConditionEqual,
	Value: "myUUID"},
    })

Where() accepts multiple Condition instances (through variadic arguments). If provided, the client will generate multiple operations each matching one condition. For example, the following operation will delete all the Logical Switches named "foo" OR "bar":

ops, err := ovs.Where(ls,
	client.Condition {
		Field: &ls.Name
		Function: ovsdb.ConditionEqual,
		Value: "foo",
	},client.Condition {
		Field: &ls.Port,
		Function: ovsdb.ConditionIncludes,
		Value: "bar",
}).Delete()

To create a Condition that matches all of the conditions simultaneously (i.e: AND semantics), use WhereAll().

Where() and WhereAll() inject conditions into operations that will be evaluated by the server. However, to perform searches on the local cache, a more flexible mechanism is available: WhereCache()

WhereCache() accepts a function that takes any Model as argument and returns a boolean. It is used to search the cache so commonly used with List() function. For example:

lsList := &[]LogicalSwitch{}
err := ovs.WhereCache(
    func(ls *LogicalSwitch) bool {
    	return strings.HasPrefix(ls.Name, "ext_")
}).List(lsList)

Server side operations can be executed using WhereCache() conditions but it's not recommended. For each matching cache element, an operation will be created matching on the "_uuid" column. The number of operations can be quite large depending on the cache size and the provided function. Most likely there is a way to express the same condition using Where() or WhereAll() which will be more efficient.

Get

Get() operation is a simple operation capable of retrieving one Model based on some of its indexes. E.g:

ls := &LogicalSwitch{UUID:"myUUID"}
err := ovs.Get(ls)
fmt.Printf("Name of the switch is: &s", ls.Name)

List

List() searches the cache and populates a slice of Models. It can be used directly or using WhereCache()

lsList := &[]LogicalSwitch{}
err := ovs.List(lsList) // List all elements

err := ovs.WhereCache(
    func(ls *LogicalSwitch) bool {
    	return strings.HasPrefix(ls.Name, "ext_")
}).List(lsList)

Create

Create returns a list of operations to create the models provided. E.g:

ops, err := ovs.Create(&LogicalSwitch{Name:"foo")}, &LogicalSwitch{Name:"bar"})

Update Update returns a list of operations to update the matching rows to match the values of the provided model. E.g:

ls := &LogicalSwitch{ExternalIDs: map[string]string {"foo": "bar"}}
ops, err := ovs.Where(...).Update(&ls, &ls.ExternalIDs}

Mutate

Mutate returns a list of operations needed to mutate the matching rows as described by the list of Mutation objects. E.g:

ls := &LogicalSwitch{}
ops, err := ovs.Where(...).Mutate(&ls, client.Mutation {
	Field:   &ls.Config,
	Mutator: ovsdb.MutateOperationInsert,
	Value:   map[string]string{"foo":"bar"},
})

Delete

Delete returns a list of operations needed to delete the matching rows. E.g:

ops, err := ovs.Where(...).Delete()

Index

Constants

View Source
const (
	SSL  = "ssl"
	TCP  = "tcp"
	UNIX = "unix"
)

Constants defined for libovsdb

Variables

View Source
var ErrNotConnected = errors.New("not connected")

ErrNotConnected is an error returned when the client is not connected

View Source
var ErrNotFound = errors.New("object not found")

ErrNotFound is used to inform the object or table was not found in the cache

Functions

This section is empty.

Types

type API

type API interface {
	// List populates a slice of Models objects based on their type
	// The function parameter must be a pointer to a slice of Models
	// If the slice is null, the entire cache will be copied into the slice
	// If it has a capacity != 0, only 'capacity' elements will be filled in
	List(result interface{}) error

	// Create a Conditional API from a Function that is used to filter cached data
	// The function must accept a Model implementation and return a boolean. E.g:
	// ConditionFromFunc(func(l *LogicalSwitch) bool { return l.Enabled })
	WhereCache(predicate interface{}) ConditionalAPI

	// Create a ConditionalAPI from a Model's index data or a list of Conditions
	// where operations apply to elements that match any of the conditions
	// If no condition is given, it will match the values provided in model.Model according
	// to the database index.
	Where(model.Model, ...model.Condition) ConditionalAPI

	// Create a ConditionalAPI from a Model's index data or a list of Conditions
	// where operations apply to elements that match all the conditions
	WhereAll(model.Model, ...model.Condition) ConditionalAPI

	// Get retrieves a model from the cache
	// The way the object will be fetch depends on the data contained in the
	// provided model and the indexes defined in the associated schema
	// For more complex ways of searching for elements in the cache, the
	// preferred way is Where({condition}).List()
	Get(model.Model) error

	// Create returns the operation needed to add the model(s) to the Database
	// Only fields with non-default values will be added to the transaction
	// If the field associated with column "_uuid" has some content, it will be
	// treated as named-uuid
	Create(...model.Model) ([]ovsdb.Operation, error)
}

API defines basic operations to interact with the database

type Client added in v0.6.0

type Client interface {
	Connect(context.Context) error
	Disconnect()
	Close()
	Schema() *ovsdb.DatabaseSchema
	Cache() *cache.TableCache
	SetOption(Option) error
	Connected() bool
	DisconnectNotify() chan struct{}
	Echo() error
	Transact(...ovsdb.Operation) ([]ovsdb.OperationResult, error)
	Monitor(...TableMonitor) (string, error)
	MonitorAll() (string, error)
	MonitorCancel(id string) error
	NewTableMonitor(m model.Model, fields ...interface{}) TableMonitor
	API
}

Client represents an OVSDB Client Connection It provides all the necessary functionality to Connect to a server, perform transactions, and build your own replica of the database with Monitor or MonitorAll. It also provides a Cache that is populated from OVSDB update notifications.

func NewOVSDBClient added in v0.6.0

func NewOVSDBClient(databaseModel *model.DBModel, opts ...Option) (Client, error)

NewOVSDBClient creates a new OVSDB Client with the provided database model. The client can be configured using one or more Option(s), like WithTLSConfig. If no WithEndpoint option is supplied, the default of unix:/var/run/openvswitch/ovsdb.sock is used

type Conditional added in v0.4.0

type Conditional interface {
	// Generate returns a list of lists of conditions to be used in Operations
	// Each element in the (outer) list corresponds to an operation
	Generate() ([][]ovsdb.Condition, error)
	// matches returns true if a model matches the condition
	Matches(m model.Model) (bool, error)
	// returns the table that this condition is associated with
	Table() string
}

Conditional is the interface used by the ConditionalAPI to match on cache objects and generate ovsdb conditions

type ConditionalAPI

type ConditionalAPI interface {
	// List uses the condition to search on the cache and populates
	// the slice of Models objects based on their type
	List(result interface{}) error

	// Mutate returns the operations needed to perform the mutation specified
	// By the model and the list of Mutation objects
	// Depending on the Condition, it might return one or many operations
	Mutate(model.Model, ...model.Mutation) ([]ovsdb.Operation, error)

	// Update returns the operations needed to update any number of rows according
	// to the data in the given model.
	// By default, all the non-default values contained in model will be updated.
	// Optional fields can be passed (pointer to fields in the model) to select the
	// the fields to be updated
	Update(model.Model, ...interface{}) ([]ovsdb.Operation, error)

	// Delete returns the Operations needed to delete the models selected via the condition
	Delete() ([]ovsdb.Operation, error)
}

ConditionalAPI is an interface used to perform operations that require / use Conditions

type Config

type Config struct {
	Addr      string
	TLSConfig *tls.Config
}

Config is a structure used in provisioning a connection to ovsdb.

type ErrWrongType added in v0.4.0

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

ErrWrongType is used to report the user provided parameter has the wrong type

func (*ErrWrongType) Error added in v0.4.0

func (e *ErrWrongType) Error() string

type Option added in v0.4.0

type Option func(o *options) error

func WithEndpoint added in v0.4.0

func WithEndpoint(endpoint string) Option

WithEndpoint sets the endpoint to be used by the client It can be used multiple times, and the first endpoint that successfully connects will be used. Endpoints are specified in OVSDB Connection Format For more details, see the ovsdb(7) man page

func WithReconnect added in v0.6.0

func WithReconnect(timeout time.Duration, backoff backoff.BackOff) Option

WithReconnect tells the client to automatically reconnect when disconnected. The timeout is used to construct the context on each call to Connect, while backoff dicates the backoff algorithm to use

func WithTLSConfig added in v0.4.0

func WithTLSConfig(cfg *tls.Config) Option

WithTLSConfig sets the tls.Config for use by the client

type TableMonitor added in v0.6.0

type TableMonitor struct {
	// Table is the table to be monitored
	Table string
	// Fields are the fields in the model to monitor
	// If none are supplied, all fields will be used
	Fields []interface{}
	// Error will contain any errors caught in the creation of a TableMonitor
	Error error
}

TableMonitor is a table to be monitored

Jump to

Keyboard shortcuts

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