go.ligato.io/vpp-agent/v3@v3.5.0/examples/kvscheduler/mock_plugins/l2plugin/descriptor/bd_interface.go (about)

     1  // Copyright (c) 2018 Cisco and/or its affiliates.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at:
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package descriptor
    16  
    17  import (
    18  	"github.com/pkg/errors"
    19  	"go.ligato.io/cn-infra/v2/logging"
    20  	"google.golang.org/protobuf/proto"
    21  
    22  	interfaces "go.ligato.io/vpp-agent/v3/examples/kvscheduler/mock_plugins/ifplugin/model"
    23  	"go.ligato.io/vpp-agent/v3/examples/kvscheduler/mock_plugins/l2plugin/descriptor/adapter"
    24  	"go.ligato.io/vpp-agent/v3/examples/kvscheduler/mock_plugins/l2plugin/mockcalls"
    25  	l2 "go.ligato.io/vpp-agent/v3/examples/kvscheduler/mock_plugins/l2plugin/model"
    26  	"go.ligato.io/vpp-agent/v3/pkg/idxvpp"
    27  	kvs "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api"
    28  )
    29  
    30  const (
    31  	// BDInterfaceDescriptorName is the name of the descriptor for bindings
    32  	// between mock bridge domains and mock interfaces.
    33  	BDInterfaceDescriptorName = "mock-bd-interface"
    34  
    35  	// dependency labels
    36  	interfaceDep = "interface-exists"
    37  )
    38  
    39  // BDInterfaceDescriptor teaches KVScheduler how to put interface into bridge
    40  // domain in the mock SB.
    41  // A binding between bridge domain and an interface is a value derived from the
    42  // bridge domain. This descriptor is therefore only for derived values.
    43  type BDInterfaceDescriptor struct {
    44  	// dependencies
    45  	log       logging.Logger
    46  	bdIndex   idxvpp.NameToIndex
    47  	bdHandler mockcalls.MockBDAPI
    48  }
    49  
    50  // NewBDInterfaceDescriptor creates a new instance of the BDInterface descriptor.
    51  func NewBDInterfaceDescriptor(bdIndex idxvpp.NameToIndex, bdHandler mockcalls.MockBDAPI, log logging.PluginLogger) *kvs.KVDescriptor {
    52  	// descriptors are supposed to be stateless and this principle is not broken
    53  	// here - we only need to keep context consisting of references to logger,
    54  	// index with BD metadata and the BD handler, to be used inside the CRUD
    55  	// methods
    56  	descrCtx := &BDInterfaceDescriptor{
    57  		bdIndex:   bdIndex,
    58  		bdHandler: bdHandler,
    59  		log:       log.NewLogger("mock-bd-iface-descriptor"),
    60  	}
    61  
    62  	// use adapter to convert typed descriptor into generic descriptor API
    63  	typedDescr := &adapter.BDInterfaceDescriptor{
    64  		Name:          BDInterfaceDescriptorName,
    65  		KeySelector:   descrCtx.IsBDInterfaceKey,
    66  		ValueTypeName: string(proto.MessageName(&l2.BridgeDomain_Interface{})),
    67  		Create:        descrCtx.Create,
    68  		Delete:        descrCtx.Delete,
    69  		Dependencies:  descrCtx.Dependencies,
    70  
    71  		// Note: this descriptor is only for derived values, therefore it doesn't
    72  		//       need to define the Retrieve method - the values under its scope
    73  		//       are derived from bridge domains, which are already Retrieved by
    74  		//       BridgeDomainDescriptor.
    75  	}
    76  	return adapter.NewBDInterfaceDescriptor(typedDescr)
    77  }
    78  
    79  // IsBDInterfaceKey returns true if the key is identifying binding between
    80  // bridge domain and interface in the mock SB.
    81  func (d *BDInterfaceDescriptor) IsBDInterfaceKey(key string) bool {
    82  	_, _, isBDIfaceKey := l2.ParseBDInterfaceKey(key)
    83  	return isBDIfaceKey
    84  }
    85  
    86  // Create puts interface into bridge domain.
    87  func (d *BDInterfaceDescriptor) Create(key string, bdIface *l2.BridgeDomain_Interface) (metadata interface{}, err error) {
    88  	// get bridge domain index
    89  	bdName, _, _ := l2.ParseBDInterfaceKey(key)
    90  	bdMeta, found := d.bdIndex.LookupByName(bdName)
    91  	if !found {
    92  		err = errors.Errorf("failed to obtain metadata for bridge domain %s", bdName)
    93  		d.log.Error(err)
    94  		return nil, err
    95  	}
    96  
    97  	// put interface into the bridge domain
    98  	err = d.bdHandler.AddInterfaceToBridgeDomain(bdMeta.GetIndex(), bdIface.Name, bdIface.BridgedVirtualInterface)
    99  	if err != nil {
   100  		d.log.Error(err)
   101  		return nil, err
   102  
   103  	}
   104  	return nil, nil
   105  }
   106  
   107  // Delete removes interface from bridge domain.
   108  func (d *BDInterfaceDescriptor) Delete(key string, bdIface *l2.BridgeDomain_Interface, metadata interface{}) error {
   109  	// get bridge domain index
   110  	bdName, _, _ := l2.ParseBDInterfaceKey(key)
   111  	bdMeta, found := d.bdIndex.LookupByName(bdName)
   112  	if !found {
   113  		err := errors.Errorf("failed to obtain metadata for bridge domain %s", bdName)
   114  		d.log.Error(err)
   115  		return err
   116  	}
   117  
   118  	err := d.bdHandler.DeleteInterfaceFromBridgeDomain(bdMeta.GetIndex(), bdIface.Name)
   119  	if err != nil {
   120  		d.log.Error(err)
   121  		return err
   122  
   123  	}
   124  	return nil
   125  }
   126  
   127  // Dependencies lists the interface as the only dependency for the binding.
   128  //
   129  // Note: some bindings derived from a given bridge domain may be pending (waiting
   130  // for their interfaces), but others and the bridge domain itself will be unaffected
   131  // and free to get configured. This is the power of derived values, which allows
   132  // you to break complex items into multiple parts handled separately.
   133  func (d *BDInterfaceDescriptor) Dependencies(key string, value *l2.BridgeDomain_Interface) []kvs.Dependency {
   134  	return []kvs.Dependency{
   135  		{
   136  			Label: interfaceDep,
   137  			Key:   interfaces.InterfaceKey(value.Name),
   138  		},
   139  	}
   140  }