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