Fix build faliures due to OFPlugin checktyle fixes
[netvirt.git] / vpnservice / sfc / translator / src / main / java / org / opendaylight / netvirt / sfc / translator / portchain / NeutronPortChainListener.java
1 /*
2  * Copyright (c) 2016, 2017 Brocade Communications 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.netvirt.sfc.translator.portchain;
10
11 import java.util.ArrayList;
12 import java.util.HashMap;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.concurrent.ExecutionException;
16 import java.util.concurrent.Future;
17 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
18 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
19 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
20 import org.opendaylight.infrautils.utils.concurrent.JdkFutures;
21 import org.opendaylight.netvirt.sfc.translator.DelegatingDataTreeListener;
22 import org.opendaylight.netvirt.sfc.translator.NeutronMdsalHelper;
23 import org.opendaylight.netvirt.sfc.translator.SfcMdsalHelper;
24 import org.opendaylight.netvirt.sfc.translator.flowclassifier.FlowClassifierTranslator;
25 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInput;
26 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathOutput;
27 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.DeleteRenderedPathInput;
28 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.RenderedServicePathService;
29 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunction;
30 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.ServiceFunctionChain;
31 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
32 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.flow.classifier.rev160511.sfc.flow.classifiers.attributes.sfc.flow.classifiers.SfcFlowClassifier;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.PortChains;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.chains.PortChain;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.pair.groups.PortPairGroup;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.pairs.PortPair;
41 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
42 import org.opendaylight.yangtools.yang.common.RpcResult;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 /**
47  * OpenDaylight Neutron Port Chain yang models data change listener.
48  */
49 public class NeutronPortChainListener extends DelegatingDataTreeListener<PortChain> {
50     private static final Logger LOG = LoggerFactory.getLogger(NeutronPortChainListener.class);
51
52     private static final InstanceIdentifier<PortChain> PORT_CHAIN_IID =
53             InstanceIdentifier.create(Neutron.class).child(PortChains.class).child(PortChain.class);
54     private final SfcMdsalHelper sfcMdsalHelper;
55     private final NeutronMdsalHelper neutronMdsalHelper;
56     private final RenderedServicePathService rspService;
57
58     public NeutronPortChainListener(DataBroker db, RenderedServicePathService rspService) {
59         super(db,new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, PORT_CHAIN_IID));
60         this.sfcMdsalHelper = new SfcMdsalHelper(db);
61         this.neutronMdsalHelper = new NeutronMdsalHelper(db);
62         this.rspService = rspService;
63     }
64
65     /**
66      * Method removes PortChain which is identified by InstanceIdentifier.
67      *
68      * @param path - the whole path to PortChain
69      * @param deletedPortChain        - PortChain for removing
70      */
71     @Override
72     public void remove(InstanceIdentifier<PortChain> path, PortChain deletedPortChain) {
73         if (this.rspService != null) {
74             DeleteRenderedPathInput deleteRenderedPathInput =
75                     PortChainTranslator.buildDeleteRenderedServicePathInput(PortChainTranslator
76                     .getSFPKey(deletedPortChain));
77             if (deleteRenderedPathInput != null) {
78                 JdkFutures.addErrorLogging(rspService.deleteRenderedPath(deleteRenderedPathInput),
79                         LOG, "deleteRenderedPath");
80             }
81         }
82         sfcMdsalHelper.deleteServiceFunctionPath(PortChainTranslator.getSFPKey(deletedPortChain));
83         sfcMdsalHelper.deleteServiceFunctionChain(PortChainTranslator.getSFCKey(deletedPortChain));
84     }
85
86     /**
87      * Method updates the original PortChain to the update PortChain.
88      * Both are identified by same InstanceIdentifier.
89      *
90      * @param path - the whole path to PortChain
91      * @param originalPortChain   - original PortChain (for update)
92      * @param updatePortChain     - changed PortChain (contain updates)
93      */
94     @Override
95     public void update(InstanceIdentifier<PortChain> path, PortChain originalPortChain, PortChain updatePortChain) {
96         //TODO: Add support for chain update
97     }
98
99     /**
100      * Method adds the PortChain which is identified by InstanceIdentifier
101      * to device.
102      *
103      * @param path - the whole path to new PortChain
104      * @param newPortChain        - new PortChain
105      */
106     @Override
107     public void add(final InstanceIdentifier<PortChain> path, final PortChain newPortChain) {
108         processPortChain(newPortChain);
109     }
110
111     private void processPortChain(PortChain newPortChain) {
112
113         //List of Port Pair Group attached to the Port Chain
114         List<PortPairGroup> portPairGroupList = new ArrayList<>();
115         //Port Pair Group and associated Port Pair
116         Map<Uuid, List<PortPair>> groupPortPairsList = new HashMap<>();
117
118         List<ServiceFunction> portChainServiceFunctionList = new ArrayList<>();
119
120         //Read chain related port pair group from neutron data store
121         for (Uuid ppgUuid : newPortChain.getPortPairGroups()) {
122             PortPairGroup ppg = neutronMdsalHelper.getNeutronPortPairGroup(ppgUuid);
123             if (ppg != null) {
124                 List<PortPair> portPairList = new ArrayList<>();
125                 portPairGroupList.add(ppg);
126                 for (Uuid ppUuid : ppg.getPortPairs()) {
127                     PortPair pp = neutronMdsalHelper.getNeutronPortPair(ppUuid);
128                     if (pp == null) {
129                         LOG.error("Port pair {} does not exist in the neutron data store", ppUuid);
130                         return;
131                     }
132                     portPairList.add(pp);
133                 }
134                 groupPortPairsList.put(ppgUuid, portPairList);
135             }
136         }
137
138         //For each port pair group
139         for (PortPairGroup ppg : portPairGroupList) {
140
141             List<PortPair> portPairList =  groupPortPairsList.get(ppg.getUuid());
142
143             //Generate all the SF and write it to SFC data store
144             for (PortPair portPair : portPairList) {
145                 //Build the service function for the given port pair.
146                 ServiceFunction serviceFunction = PortPairTranslator.buildServiceFunction(portPair, ppg);
147                 portChainServiceFunctionList.add(serviceFunction);
148
149                 //Write the Service Function to SFC data store.
150                 LOG.info("Add Service Function {} for Port Pair {}", serviceFunction, portPair);
151                 sfcMdsalHelper.addServiceFunction(serviceFunction);
152             }
153
154             //Build the SFF Builder from port pair group
155             ServiceFunctionForwarder serviceFunctionForwarder;
156             serviceFunctionForwarder = PortPairGroupTranslator.buildServiceFunctionForwarder(ppg, portPairList);
157             // Send SFF create request
158             LOG.info("Update Service Function Forwarder with {} for Port Pair Group {}", serviceFunctionForwarder, ppg);
159             sfcMdsalHelper.updateServiceFunctionForwarder(serviceFunctionForwarder);
160         }
161
162         //Build Service Function Chain Builder
163         ServiceFunctionChain sfc =
164                 PortChainTranslator.buildServiceFunctionChain(newPortChain, portChainServiceFunctionList);
165
166         //Write SFC to data store
167         if (sfc == null) {
168             LOG.warn("Service Function Chain building failed for Port Chain {}", newPortChain);
169             return;
170         }
171
172         LOG.info("Add service function chain {}", sfc);
173         sfcMdsalHelper.addServiceFunctionChain(sfc);
174
175         // Build Service Function Path Builder
176         ServiceFunctionPath sfp = PortChainTranslator.buildServiceFunctionPath(sfc);
177
178         //Write SFP to data store
179         LOG.info("Add service function path {}", sfp);
180         sfcMdsalHelper.addServiceFunctionPath(sfp);
181
182         // TODO This can be removed after oxygen
183         // In Oxygen, RSP will be automatically created from the SFP without
184         // the need to call the rpc, which will be deprecated
185         if (this.rspService != null) {
186             // Build Create Rendered Service Path input
187             CreateRenderedPathInput rpInput = PortChainTranslator.buildCreateRenderedServicePathInput(sfp);
188
189             //Call Create Rendered Service Path RPC call
190             if (rpInput != null) {
191                 LOG.info("Call RPC for creating RSP :{}", rpInput);
192                 Future<RpcResult<CreateRenderedPathOutput>> result =  this.rspService.createRenderedPath(rpInput);
193                 try {
194                     if (result.get() != null) {
195                         CreateRenderedPathOutput output = result.get().getResult();
196                         LOG.debug("RSP created on SFC : {}", output.getName());
197                     } else {
198                         LOG.error("RSP creation failed : {}", rpInput);
199                     }
200                 } catch (InterruptedException | ExecutionException e) {
201                     LOG.error("Error occurred during creating Rendered Service Path using RPC call", e);
202                 }
203             }
204         } else {
205             LOG.error("Rendered Path Service is not available, can't create Rendered Path for Port Chain",
206                     newPortChain);
207         }
208
209         // Add ACLs from flow classifiers
210         processFlowClassifiers(newPortChain, newPortChain.getFlowClassifiers(), sfp.getName().getValue());
211     }
212
213     private void processFlowClassifiers(PortChain pc, List<Uuid> flowClassifiers, String sfpName) {
214         for (Uuid uuid : flowClassifiers) {
215             SfcFlowClassifier fc = neutronMdsalHelper.getNeutronFlowClassifier(uuid);
216             if (fc != null) {
217                 Acl acl = FlowClassifierTranslator.buildAcl(fc, sfpName);
218                 if (acl != null) {
219                     sfcMdsalHelper.addAclFlowClassifier(acl);
220                 } else {
221                     LOG.warn("Acl building failed for flow classifier {}. Traffic might not be redirected to RSP", fc);
222                 }
223
224             } else {
225                 LOG.error("Neutron Flow Classifier {} attached to Port Chain {} is not present in the neutron data "
226                     + "store", uuid, pc);
227             }
228         }
229     }
230 }