cc5387dcf38109109d354fccecb48e206d674477
[netvirt.git] / openstack / net-virt-providers / src / main / java / org / opendaylight / ovsdb / openstack / netvirt / providers / openflow13 / services / LoadBalancerService.java
1 /*
2  * Copyright (C) 2014 SDN Hub, LLC.
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  * Authors : Srini Seetharaman, Madhu Venugopal
9  */
10 package org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services;
11
12 import java.math.BigInteger;
13 import java.util.List;
14 import java.util.Map;
15
16 import org.opendaylight.ovsdb.openstack.netvirt.NetworkHandler;
17 import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
18 import org.opendaylight.ovsdb.openstack.netvirt.api.L3ForwardingProvider;
19 import org.opendaylight.ovsdb.openstack.netvirt.api.LoadBalancerConfiguration;
20 import org.opendaylight.ovsdb.openstack.netvirt.api.LoadBalancerConfiguration.LoadBalancerPoolMember;
21 import org.opendaylight.ovsdb.openstack.netvirt.api.LoadBalancerProvider;
22 import org.opendaylight.ovsdb.openstack.netvirt.api.Status;
23 import org.opendaylight.ovsdb.openstack.netvirt.api.StatusCode;
24 import org.opendaylight.ovsdb.openstack.netvirt.providers.ConfigInterface;
25 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
26 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
27 import org.opendaylight.ovsdb.utils.mdsal.openflow.ActionUtils;
28 import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4Builder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
45 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg1;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg2;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxRegCaseBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.OfjNxHashFields;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.OfjNxMpAlgorithm;
56 import org.osgi.framework.BundleContext;
57 import org.osgi.framework.ServiceReference;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
60
61 import com.google.common.collect.Lists;
62
63 public class LoadBalancerService extends AbstractServiceInstance implements LoadBalancerProvider, ConfigInterface {
64
65     private static final Logger logger = LoggerFactory.getLogger(LoadBalancerProvider.class);
66     private static final int DEFAULT_FLOW_PRIORITY = 32768;
67     private static final Long FIRST_PASS_REGA_MATCH_VALUE = 0L;
68     private static final Long SECOND_PASS_REGA_MATCH_VALUE = 1L;
69
70     private static final Class<? extends NxmNxReg> REG_FIELD_A = NxmNxReg1.class;
71     private static final Class<? extends NxmNxReg> REG_FIELD_B = NxmNxReg2.class;
72
73     public LoadBalancerService() {
74         super(Service.LOAD_BALANCER);
75     }
76
77     public LoadBalancerService(Service service) {
78         super(service);
79     }
80
81     /**
82      * When this method is called, we do the following for minimizing flow updates:
83      * 1. Overwrite the solo multipath rule that applies to all members
84      * 2. Append second pass rule for the header rewriting specific to this member
85      * 3. Append reverse rules specific to this member
86      */
87     @Override
88     public Status programLoadBalancerPoolMemberRules(Node node,
89                                                      LoadBalancerConfiguration lbConfig, LoadBalancerPoolMember member,
90                                                      org.opendaylight.ovsdb.openstack.netvirt.api.Action action) {
91         if (lbConfig == null || member == null) {
92             logger.error("Null value for LB config {} or Member {}", lbConfig, member);
93             return new Status(StatusCode.BADREQUEST);
94         }
95         if (!lbConfig.isValid()) {
96             logger.error("LB config is invalid: {}", lbConfig);
97             return new Status(StatusCode.BADREQUEST);
98         }
99         logger.debug("Performing {} rules for member {} with index {} on LB with VIP {} and total members {}",
100                 action, member.getIP(), member.getIndex(), lbConfig.getVip(), lbConfig.getMembers().size());
101
102         NodeBuilder nodeBuilder = new NodeBuilder();
103         nodeBuilder.setId(new NodeId(Constants.OPENFLOW_NODE_PREFIX + node.getNodeId().getValue()));
104         nodeBuilder.setKey(new NodeKey(nodeBuilder.getId()));
105
106         //Update the multipath rule
107         manageLoadBalancerVIPRulesFirstPass(nodeBuilder, lbConfig, true);
108
109         if (action.equals(org.opendaylight.ovsdb.openstack.netvirt.api.Action.ADD)) {
110             manageLoadBalancerMemberVIPRulesSecondPass(nodeBuilder, lbConfig, member, true);
111             manageLoadBalancerMemberReverseRules(nodeBuilder, lbConfig, member, true);
112             return new Status(StatusCode.SUCCESS);
113         }
114         /* TODO: Delete single member.
115          * For now, removing a member requires deleting the full LB instance and re-adding
116          */
117         return new Status(StatusCode.NOTIMPLEMENTED);
118     }
119
120     /**
121      * When this method is called, we perform the following:
122      * 1. Write the solo multipath rule that applies to all members
123      * 2. Append second pass rules for the header rewriting for all members
124      * 3. Append reverse rules for all the members, specific to the protocol/port
125      */
126     @Override
127     public Status programLoadBalancerRules(Node node, LoadBalancerConfiguration lbConfig,
128                                            org.opendaylight.ovsdb.openstack.netvirt.api.Action action) {
129         if (lbConfig == null) {
130             logger.error("LB config is invalid: {}", lbConfig);
131             return new Status(StatusCode.BADREQUEST);
132         }
133         if (!lbConfig.isValid()) {
134             logger.error("LB config is invalid: {}", lbConfig);
135             return new Status(StatusCode.BADREQUEST);
136         }
137         logger.debug("Performing {} rules for VIP {} and {} members", action, lbConfig.getVip(), lbConfig.getMembers().size());
138
139         NodeBuilder nodeBuilder = new NodeBuilder();
140         nodeBuilder.setId(new NodeId(Constants.OPENFLOW_NODE_PREFIX + node.getNodeId().getValue()));
141         nodeBuilder.setKey(new NodeKey(nodeBuilder.getId()));
142
143         if (action.equals(org.opendaylight.ovsdb.openstack.netvirt.api.Action.ADD)) {
144             manageLoadBalancerVIPRulesFirstPass(nodeBuilder, lbConfig, true);
145             manageLoadBalancerVIPRulesSecondPass(nodeBuilder, lbConfig, true);
146             manageLoadBalancerReverseRules(nodeBuilder, lbConfig, true);
147             return new Status(StatusCode.SUCCESS);
148         }
149         else if (action.equals(org.opendaylight.ovsdb.openstack.netvirt.api.Action.DELETE)) {
150             manageLoadBalancerVIPRulesFirstPass(nodeBuilder, lbConfig, false);
151             manageLoadBalancerVIPRulesSecondPass(nodeBuilder, lbConfig, false);
152             manageLoadBalancerReverseRules(nodeBuilder, lbConfig, false);
153             return new Status(StatusCode.SUCCESS);
154         }
155
156         return new Status(StatusCode.NOTIMPLEMENTED);
157     }
158
159     /**
160      * Method to insert/remove default rule for traffic destined to the VIP and no
161      * server selection performed yet
162      * @param nodeBuilder NodeBuilder
163      * @param lbConfig LoadBalancerConfiguration
164      * @param write Boolean to indicate of the flow is to be inserted or removed
165      */
166     private void manageLoadBalancerVIPRulesFirstPass(NodeBuilder nodeBuilder, LoadBalancerConfiguration lbConfig, boolean write) {
167         MatchBuilder matchBuilder = new MatchBuilder();
168         FlowBuilder flowBuilder = new FlowBuilder();
169
170         // Match Tunnel-ID, VIP, and Reg0==0
171         if (lbConfig.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN) ||
172             lbConfig.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE))
173             MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(lbConfig.getProviderSegmentationId()));
174         else if (lbConfig.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN))
175             MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(lbConfig.getProviderSegmentationId())), true);
176         else
177             return; //Should not get here. TODO: Other types
178
179         MatchUtils.createDstL3IPv4Match(matchBuilder, MatchUtils.iPv4PrefixFromIPv4Address(lbConfig.getVip()));
180         MatchUtils.addNxRegMatch(matchBuilder, new MatchUtils.RegMatch(REG_FIELD_A, FIRST_PASS_REGA_MATCH_VALUE));
181
182         String flowId = "LOADBALANCER_FORWARD_FLOW1_" + lbConfig.getProviderSegmentationId() + "_" + lbConfig.getVip();
183         flowBuilder.setId(new FlowId(flowId));
184         FlowKey key = new FlowKey(new FlowId(flowId));
185         flowBuilder.setMatch(matchBuilder.build());
186         flowBuilder.setPriority(DEFAULT_FLOW_PRIORITY);
187         flowBuilder.setBarrier(true);
188         flowBuilder.setTableId(this.getTable());
189         flowBuilder.setKey(key);
190         flowBuilder.setFlowName(flowId);
191         flowBuilder.setHardTimeout(0);
192         flowBuilder.setIdleTimeout(0);
193
194         if (write) {
195             // Create the OF Actions and Instructions
196             InstructionsBuilder isb = new InstructionsBuilder();
197
198             // Instructions List Stores Individual Instructions
199             List<Instruction> instructions = Lists.newArrayList();
200
201             List<Action> actionList = Lists.newArrayList();
202
203             ActionBuilder ab = new ActionBuilder();
204             ab.setAction(ActionUtils.nxLoadRegAction(new DstNxRegCaseBuilder().setNxReg(REG_FIELD_A).build(),
205                     BigInteger.valueOf(SECOND_PASS_REGA_MATCH_VALUE)));
206             ab.setOrder(0);
207             ab.setKey(new ActionKey(0));
208             actionList.add(ab.build());
209
210             ab = new ActionBuilder();
211             ab.setAction(ActionUtils.nxMultipathAction(OfjNxHashFields.NXHASHFIELDSSYMMETRICL4,
212                     0, OfjNxMpAlgorithm.NXMPALGMODULON,
213                     lbConfig.getMembers().size()-1, //By Nicira-Ext spec, this field is max_link minus 1
214                     0L, new DstNxRegCaseBuilder().setNxReg(REG_FIELD_B).build(),
215                     0, 31));
216             ab.setOrder(1);
217             ab.setKey(new ActionKey(1));
218             actionList.add(ab.build());
219
220             ab = new ActionBuilder();
221             ab.setAction(ActionUtils.nxResubmitAction(null, this.getTable()));
222             ab.setOrder(2);
223             ab.setKey(new ActionKey(2));
224             actionList.add(ab.build());
225
226             // Create an Apply Action
227             ApplyActionsBuilder aab = new ApplyActionsBuilder();
228             aab.setAction(actionList);
229             InstructionBuilder ib = new InstructionBuilder();
230             ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
231
232             // Call the InstructionBuilder Methods Containing Actions
233             ib.setOrder(0);
234             ib.setKey(new InstructionKey(0));
235             instructions.add(ib.build());
236
237             // Add InstructionBuilder to the Instruction(s)Builder List
238             isb.setInstruction(instructions);
239
240             // Add InstructionsBuilder to FlowBuilder
241             flowBuilder.setInstructions(isb.build());
242
243             writeFlow(flowBuilder, nodeBuilder);
244
245         } else {
246             removeFlow(flowBuilder, nodeBuilder);
247         }
248     }
249
250     /*
251      * Method to program each rule that matches on Reg0 and Reg1 to insert appropriate header rewriting
252      * rules for all members. This function calls manageLoadBalancerMemberVIPRulesSecondPass in turn.
253      * @param nodeBuilder Node to insert rule to
254      * @param lbConfig Configuration for this LoadBalancer instance
255      * @param write Boolean to indicate of the flow is to be inserted or removed
256      */
257     private void manageLoadBalancerVIPRulesSecondPass(NodeBuilder nodeBuilder, LoadBalancerConfiguration lbConfig, boolean write) {
258         for(Map.Entry<String, LoadBalancerPoolMember> entry : lbConfig.getMembers().entrySet()){
259             manageLoadBalancerMemberVIPRulesSecondPass(nodeBuilder, lbConfig, entry.getValue(), write);
260         }
261     }
262
263     private void manageLoadBalancerMemberVIPRulesSecondPass(NodeBuilder nodeBuilder, LoadBalancerConfiguration lbConfig, LoadBalancerPoolMember member, boolean write) {
264         String vip = lbConfig.getVip();
265
266         MatchBuilder matchBuilder = new MatchBuilder();
267         FlowBuilder flowBuilder = new FlowBuilder();
268
269         // Match Tunnel-ID, VIP, Reg0==1 and Reg1==Index of member
270         if (lbConfig.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN) ||
271             lbConfig.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE))
272             MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(lbConfig.getProviderSegmentationId()));
273         else if (lbConfig.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN))
274             MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(lbConfig.getProviderSegmentationId())), true);
275         else
276             return; //Should not get here. TODO: Other types
277
278         MatchUtils.createDstL3IPv4Match(matchBuilder, MatchUtils.iPv4PrefixFromIPv4Address(vip));
279         MatchUtils.addNxRegMatch(matchBuilder, new MatchUtils.RegMatch(REG_FIELD_A, SECOND_PASS_REGA_MATCH_VALUE),
280                                                new MatchUtils.RegMatch(REG_FIELD_B, (long)member.getIndex()));
281
282         String flowId = "LOADBALANCER_FORWARD_FLOW2_" + lbConfig.getProviderSegmentationId() + "_" +
283                         vip + "_" + member.getIP();
284         flowBuilder.setId(new FlowId(flowId));
285         FlowKey key = new FlowKey(new FlowId(flowId));
286         flowBuilder.setMatch(matchBuilder.build());
287         flowBuilder.setPriority(DEFAULT_FLOW_PRIORITY+1);
288         flowBuilder.setBarrier(true);
289         flowBuilder.setTableId(this.getTable());
290         flowBuilder.setKey(key);
291         flowBuilder.setFlowName(flowId);
292         flowBuilder.setHardTimeout(0);
293         flowBuilder.setIdleTimeout(0);
294
295         if (write) {
296             // Create the OF Actions and Instructions
297             InstructionsBuilder isb = new InstructionsBuilder();
298
299             // Instructions List Stores Individual Instructions
300             List<Instruction> instructions = Lists.newArrayList();
301
302             List<Action> actionList = Lists.newArrayList();
303             ActionBuilder ab = new ActionBuilder();
304             ab.setAction(ActionUtils.setDlDstAction(new MacAddress(member.getMAC())));
305             ab.setOrder(0);
306             ab.setKey(new ActionKey(0));
307             actionList.add(ab.build());
308
309             ab = new ActionBuilder();
310             Ipv4Builder ipb = new Ipv4Builder().setIpv4Address(MatchUtils.iPv4PrefixFromIPv4Address(member.getIP()));
311             ab.setAction(ActionUtils.setNwDstAction(ipb.build()));
312             ab.setOrder(1);
313             ab.setKey(new ActionKey(1));
314             actionList.add(ab.build());
315
316             // Create an Apply Action
317             ApplyActionsBuilder aab = new ApplyActionsBuilder();
318             aab.setAction(actionList);
319
320             // Call the InstructionBuilder Methods Containing Actions
321             InstructionBuilder ib = new InstructionBuilder();
322             ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
323             ib.setOrder(0);
324             ib.setKey(new InstructionKey(0));
325             instructions.add(ib.build());
326
327             // Call the InstructionBuilder Methods Containing Actions
328             ib = this.getMutablePipelineInstructionBuilder();
329             ib.setOrder(1);
330             ib.setKey(new InstructionKey(1));
331             instructions.add(ib.build());
332
333             // Add InstructionBuilder to the Instruction(s)Builder List
334             isb.setInstruction(instructions);
335
336             // Add InstructionsBuilder to FlowBuilder
337             flowBuilder.setInstructions(isb.build());
338
339             writeFlow(flowBuilder, nodeBuilder);
340
341         } else {
342             removeFlow(flowBuilder, nodeBuilder);
343         }
344     }
345
346     /**
347      * Method to program all reverse rules that matches member {IP, Protocol, Port} for all members.
348      * This function calls manageLoadBalancerMemberReverseRules in turn.
349      * @param nodeBuilder Node to insert rule to
350      * @param lbConfig Configuration for this LoadBalancer instance
351      */
352     private void manageLoadBalancerReverseRules(NodeBuilder nodeBuilder, LoadBalancerConfiguration lbConfig, boolean write) {
353         for(Map.Entry<String, LoadBalancerPoolMember> entry : lbConfig.getMembers().entrySet()){
354             manageLoadBalancerMemberReverseRules(nodeBuilder, lbConfig, entry.getValue(), write);
355         }
356     }
357
358     private void manageLoadBalancerMemberReverseRules(NodeBuilder nodeBuilder, LoadBalancerConfiguration lbConfig,
359             LoadBalancerPoolMember member, boolean write) {
360
361         String vip = lbConfig.getVip();
362         String vmac = lbConfig.getVmac();
363
364         MatchBuilder matchBuilder = new MatchBuilder();
365         FlowBuilder flowBuilder = new FlowBuilder();
366
367         // Match Tunnel-ID, MemberIP, and Protocol/Port
368         if (lbConfig.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN) ||
369                    lbConfig.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE))
370             MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(lbConfig.getProviderSegmentationId()));
371         else if (lbConfig.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN))
372             MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(lbConfig.getProviderSegmentationId())), true);
373         else
374             return; //Should not get here. TODO: Other types
375
376         MatchUtils.createSrcL3IPv4Match(matchBuilder, MatchUtils.iPv4PrefixFromIPv4Address(member.getIP()));
377         MatchUtils.createSetSrcTcpMatch(matchBuilder, new PortNumber(member.getPort()));
378
379         String flowId = "LOADBALANCER_REVERSE_FLOW_" + lbConfig.getProviderSegmentationId() +
380                         vip + "_" + member.getIP();
381         flowBuilder.setId(new FlowId(flowId));
382         FlowKey key = new FlowKey(new FlowId(flowId));
383         flowBuilder.setMatch(matchBuilder.build());
384         flowBuilder.setPriority(DEFAULT_FLOW_PRIORITY);
385         flowBuilder.setBarrier(true);
386         flowBuilder.setTableId(this.getTable());
387         flowBuilder.setKey(key);
388         flowBuilder.setFlowName(flowId);
389         flowBuilder.setHardTimeout(0);
390         flowBuilder.setIdleTimeout(0);
391
392         if (write) {
393             // Create the OF Actions and Instructions
394             InstructionsBuilder isb = new InstructionsBuilder();
395
396             // Instructions List Stores Individual Instructions
397             List<Instruction> instructions = Lists.newArrayList();
398
399             List<Action> actionList = Lists.newArrayList();
400             ActionBuilder ab = new ActionBuilder();
401             Ipv4Builder ipb = new Ipv4Builder().setIpv4Address(MatchUtils.iPv4PrefixFromIPv4Address(vip));
402             ab.setAction(ActionUtils.setNwSrcAction(ipb.build()));
403             ab.setOrder(0);
404             ab.setKey(new ActionKey(0));
405             actionList.add(ab.build());
406
407             /* If a dummy MAC is assigned to the VIP, we use that as the
408              * source MAC for the reverse traffic.
409              */
410             if (vmac != null) {
411                 ab = new ActionBuilder();
412                 ab.setAction(ActionUtils.setDlDstAction(new MacAddress(vmac)));
413                 ab.setOrder(1);
414                 ab.setKey(new ActionKey(1));
415                 actionList.add(ab.build());
416             }
417
418             // Create an Apply Action
419             ApplyActionsBuilder aab = new ApplyActionsBuilder();
420             aab.setAction(actionList);
421
422             // Call the InstructionBuilder Methods Containing Actions
423             InstructionBuilder ib = new InstructionBuilder();
424             ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
425             ib.setOrder(0);
426             ib.setKey(new InstructionKey(0));
427             instructions.add(ib.build());
428
429             // Call the InstructionBuilder Methods Containing Actions
430             ib = this.getMutablePipelineInstructionBuilder();
431             ib.setOrder(1);
432             ib.setKey(new InstructionKey(1));
433             instructions.add(ib.build());
434
435             // Add InstructionBuilder to the Instruction(s)Builder List
436             isb.setInstruction(instructions);
437
438             // Add InstructionsBuilder to FlowBuilder
439             flowBuilder.setInstructions(isb.build());
440
441             writeFlow(flowBuilder, nodeBuilder);
442
443         } else {
444             removeFlow(flowBuilder, nodeBuilder);
445         }
446     }
447
448     @Override
449     public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
450         super.setOrchestrator(bundleContext.getServiceReference(LoadBalancerProvider.class.getName()), this);
451     }
452
453     @Override
454     public void setDependencies(Object impl) {
455
456     }
457 }