client

package
v0.0.0-...-f0bc3ce Latest Latest
Warning

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

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

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 ClientDBModel type) is built to represent the entire OVSDB:

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

The ClientDBModel 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(context.Background(), clientDBModel)

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 use any of fields that correspond to indexes to generate an appropriate condition. 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() or WhereAll() evaluate the provided index values or explicit conditions against the cache and generate conditions based on the UUIDs of matching models. If no matches are found in the cache, the generated conditions will be based on the index or condition fields themselves.

A more flexible mechanism to search the cache 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 schema 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 ErrAlreadyConnected = errors.New("already connected")

ErrAlreadyConnected is an error returned when the client is already connected

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

View Source
var ErrUnsupportedRPC = errors.New("unsupported rpc")

ErrUnsupportedRPC is an error returned when an unsupported RPC method is called

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
	// Models can be structs or pointers to structs
	// 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(ctx context.Context, 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 })
	WherePredict(ctx context.Context, predicate interface{}) (ConditionalAPI, 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, where operations
	// apply to elements that match the values provided in one or more
	// model.Models according to the indexes. All provided Models must be
	// the same type or an error will be generated when operations are
	// are performed on the ConditionalAPI.
	Where(...model.Model) ConditionalAPI

	// WhereAny creates a ConditionalAPI from a list of Conditions where
	// operations apply to elements that match any (eg, logical OR) of the
	// conditions.
	WhereAny(model.Model, ...model.Condition) ConditionalAPI

	// WhereAll creates a ConditionalAPI from a list of Conditions where
	// operations apply to elements that match all (eg, logical AND) of 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(context.Context, 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 other than a
	// UUID, it will be treated as named-uuid
	Create(...model.Model) ([]ovsdb.Operation, error)
}

API defines basic operations to interact with the database

type Client

type Client interface {
	Connect(context.Context) error
	Disconnect()
	Close()
	Schema() ovsdb.DatabaseSchema
	Cache() *cache.TableCache
	UpdateEndpoints([]string)
	SetOption(Option) error
	Connected() bool
	DisconnectNotify() chan struct{}
	Echo(context.Context) error
	Transact(context.Context, ...ovsdb.Operation) ([]ovsdb.OperationResult, error)
	Monitor(context.Context, *Monitor) (MonitorCookie, error)
	MonitorAll(context.Context) (MonitorCookie, error)
	MonitorCancel(ctx context.Context, cookie MonitorCookie) error
	NewMonitor(...MonitorOption) *Monitor
	CurrentEndpoint() string
	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

func NewOVSDBClient(clientDBModel model.ClientDBModel, 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

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)
	// Returns the models that match the conditions
	Matches() (map[string]model.Model, 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(ctx context.Context, 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)

	// Wait returns the operations needed to perform the wait specified
	// by the until condition, timeout, row and columns based on provided parameters.
	Wait(ovsdb.WaitCondition, *int, model.Model, ...interface{}) ([]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

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

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

func (*ErrWrongType) Error

func (e *ErrWrongType) Error() string

type Monitor

type Monitor struct {
	Method            string
	Tables            []TableMonitor
	Errors            []error
	LastTransactionID string
}

Monitor represents a monitor

type MonitorCookie

type MonitorCookie struct {
	DatabaseName string `json:"databaseName"`
	ID           string `json:"id"`
}

MonitorCookie is the struct we pass to correlate from updates back to their originating Monitor request.

type MonitorOption

type MonitorOption func(o *ovsdbClient, m *Monitor) error

MonitorOption adds Tables to a Monitor

func WithConditionalTable

func WithConditionalTable(m model.Model, conditions []model.Condition, fields ...interface{}) MonitorOption

func WithTable

func WithTable(m model.Model, fields ...interface{}) MonitorOption

type Option

type Option func(o *options) error

func WithEndpoint

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 WithInactivityCheck

func WithInactivityCheck(inactivityTimeout, reconnectTimeout time.Duration,
	reconnectBackoff backoff.BackOff) Option

WithInactivityCheck tells the client to send Echo request to ovsdb server periodically upon inactivityTimeout. When Echo request fails, then it attempts to reconnect with server. The inactivity check is performed as long as the connection is established. The reconnectTimeout argument is used to construct the context on each call to Connect, while reconnectBackoff dictates the backoff algorithm to use.

func WithLeaderOnly

func WithLeaderOnly(leaderOnly bool) Option

WithLeaderOnly tells the client to treat endpoints that are clustered and not the leader as down.

func WithLogger

func WithLogger(l *logr.Logger) Option

WithLogger allows setting a specific log sink. Otherwise, the default go log package is used.

func WithMetricsRegistry

func WithMetricsRegistry(r prometheus.Registerer) Option

WithMetricsRegistry allows the user to specify a Prometheus metrics registry. If supplied, the metrics as defined in metrics.go will be registered.

func WithMetricsRegistryNamespaceSubsystem

func WithMetricsRegistryNamespaceSubsystem(r prometheus.Registerer, namespace, subsystem string) Option

WithMetricsRegistryNamespaceSubsystem allows the user to specify a Prometheus metrics registry and Prometheus metric namespace and subsystem of the component utilizing libovsdb. If supplied, the metrics as defined in metrics.go will be registered.

func WithReconnect

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 dictates the backoff algorithm to use. Using WithReconnect implies that requested transactions will block until the client has fully reconnected, rather than immediately returning an error if there is no connection.

func WithTLSConfig

func WithTLSConfig(cfg *tls.Config) Option

WithTLSConfig sets the tls.Config for use by the client

type TableMonitor

type TableMonitor struct {
	// Table is the table to be monitored
	Table string
	// Conditions are the conditions under which the table should be monitored
	Conditions []ovsdb.Condition
	// Fields are the fields in the model to monitor
	// If none are supplied, all fields will be used
	Fields []string
}

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