package org.opendaylight.groupbasedpolicy.renderer.vpp.iface;
+import static com.google.common.base.Preconditions.checkNotNull;
+
import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.CloseOnFailTransactionChain;
import org.opendaylight.groupbasedpolicy.renderer.vpp.util.KeyFactory;
import org.opendaylight.groupbasedpolicy.util.IidFactory;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
public static final ProviderName VPP_ENDPOINT_LOCATION_PROVIDER =
new ProviderName("VPP endpoint location provider");
public static final long PROVIDER_PRIORITY = 10L;
- private final DataBroker dataProvider;
+ private final BindingTransactionChain txChain;
public VppEndpointLocationProvider(DataBroker dataProvider) {
- this.dataProvider = Preconditions.checkNotNull(dataProvider);
LocationProvider locationProvider = new LocationProviderBuilder().setProvider(VPP_ENDPOINT_LOCATION_PROVIDER)
.setPriority(PROVIDER_PRIORITY)
.build();
- WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
+ txChain = checkNotNull(dataProvider)
+ .createTransactionChain(new CloseOnFailTransactionChain(VppEndpointLocationProvider.class.getSimpleName()));
+ WriteTransaction wTx = txChain.newWriteOnlyTransaction();
wTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.locationProviderIid(VPP_ENDPOINT_LOCATION_PROVIDER),
locationProvider, true);
public void createLocationForVppEndpoint(VppEndpoint vppEndpoint) {
ProviderAddressEndpointLocation providerAddressEndpointLocation =
createProviderAddressEndpointLocation(vppEndpoint);
- WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
+ WriteTransaction wTx = txChain.newWriteOnlyTransaction();
wTx.put(LogicalDatastoreType.CONFIGURATION,
IidFactory.providerAddressEndpointLocationIid(VPP_ENDPOINT_LOCATION_PROVIDER,
providerAddressEndpointLocation.getKey()),
public void deleteLocationForVppEndpoint(VppEndpoint vppEndpoint) {
ProviderAddressEndpointLocationKey provAddrEpLocKey = createProviderAddressEndpointLocationKey(vppEndpoint);
- WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
+ WriteTransaction wTx = txChain.newWriteOnlyTransaction();
wTx.delete(LogicalDatastoreType.CONFIGURATION,
IidFactory.providerAddressEndpointLocationIid(VPP_ENDPOINT_LOCATION_PROVIDER, provAddrEpLocKey));
LOG.debug("Deleting location for {}", provAddrEpLocKey);
new AbsoluteLocationBuilder().setLocationType(location).build();
ProviderAddressEndpointLocation providerAddressEndpointLocation = new ProviderAddressEndpointLocationBuilder()
.setKey(provAddrEpLocKey).setAbsoluteLocation(absoluteLocation).build();
- WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
+ WriteTransaction wTx = txChain.newWriteOnlyTransaction();
wTx.put(LogicalDatastoreType.CONFIGURATION,
IidFactory.providerAddressEndpointLocationIid(VPP_ENDPOINT_LOCATION_PROVIDER,
providerAddressEndpointLocation.getKey()),
@Override
public void close() throws Exception {
- WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
+ WriteTransaction wTx = txChain.newWriteOnlyTransaction();
wTx.delete(LogicalDatastoreType.CONFIGURATION, IidFactory.locationProviderIid(VPP_ENDPOINT_LOCATION_PROVIDER));
wTx.submit();
}
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.NetworkDomainContainment;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.LocationType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L2FloodDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.fields.Parent;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.forwarding.renderer.forwarding.by.tenant.RendererForwardingContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.forwarding.renderer.forwarding.by.tenant.RendererForwardingContextKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.forwarding.renderer.forwarding.by.tenant.RendererNetworkDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.forwarding.renderer.forwarding.by.tenant.RendererNetworkDomainKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.Config;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.VlanNetwork;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.BridgeDomain;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.SetMultimap;
+import com.google.common.collect.Table;
public final class ForwardingManager {
}
if (Strings.isNullOrEmpty(rEpLoc.getExternalNode())) {
- Optional<String> optL2FloodDomain = resolveL2FloodDomain(rEp.getNetworkContainment());
+ java.util.Optional<String> optL2FloodDomain = resolveL2FloodDomain(rEp, policyCtx);
if (!optL2FloodDomain.isPresent()) {
// TODO add it to the status for renderer manager
LOG.info("Rednerer endpoint does not have l2FloodDomain as network containment {}", rEp);
return result;
}
- public static Optional<String> resolveL2FloodDomain(@Nullable NetworkContainment netCont) {
+ public static java.util.Optional<String> resolveL2FloodDomain(@Nonnull AddressEndpointWithLocation ep,
+ @Nonnull PolicyContext policyCtx) {
+ NetworkContainment netCont = ep.getNetworkContainment();
if (netCont == null) {
- return Optional.absent();
+ return java.util.Optional.empty();
}
Containment containment = netCont.getContainment();
if (containment instanceof ForwardingContextContainment) {
ForwardingContextContainment fwCtxCont = (ForwardingContextContainment) containment;
- if (fwCtxCont.getContextType().isAssignableFrom(L2FloodDomain.class)) {
- return fwCtxCont.getContextId() == null ? null : Optional.of(fwCtxCont.getContextId().getValue());
+ if (L2FloodDomain.class.equals(fwCtxCont.getContextType())) {
+ return fwCtxCont.getContextId() == null ? java.util.Optional.empty() : java.util.Optional
+ .of(fwCtxCont.getContextId().getValue());
}
}
if (containment instanceof NetworkDomainContainment) {
- // TODO address missing impl
- LOG.info("Network domain containment in endpoint is not supported yet. {}", netCont);
- return Optional.absent();
+ NetworkDomainContainment netDomainCont = (NetworkDomainContainment) containment;
+ RendererNetworkDomain rendererNetworkDomain =
+ policyCtx.getNetworkDomainTable().get(ep.getTenant(), new RendererNetworkDomainKey(
+ netDomainCont.getNetworkDomainId(), netDomainCont.getNetworkDomainType()));
+ java.util.Optional<String> optL2Fd = getForwardingCtxForParent(ep.getTenant(),
+ rendererNetworkDomain.getParent(), policyCtx.getForwardingCtxTable())
+ .filter(fwdCtx -> L2FloodDomain.class.equals(fwdCtx.getContextType()))
+ .map(RendererForwardingContext::getContextId)
+ .map(ContextId::getValue);
+ if (!optL2Fd.isPresent()) {
+ LOG.info("network-domain-containment in endpoint does not have L2-flood-domain as parent. "
+ + "This case is not supported in VPP renderer. {}", ep);
+ }
+ return optL2Fd;
+ }
+ return java.util.Optional.empty();
+ }
+
+ public static @Nonnull java.util.Optional<RendererForwardingContext> getForwardingCtxForParent(
+ @Nullable TenantId tenant, @Nullable Parent parent,
+ Table<TenantId, RendererForwardingContextKey, RendererForwardingContext> forwardingCtxTable) {
+ if (tenant == null || parent == null) {
+ return java.util.Optional.empty();
+ }
+ if (parent.getContextId() != null && parent.getContextType() != null) {
+ return java.util.Optional.ofNullable(forwardingCtxTable.get(tenant,
+ new RendererForwardingContextKey(parent.getContextId(), parent.getContextType())));
}
- return Optional.absent();
+ return java.util.Optional.empty();
}
}
import org.opendaylight.groupbasedpolicy.renderer.vpp.util.KeyFactory;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.peer.endpoints.PeerEndpointKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererPolicy;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Configuration;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpoint;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.forwarding.renderer.forwarding.by.tenant.RendererForwardingContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.forwarding.renderer.forwarding.by.tenant.RendererForwardingContextKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.forwarding.renderer.forwarding.by.tenant.RendererNetworkDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.forwarding.renderer.forwarding.by.tenant.RendererNetworkDomainKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.rule.groups.RuleGroup;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.rule.groups.RuleGroupKey;
private final ImmutableTable<RendererEndpointKey, PeerEndpointKey, ImmutableSortedSet<RendererResolvedPolicy>> policyTable;
private final ImmutableMap<RuleGroupKey, ResolvedRuleGroup> ruleGroupByKey;
private final ImmutableMap<AddressEndpointKey, AddressEndpointWithLocation> addrEpByKey;
+ private final ImmutableTable<TenantId, RendererForwardingContextKey, RendererForwardingContext> forwardingCtxTable;
+ private final ImmutableTable<TenantId, RendererNetworkDomainKey, RendererNetworkDomain> networkDomainTable;
public PolicyContext(@Nonnull RendererPolicy policy) {
this.policy = Preconditions.checkNotNull(policy);
List<RendererEndpoint> rendererEps = resolveRendererEndpoints(config);
this.policyTable = resolvePolicy(rendererEps, ruleGroupByKey);
addrEpByKey = resolveAddrEpWithLoc(config);
+ this.forwardingCtxTable = resolveForwardingCtxTable(config);
+ this.networkDomainTable = resolveNetworkDomainTable(config);
} else {
this.ruleGroupByKey = ImmutableMap.of();
this.policyTable = ImmutableTable.of();
this.addrEpByKey = ImmutableMap.of();
+ this.forwardingCtxTable = ImmutableTable.of();
+ this.networkDomainTable = ImmutableTable.of();
}
}
.collectingAndThen(Collectors.toMap(RuleGroup::getKey, ResolvedRuleGroup::new), ImmutableMap::copyOf));
}
+ private static ImmutableTable<TenantId, RendererForwardingContextKey, RendererForwardingContext> resolveForwardingCtxTable(
+ Configuration config) {
+ Builder<TenantId, RendererForwardingContextKey, RendererForwardingContext> resultBuilder = new Builder<>();
+ Optional.ofNullable(config.getRendererForwarding()).map(x -> x.getRendererForwardingByTenant()).ifPresent(x -> {
+ x.forEach(fwdByTenant -> {
+ Optional.ofNullable(fwdByTenant.getRendererForwardingContext()).ifPresent(fwdCtxs -> {
+ fwdCtxs.forEach(fwdCtx -> {
+ resultBuilder.put(fwdByTenant.getTenantId(), fwdCtx.getKey(), fwdCtx);
+ });
+ });
+ });
+ });
+ return resultBuilder.build();
+ }
+
+ private static ImmutableTable<TenantId, RendererNetworkDomainKey, RendererNetworkDomain> resolveNetworkDomainTable(
+ Configuration config) {
+ Builder<TenantId, RendererNetworkDomainKey, RendererNetworkDomain> resultBuilder = new Builder<>();
+ Optional.ofNullable(config.getRendererForwarding()).map(x -> x.getRendererForwardingByTenant()).ifPresent(x -> {
+ x.forEach(fwdByTenant -> {
+ Optional.ofNullable(fwdByTenant.getRendererNetworkDomain()).ifPresent(netDomains -> {
+ netDomains.forEach(netDomain -> {
+ resultBuilder.put(fwdByTenant.getTenantId(), netDomain.getKey(), netDomain);
+ });
+ });
+ });
+ });
+ return resultBuilder.build();
+ }
+
private static ImmutableMap<AddressEndpointKey, AddressEndpointWithLocation> resolveAddrEpWithLoc(
Configuration config) {
return Maps.uniqueIndex(config.getEndpoints().getAddressEndpointWithLocation(),
return addrEpByKey;
}
+ public @Nonnull ImmutableTable<TenantId, RendererForwardingContextKey, RendererForwardingContext> getForwardingCtxTable() {
+ return forwardingCtxTable;
+ }
+
+ public @Nonnull ImmutableTable<TenantId, RendererNetworkDomainKey, RendererNetworkDomain> getNetworkDomainTable() {
+ return networkDomainTable;
+ }
+
@Override
public String toString() {
- return "PolicyContext [policy=" + policy + ", policyTable=" + policyTable + ", ruleGroupByKey=" + ruleGroupByKey
- + ", addrEpByKey=" + addrEpByKey + "]";
+ return "PolicyContext [policyTable=" + policyTable + ", ruleGroupByKey=" + ruleGroupByKey + ", addrEpByKey="
+ + addrEpByKey + ", forwardingCtxTable=" + forwardingCtxTable + ", networkDomainTable="
+ + networkDomainTable + "]";
}
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableSet;
.map(addrEpKey -> policyCtx.getAddrEpByKey().get(addrEpKey))
.collect(Collectors.toSet())
.forEach(addrEpWithLoc -> {
- Optional<String> optL2Fd =
- ForwardingManager.resolveL2FloodDomain(addrEpWithLoc.getNetworkContainment());
+ java.util.Optional<String> optL2Fd = ForwardingManager.resolveL2FloodDomain(addrEpWithLoc, policyCtx);
if (optL2Fd.isPresent()) {
ExternalLocationCase rEpLoc = ForwardingManager.resolveAndValidateLocation(addrEpWithLoc);
InstanceIdentifier<?> externalNodeMountPoint = rEpLoc.getExternalNodeMountPoint();
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.vpp.util;
+
+import javax.annotation.Nonnull;
+
+import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+
+public class CloseOnFailTransactionChain implements TransactionChainListener {
+
+ private static final Logger LOG = LoggerFactory.getLogger(CloseOnFailTransactionChain.class);
+ private final String owner;
+
+ public CloseOnFailTransactionChain(@Nonnull String owner) {
+ this.owner = Preconditions.checkNotNull(owner);
+ }
+
+ @Override
+ public void onTransactionChainSuccessful(TransactionChain<?, ?> chain) {
+ LOG.info("Transaction chain owned by {} was successful. {}", owner, chain);
+ }
+
+ @Override
+ public void onTransactionChainFailed(TransactionChain<?, ?> chain, AsyncTransaction<?, ?> transaction,
+ Throwable cause) {
+ LOG.warn("Transaction chain owned by {} failed. Transaction which caused the chain to fail {}", owner,
+ transaction, cause);
+ chain.close();
+ }
+
+}