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
- Variables
- type API
- type Client
- type Conditional
- type ConditionalAPI
- type Config
- type ErrWrongType
- type Monitor
- type MonitorCookie
- type MonitorOption
- type Option
- func WithEndpoint(endpoint string) Option
- func WithInactivityCheck(inactivityTimeout, reconnectTimeout time.Duration, ...) Option
- func WithLeaderOnly(leaderOnly bool) Option
- func WithLogger(l *logr.Logger) Option
- func WithMetricsRegistry(r prometheus.Registerer) Option
- func WithMetricsRegistryNamespaceSubsystem(r prometheus.Registerer, namespace, subsystem string) Option
- func WithReconnect(timeout time.Duration, backoff backoff.BackOff) Option
- func WithTLSConfig(cfg *tls.Config) Option
- type TableMonitor
Constants ¶
const ( SSL = "ssl" TCP = "tcp" UNIX = "unix" )
Constants defined for libovsdb
Variables ¶
var ErrAlreadyConnected = errors.New("already connected")
ErrAlreadyConnected is an error returned when the client is already connected
var ErrNotConnected = errors.New("not connected")
ErrNotConnected is an error returned when the client is not connected
var ErrNotFound = errors.New("object not found")
ErrNotFound is used to inform the object or table was not found in the cache
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 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 ¶
MonitorCookie is the struct we pass to correlate from updates back to their originating Monitor request.
type MonitorOption ¶
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 ¶
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 ¶
WithLeaderOnly tells the client to treat endpoints that are clustered and not the leader as down.
func WithLogger ¶
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 ¶
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 ¶
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