2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
\r
4 * This program and the accompanying materials are made available under the
\r
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
\r
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
\r
9 package org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.processors;
\r
11 import java.util.Collections;
\r
12 import java.util.List;
\r
14 import javax.annotation.Nullable;
\r
16 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
\r
17 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
\r
18 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
\r
19 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
\r
20 import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
\r
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
\r
22 import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
\r
23 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
\r
24 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
\r
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
\r
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
\r
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
\r
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
\r
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.UniqueId;
\r
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.Mappings;
\r
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.GbpByNeutronMappings;
\r
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.BaseEndpointsByPorts;
\r
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.base.endpoints.by.ports.BaseEndpointByPort;
\r
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.base.endpoints.by.ports.BaseEndpointByPortKey;
\r
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.Config;
\r
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.ExcludeFromPolicy;
\r
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.ExcludeFromPolicyBuilder;
\r
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.LoopbackCase;
\r
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.LoopbackCaseBuilder;
\r
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.TapCase;
\r
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.TapCaseBuilder;
\r
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.VhostUserCaseBuilder;
\r
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpoint;
\r
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointBuilder;
\r
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointKey;
\r
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.binding.rev150712.PortBindingExtension;
\r
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.binding.rev150712.binding.attributes.VifDetails;
\r
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.Routers;
\r
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
\r
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.RouterKey;
\r
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
\r
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
\r
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
\r
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.PortKey;
\r
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
\r
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
\r
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
\r
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetKey;
\r
59 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
\r
60 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
\r
61 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
\r
62 import org.slf4j.Logger;
\r
63 import org.slf4j.LoggerFactory;
\r
65 import com.google.common.annotations.VisibleForTesting;
\r
66 import com.google.common.base.Optional;
\r
67 import com.google.common.base.Strings;
\r
69 import javax.annotation.Nonnull;
\r
70 public class PortHandler implements TransactionChainListener {
\r
72 private static final Logger LOG = LoggerFactory.getLogger(PortHandler.class);
\r
74 private static final String COMPUTE_OWNER = "compute";
\r
75 private static final String DHCP_OWNER = "dhcp";
\r
76 static final String ROUTER_OWNER = "network:router_interface";
\r
77 private static final String[] SUPPORTED_DEVICE_OWNERS = {COMPUTE_OWNER, DHCP_OWNER, ROUTER_OWNER};
\r
78 private static final String VHOST_USER = "vhostuser";
\r
79 private static final String UNBOUND = "unbound";
\r
80 private static final String VPP_INTERFACE_NAME_PREFIX = "neutron_port_";
\r
81 private static final String TAP_PORT_NAME_PREFIX = "tap";
\r
82 private static final String RT_PORT_NAME_PREFIX = "qr-";
\r
83 private static final String VHOST_SOCKET_KEY = "vhostuser_socket";
\r
84 static final String DEFAULT_NODE = "default";
\r
86 private final NodeId routingNode;
\r
87 private BindingTransactionChain transactionChain;
\r
88 private DataBroker dataBroker;
\r
90 PortHandler(DataBroker dataBroker, NodeId routingNodeId) {
\r
91 this.dataBroker = dataBroker;
\r
92 this.routingNode = routingNodeId;
\r
93 transactionChain = this.dataBroker.createTransactionChain(this);
\r
96 void processCreated(Port port) {
\r
97 ReadOnlyTransaction rTx = transactionChain.newReadOnlyTransaction();
\r
98 Optional<BaseEndpointByPort> optBaseEpByPort = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
\r
99 createBaseEpByPortIid(port.getUuid()), rTx);
\r
101 if (!optBaseEpByPort.isPresent()) {
\r
104 processCreatedData(port, optBaseEpByPort.get());
\r
107 void processCreated(BaseEndpointByPort bebp) {
\r
108 ReadOnlyTransaction rTx = transactionChain.newReadOnlyTransaction();
\r
109 Optional<Port> optPort = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
\r
110 createPortIid(bebp.getPortId()), rTx);
\r
112 if (!optPort.isPresent()) {
\r
115 processCreatedData(optPort.get(), bebp);
\r
119 void processCreatedData(Port port, BaseEndpointByPort bebp) {
\r
120 if (isValidVhostUser(port)
\r
121 // this is a hack for vpp router port
\r
122 // Openstack does not send binding details yet
\r
123 || isValidVppRouterPort(port)) {
\r
124 VppEndpoint vppEp = buildVppEndpoint(port, bebp);
\r
125 if (vppEp == null) {
\r
126 LOG.warn("Cannot create vpp-endpoint from neutron port {}", port);
\r
129 writeVppEndpoint(createVppEndpointIid(vppEp.getKey()), vppEp);
\r
130 LOG.debug("Created vpp-endpoint {}", vppEp);
\r
134 private boolean isValidVhostUser(Port port) {
\r
135 PortBindingExtension portBindingExt = port.getAugmentation(PortBindingExtension.class);
\r
136 if (portBindingExt != null) {
\r
137 String vifType = portBindingExt.getVifType();
\r
138 String deviceOwner = port.getDeviceOwner();
\r
139 if (vifType != null && deviceOwner != null) {
\r
140 if (vifType.contains(VHOST_USER)) {
\r
141 for (String supportedDeviceOwner : SUPPORTED_DEVICE_OWNERS) {
\r
142 if (deviceOwner.contains(supportedDeviceOwner)) {
\r
152 void processUpdated(Port original, Port delta) {
\r
153 if (!isUpdateNeeded(original, delta)){
\r
154 LOG.trace("Port update skipped, port didn`t change. before {}, after: {}" , original, delta);
\r
158 LOG.trace("Updating port before: {}, after: {}" , original, delta);
\r
159 if (isValidVhostUser(original)) {
\r
160 ReadOnlyTransaction rTx = transactionChain.newReadOnlyTransaction();
\r
161 Optional<BaseEndpointByPort> optBebp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
\r
162 createBaseEpByPortIid(original.getUuid()), rTx);
\r
164 if (!optBebp.isPresent()) {
\r
167 LOG.trace("Updating port - deleting old port {}" , optBebp.get().getPortId());
\r
168 processDeleted(optBebp.get());
\r
170 LOG.trace("Updating port - creating new port {}" , delta.getUuid());
\r
171 processCreated(delta);
\r
174 private boolean isUpdateNeeded(final Port oldPort, final Port newPort) {
\r
175 //TODO fix this to better support update of ports for VPP
\r
176 final PortBindingExtension oldPortAugmentation = oldPort.getAugmentation(PortBindingExtension.class);
\r
177 final PortBindingExtension newPortAugmentation = newPort.getAugmentation(PortBindingExtension.class);
\r
179 if (newPortAugmentation == null) {
\r
180 LOG.trace("Port {} is no longer a vhost type port, updating port...");
\r
184 final String oldDeviceOwner = oldPort.getDeviceOwner();
\r
185 final String oldVifType = oldPortAugmentation.getVifType();
\r
186 final String newDeviceOwner = newPort.getDeviceOwner();
\r
187 final String newVifType = newPortAugmentation.getVifType();
\r
189 // TODO potential bug here
\r
190 // Temporary change for Openstack Mitaka: If old neutron-binding:vif-type is vhost, new one is unbound and
\r
191 // device owner is ROUTER_OWNER, skip update. Openstack (or ml2) sometimes sends router update messages in
\r
192 // incorrect order which causes unwanted port removal
\r
193 if (oldVifType.equals(VHOST_USER) && newVifType.equals(UNBOUND) && oldDeviceOwner != null &&
\r
194 ROUTER_OWNER.equals(oldDeviceOwner) && ROUTER_OWNER.equals(newDeviceOwner)) {
\r
195 LOG.warn("Port vif-type was updated from vhost to unbound. This update is currently disabled and will be skipped");
\r
199 if (newVifType != null && !newVifType.equals(oldVifType)) {
\r
200 LOG.trace("Vif type changed, old: {} new {}", oldVifType, newVifType);
\r
204 final List<VifDetails> vifDetails = oldPortAugmentation.getVifDetails();
\r
206 if (!oldPortAugmentation.getHostId().equals(newPortAugmentation.getHostId()) ||
\r
207 nullToEmpty(vifDetails).size() != nullToEmpty(newPortAugmentation.getVifDetails()).size()) {
\r
211 for (VifDetails vifDetail : nullToEmpty(vifDetails)) {
\r
212 //check if vhostuser_socket, vhostuser_mode and port_filter are changed
\r
213 if (!newPortAugmentation.getVifDetails().contains(vifDetail))
\r
219 void processDeleted(BaseEndpointByPort bebp) {
\r
220 LOG.trace("Deleting vpp-endpoint by BaseEndpointByPort {}" , bebp);
\r
221 VppEndpointKey vppEpKey = new VppEndpointKey(bebp.getAddress(), bebp.getAddressType(), bebp.getContextId(),
\r
222 bebp.getContextType());
\r
223 InstanceIdentifier<VppEndpoint> vppEpIid = createVppEndpointIid(vppEpKey);
\r
224 ReadOnlyTransaction rTx = transactionChain.newReadOnlyTransaction();
\r
225 Optional<VppEndpoint> readVppEp = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, vppEpIid, rTx);
\r
227 if (readVppEp.isPresent()) {
\r
228 writeVppEndpoint(vppEpIid, null);
\r
229 LOG.debug("Deleted vpp-endpoint {}", vppEpKey);
\r
233 private synchronized void writeVppEndpoint(InstanceIdentifier<VppEndpoint> vppEpIid, VppEndpoint vppEp) {
\r
234 WriteTransaction wTx = transactionChain.newWriteOnlyTransaction();
\r
235 if (vppEp != null) {
\r
236 wTx.put(LogicalDatastoreType.CONFIGURATION, vppEpIid, vppEp, true);
\r
238 wTx.delete(LogicalDatastoreType.CONFIGURATION, vppEpIid);
\r
244 VppEndpoint buildVppEndpoint(Port port, BaseEndpointByPort bebp) {
\r
245 PortBindingExtension portBinding = port.getAugmentation(PortBindingExtension.class);
\r
246 VppEndpointBuilder vppEpBuilder = new VppEndpointBuilder().setDescription("neutron port")
\r
247 .setContextId(bebp.getContextId())
\r
248 .setContextType(bebp.getContextType())
\r
249 .setAddress(bebp.getAddress())
\r
250 .setAddressType(bebp.getAddressType())
\r
251 .setVppInterfaceName(VPP_INTERFACE_NAME_PREFIX + bebp.getPortId().getValue())
\r
252 .setVppNodeId(new NodeId(portBinding.getHostId()));
\r
253 if (port.getDeviceOwner().contains(COMPUTE_OWNER)) {
\r
254 vppEpBuilder.setInterfaceTypeChoice(
\r
255 new VhostUserCaseBuilder().setSocket(getSocketFromPortBinding(portBinding)).build());
\r
256 } else if (port.getDeviceOwner().contains(DHCP_OWNER) && port.getMacAddress() != null) {
\r
257 TapCase tapCase = new TapCaseBuilder().setPhysicalAddress(new PhysAddress(port.getMacAddress().getValue()))
\r
258 .setName(createPortName(port.getUuid()))
\r
260 vppEpBuilder.setInterfaceTypeChoice(tapCase);
\r
261 } else if (isValidQRouterPort(port)) {
\r
262 TapCase tapCase = new TapCaseBuilder().setPhysicalAddress(new PhysAddress(port.getMacAddress().getValue()))
\r
263 .setName(createQRouterPortName(port.getUuid()))
\r
265 vppEpBuilder.setInterfaceTypeChoice(tapCase);
\r
266 vppEpBuilder.addAugmentation(ExcludeFromPolicy.class,
\r
267 new ExcludeFromPolicyBuilder().setExcludeFromPolicy(true).build());
\r
268 } else if (isValidVppRouterPort(port)) {
\r
269 if (!DEFAULT_NODE.equals(routingNode.getValue())) {
\r
271 "Host-id changed by ODL for port {}. This is a supplementary workaround for choosing a routing node.",
\r
273 vppEpBuilder.setVppNodeId(routingNode);
\r
274 } else if (port.getDeviceId() != null) {
\r
275 LOG.debug("Resolving host-id for unbound router port {}", port.getUuid());
\r
276 ReadOnlyTransaction readTx = dataBroker.newReadOnlyTransaction();
\r
277 Optional<Ports> optPorts = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
\r
278 InstanceIdentifier.builder(Neutron.class).child(Ports.class).build(), readTx);
\r
280 if (optPorts.isPresent() && optPorts.get().getPort() != null) {
\r
281 java.util.Optional<Port> optPortOnTheSameNode = optPorts.get()
\r
284 .filter(p -> !p.getUuid().equals(port.getUuid()))
\r
285 .filter(p -> p.getAugmentation(PortBindingExtension.class) != null)
\r
286 .filter(p -> p.getDeviceOwner().contains(DHCP_OWNER))
\r
288 if (optPortOnTheSameNode.isPresent()) {
\r
289 PortBindingExtension binding =
\r
290 optPortOnTheSameNode.get().getAugmentation(PortBindingExtension.class);
\r
291 if (binding != null && binding.getHostId() != null) {
\r
292 vppEpBuilder.setVppNodeId(new NodeId(binding.getHostId()));
\r
294 LOG.warn("Cannot resolve location of router-port {}", port.getUuid());
\r
300 vppEpBuilder.addAugmentation(ExcludeFromPolicy.class,
\r
301 new ExcludeFromPolicyBuilder().setExcludeFromPolicy(true).build());
\r
302 vppEpBuilder.setInterfaceTypeChoice(getLoopbackCase(port));
\r
304 return vppEpBuilder.build();
\r
307 private String getSocketFromPortBinding(@Nonnull PortBindingExtension portBindingExtension) {
\r
308 List<VifDetails> vifDetails = nullToEmpty(portBindingExtension.getVifDetails());
\r
310 for (VifDetails detail : vifDetails) {
\r
311 if (VHOST_SOCKET_KEY.equalsIgnoreCase(detail.getDetailsKey())) {
\r
312 return detail.getValue();
\r
318 private LoopbackCase getLoopbackCase(Port port) {
\r
319 LoopbackCaseBuilder loopbackCase = new LoopbackCaseBuilder()
\r
320 .setPhysAddress(new PhysAddress(port.getMacAddress().getValue()));
\r
321 Optional<FixedIps> fixedIpsOptional = resolveFirstFixedIps(port);
\r
322 if(fixedIpsOptional.isPresent() && fixedIpsOptional.get().getIpAddress() != null){
\r
323 loopbackCase.setIpAddress(fixedIpsOptional.get().getIpAddress());
\r
324 ReadOnlyTransaction rTx = transactionChain.newReadOnlyTransaction();
\r
325 Optional<Subnet> subnetOptional =
\r
326 DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
\r
327 InstanceIdentifier.builder(Neutron.class)
\r
328 .child(Subnets.class)
\r
329 .child(Subnet.class, new SubnetKey(fixedIpsOptional.get().getSubnetId()))
\r
331 if (subnetOptional.isPresent()) {
\r
332 Ipv4Prefix ipv4Prefix = subnetOptional.get().getCidr().getIpv4Prefix();
\r
333 loopbackCase.setIpPrefix(new IpPrefix(ipv4Prefix));
\r
335 LOG.warn("IpPrefix for loopback port: {} was not set.", port);
\r
337 if (loopbackCase.getIpAddress() != null && loopbackCase.getIpPrefix() != null) {
\r
338 loopbackCase.setBvi(true);
\r
339 LOG.trace("Creating loopback BVI interface: {} for VPP router port: {}.", loopbackCase, port);
\r
343 LOG.warn("IpAddress for loopback port: {} was not set.", port);
\r
345 return loopbackCase.build();
\r
349 * If Qrouter (L3 Agent) is in use, any of Openstack neutron routers is not going be mapped
\r
352 private boolean isValidQRouterPort(Port port) {
\r
353 Optional<Router> optRouter = getRouterOptional(port);
\r
354 return !optRouter.isPresent() && port.getDeviceOwner().contains(ROUTER_OWNER)
\r
355 && port.getMacAddress() != null;
\r
358 private boolean isValidVppRouterPort(Port port) {
\r
359 Optional<Router> optRouter = getRouterOptional(port);
\r
360 return optRouter.isPresent() && port.getDeviceOwner().contains(ROUTER_OWNER)
\r
361 && port.getMacAddress() != null;
\r
364 private Optional<Router> getRouterOptional(Port port) {
\r
365 if (Strings.isNullOrEmpty(port.getDeviceId())) {
\r
366 return Optional.absent();
\r
368 ReadOnlyTransaction rTx = transactionChain.newReadOnlyTransaction();
\r
369 InstanceIdentifier<Router> routerIid = InstanceIdentifier.builder(Neutron.class)
\r
370 .child(Routers.class)
\r
371 .child(Router.class, new RouterKey(new Uuid(port.getDeviceId())))
\r
373 Optional<Router> optRouter = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, routerIid, rTx);
\r
378 public static Optional<FixedIps> resolveFirstFixedIps(Port port) {
\r
379 List<FixedIps> fixedIps = port.getFixedIps();
\r
380 if (fixedIps != null && !fixedIps.isEmpty()) {
\r
381 return Optional.of(fixedIps.get(0));
\r
383 return Optional.absent();
\r
386 private String createPortName(Uuid portUuid) {
\r
387 String tapPortName;
\r
388 String uuid = portUuid.getValue();
\r
389 if (uuid != null && uuid.length() >= 12) {
\r
390 tapPortName = TAP_PORT_NAME_PREFIX + uuid.substring(0, 11);
\r
392 tapPortName = TAP_PORT_NAME_PREFIX + uuid;
\r
394 return tapPortName;
\r
397 private String createQRouterPortName(Uuid portUuid) {
\r
398 String tapPortName;
\r
399 String uuid = portUuid.getValue();
\r
400 if (uuid != null && uuid.length() >= 12) {
\r
401 tapPortName = RT_PORT_NAME_PREFIX + uuid.substring(0, 11);
\r
403 tapPortName = RT_PORT_NAME_PREFIX + uuid;
\r
405 return tapPortName;
\r
408 private InstanceIdentifier<VppEndpoint> createVppEndpointIid(VppEndpointKey vppEpKey) {
\r
409 return InstanceIdentifier.builder(Config.class).child(VppEndpoint.class, vppEpKey).build();
\r
412 private InstanceIdentifier<BaseEndpointByPort> createBaseEpByPortIid(Uuid uuid) {
\r
413 return createBaseEpByPortIid(new UniqueId(uuid.getValue()));
\r
416 private InstanceIdentifier<BaseEndpointByPort> createBaseEpByPortIid(UniqueId uuid) {
\r
417 return InstanceIdentifier.builder(Mappings.class)
\r
418 .child(GbpByNeutronMappings.class)
\r
419 .child(BaseEndpointsByPorts.class)
\r
420 .child(BaseEndpointByPort.class, new BaseEndpointByPortKey(uuid))
\r
424 InstanceIdentifier<Port> createWildcartedPortIid() {
\r
425 return portsIid().child(Port.class).build();
\r
428 private InstanceIdentifier<Port> createPortIid(UniqueId uuid) {
\r
429 return portsIid().child(Port.class, new PortKey(new Uuid(uuid.getValue()))).build();
\r
432 private InstanceIdentifierBuilder<Ports> portsIid() {
\r
433 return InstanceIdentifier.builder(Neutron.class).child(Ports.class);
\r
437 public void onTransactionChainFailed(TransactionChain<?, ?> chain, AsyncTransaction<?, ?> transaction,
\r
439 LOG.error("Transaction chain failed. {} \nTransaction which caused the chain to fail {}", cause.getMessage(),
\r
440 transaction, cause);
\r
441 transactionChain.close();
\r
442 transactionChain = dataBroker.createTransactionChain(this);
\r
446 public void onTransactionChainSuccessful(TransactionChain<?, ?> chain) {
\r
447 LOG.trace("Transaction chain was successful. {}", chain);
\r
450 private <T> List<T> nullToEmpty(@Nullable List<T> list) {
\r
451 return list == null ? Collections.emptyList() : list;
\r