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 }