Merge "Endpoint added"
[groupbasedpolicy.git] / renderers / vpp / src / main / java / org / opendaylight / groupbasedpolicy / renderer / vpp / policy / ForwardingManager.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.groupbasedpolicy.renderer.vpp.policy;
10
11 import java.util.Set;
12 import java.util.concurrent.ExecutionException;
13
14 import javax.annotation.Nonnull;
15 import javax.annotation.Nullable;
16
17 import org.opendaylight.groupbasedpolicy.renderer.vpp.api.BridgeDomainManager;
18 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
19 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.KeyFactory;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.NetworkContainment;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.Containment;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.ForwardingContextContainment;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.NetworkDomainContainment;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.LocationType;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L2FloodDomain;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpointKey;
29 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 import com.google.common.base.Optional;
34 import com.google.common.base.Preconditions;
35 import com.google.common.base.Strings;
36 import com.google.common.collect.SetMultimap;
37
38 public class ForwardingManager {
39
40     private static final Logger LOG = LoggerFactory.getLogger(ForwardingManager.class);
41
42     private final InterfaceManager ifaceManager;
43     private final BridgeDomainManager bdManager;
44
45     public ForwardingManager(@Nonnull InterfaceManager ifaceManager, @Nonnull BridgeDomainManager bdManager) {
46         this.ifaceManager = Preconditions.checkNotNull(ifaceManager);
47         this.bdManager = Preconditions.checkNotNull(bdManager);
48     }
49
50     public void createVxlanBridgeDomainsOnNodes(SetMultimap<String, NodeId> vppNodesByBridgeDomain) {
51         for (String bd : vppNodesByBridgeDomain.keySet()) {
52             Set<NodeId> vppNodes = vppNodesByBridgeDomain.get(bd);
53             for (NodeId vppNode : vppNodes) {
54                 try {
55                     bdManager.createVxlanBridgeDomainOnVppNode(bd, null, vppNode).get();
56                 } catch (InterruptedException | ExecutionException e) {
57                     LOG.warn("Bridge domain {} was not created on node {}", bd, vppNode.getValue(), e);
58                 }
59             }
60         }
61     }
62
63     public void removeVxlanBridgeDomainsOnNodes(SetMultimap<String, NodeId> vppNodesByBridgeDomain) {
64         for (String bd : vppNodesByBridgeDomain.keySet()) {
65             Set<NodeId> vppNodes = vppNodesByBridgeDomain.get(bd);
66             for (NodeId vppNode : vppNodes) {
67                 try {
68                     bdManager.removeBridgeDomainFromVppNode(bd, vppNode).get();
69                 } catch (InterruptedException | ExecutionException e) {
70                     LOG.warn("Bridge domain {} was not removed from node {}", bd, vppNode.getValue(), e);
71                 }
72             }
73         }
74     }
75
76     public void createForwardingForEndpoint(RendererEndpointKey rEpKey, PolicyContext policyCtx) {
77         AddressEndpointWithLocation rEp = policyCtx.getAddrEpByKey().get(KeyFactory.addressEndpointKey(rEpKey));
78         ExternalLocationCase rEpLoc = resolveAndValidateLocation(rEp);
79         if (Strings.isNullOrEmpty(rEpLoc.getExternalNodeConnector())) {
80             // TODO add it to the status for renderer manager
81             LOG.info("Rednerer endpoint does not have external-node-connector therefore it is ignored {}", rEp);
82             return;
83         }
84
85         if (Strings.isNullOrEmpty(rEpLoc.getExternalNode())) {
86             Optional<String> optL2FloodDomain = resolveL2FloodDomain(rEp.getNetworkContainment());
87             if (!optL2FloodDomain.isPresent()) {
88                 // TODO add it to the status for renderer manager
89                 LOG.info("Rednerer endpoint does not have l2FloodDomain as network containment {}", rEp);
90                 return;
91             }
92             String l2FloodDomain = optL2FloodDomain.get();
93             try {
94                 ifaceManager.addBridgeDomainToInterface(l2FloodDomain, rEp).get();
95                 LOG.debug("Interface added to bridge-domain {} for endpoint {}", l2FloodDomain, rEp);
96             } catch (InterruptedException | ExecutionException e) {
97                 // TODO add it to the status for renderer manager
98                 LOG.warn("Interface was not added to bridge-domain {} for endpoint {}", l2FloodDomain, rEp, e);
99             }
100         }
101     }
102
103     public void removeForwardingForEndpoint(RendererEndpointKey rEpKey, PolicyContext policyCtx) {
104         AddressEndpointWithLocation rEp = policyCtx.getAddrEpByKey().get(KeyFactory.addressEndpointKey(rEpKey));
105         ExternalLocationCase rEpLoc = resolveAndValidateLocation(rEp);
106         if (Strings.isNullOrEmpty(rEpLoc.getExternalNodeConnector())) {
107             // nothing was created for endpoint therefore nothing is removed
108             return;
109         }
110
111         if (!Strings.isNullOrEmpty(rEpLoc.getExternalNode())) {
112             try {
113                 ifaceManager.deleteBridgeDomainFromInterface(rEp).get();
114                 LOG.debug("bridge-domain was deleted from interface for endpoint {}", rEp);
115             } catch (InterruptedException | ExecutionException e) {
116                 // TODO add it to the status for renderer manager
117                 LOG.warn("bridge-domain was not deleted from interface for endpoint {}", rEp, e);
118             }
119         }
120     }
121
122     public static ExternalLocationCase resolveAndValidateLocation(AddressEndpointWithLocation addrEpWithLoc) {
123         LocationType locationType = addrEpWithLoc.getAbsoluteLocation().getLocationType();
124         if (!(locationType instanceof ExternalLocationCase)) {
125             throw new IllegalStateException("Endpoint does not have external location " + addrEpWithLoc);
126         }
127         ExternalLocationCase result = (ExternalLocationCase) locationType;
128         if (result.getExternalNodeMountPoint() == null) {
129             throw new IllegalStateException("Endpoint does not have external-node-mount-point " + addrEpWithLoc);
130         }
131         return result;
132     }
133
134     public static Optional<String> resolveL2FloodDomain(@Nullable NetworkContainment netCont) {
135         if (netCont == null) {
136             return Optional.absent();
137         }
138         Containment containment = netCont.getContainment();
139         if (containment instanceof ForwardingContextContainment) {
140             ForwardingContextContainment fwCtxCont = (ForwardingContextContainment) containment;
141             if (fwCtxCont.getContextType().isAssignableFrom(L2FloodDomain.class)) {
142                 return fwCtxCont.getContextId() == null ? null : Optional.of(fwCtxCont.getContextId().getValue());
143             }
144         }
145         if (containment instanceof NetworkDomainContainment) {
146             // TODO address missing impl
147             LOG.info("Network domain containment in endpoint is not supported yet. {}", netCont);
148             return Optional.absent();
149         }
150         return Optional.absent();
151     }
152
153 }