2 * Copyright (c) 2013 Plexxi, Inc. and others. All rights reserved.
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
9 package org.opendaylight.affinity.affinity.internal;
12 import org.opendaylight.yang.gen.v1.affinity.rev130925.AffinityService;
13 import org.opendaylight.yang.gen.v1.affinity.rev130925.HostEndpoint;
14 import org.opendaylight.yang.gen.v1.affinity.rev130925.host_endpoint.L2address;
15 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
17 import org.opendaylight.yang.gen.v1.affinity.rev130925.CreategroupInput;
18 import org.opendaylight.yang.gen.v1.affinity.rev130925.AddendpointInput;
20 import java.util.concurrent.Future;
21 import org.opendaylight.controller.sal.common.util.Futures;
22 import org.opendaylight.controller.sal.common.util.Rpcs;
24 import org.opendaylight.yangtools.yang.common.RpcError;
25 import org.opendaylight.yangtools.yang.common.RpcResult;
28 import java.io.FileNotFoundException;
29 import java.io.IOException;
30 import java.io.ObjectInputStream;
31 import java.net.UnknownHostException;
32 import java.net.InetAddress;
33 import java.net.NetworkInterface;
34 import java.net.SocketException;
35 import java.util.ArrayList;
36 import java.util.Collections;
37 import java.util.Date;
38 import java.util.Dictionary;
39 import java.util.EnumSet;
40 import java.util.Enumeration;
41 import java.util.HashMap;
42 import java.util.HashSet;
43 import java.util.List;
45 import java.util.AbstractMap;
47 import java.util.concurrent.ConcurrentHashMap;
48 import java.util.concurrent.ConcurrentMap;
49 import java.util.concurrent.CopyOnWriteArrayList;
50 import java.util.ArrayList;
51 import java.util.EnumSet;
52 import java.util.HashMap;
53 import java.util.HashSet;
54 import java.util.List;
56 import java.util.Map.Entry;
58 import java.util.concurrent.ConcurrentHashMap;
59 import java.util.concurrent.ConcurrentMap;
61 import org.apache.felix.dm.Component;
62 import org.eclipse.osgi.framework.console.CommandInterpreter;
63 import org.eclipse.osgi.framework.console.CommandProvider;
64 import org.opendaylight.controller.clustering.services.CacheConfigException;
65 import org.opendaylight.controller.clustering.services.CacheExistException;
66 import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
67 import org.opendaylight.controller.clustering.services.IClusterContainerServices;
68 import org.opendaylight.controller.clustering.services.IClusterServices;
69 import org.opendaylight.controller.configuration.IConfigurationContainerAware;
70 //import org.opendaylight.controller.forwardingrulesmanager.FlowEntry;
71 //import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager;
72 import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService;
73 import org.opendaylight.controller.sal.flowprogrammer.Flow;
74 import org.opendaylight.controller.sal.utils.IPProtocols;
76 import org.opendaylight.controller.sal.core.IContainer;
77 import org.opendaylight.controller.sal.core.Node;
78 import org.opendaylight.controller.sal.core.Host;
79 import org.opendaylight.controller.sal.core.NodeConnector;
80 import org.opendaylight.controller.sal.core.NodeTable;
81 import org.opendaylight.controller.sal.core.Property;
82 import org.opendaylight.controller.sal.core.UpdateType;
84 import org.opendaylight.controller.sal.flowprogrammer.Flow;
85 import org.opendaylight.controller.sal.match.Match;
86 import org.opendaylight.controller.sal.match.MatchType;
87 import org.opendaylight.controller.sal.match.MatchField;
88 import org.opendaylight.controller.sal.action.Action;
89 import org.opendaylight.controller.sal.action.Output;
90 import org.opendaylight.controller.sal.utils.EtherTypes;
92 import org.opendaylight.controller.sal.reader.FlowOnNode;
93 import org.opendaylight.controller.sal.reader.IReadService;
94 import org.opendaylight.controller.sal.reader.IReadServiceListener;
95 import org.opendaylight.controller.sal.utils.GlobalConstants;
96 import org.opendaylight.controller.sal.utils.IObjectReader;
97 import org.opendaylight.controller.sal.utils.ObjectReader;
98 import org.opendaylight.controller.sal.utils.ObjectWriter;
99 import org.opendaylight.controller.sal.utils.NetUtils;
101 import org.opendaylight.controller.hosttracker.IfIptoHost;
102 import org.opendaylight.controller.sal.utils.Status;
103 import org.opendaylight.controller.sal.utils.StatusCode;
105 import org.opendaylight.controller.sal.utils.ServiceHelper;
106 import org.opendaylight.affinity.affinity.AffinityGroup;
107 import org.opendaylight.affinity.affinity.AffinityLink;
108 import org.opendaylight.affinity.affinity.AffinityIdentifier;
109 import org.opendaylight.affinity.affinity.IAffinityManager;
110 import org.opendaylight.affinity.affinity.IAffinityManagerAware;
112 import org.opendaylight.controller.hosttracker.IfIptoHost;
113 import org.opendaylight.controller.hosttracker.IfNewHostNotify;
114 import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;
115 import org.opendaylight.controller.switchmanager.ISwitchManager;
116 import org.opendaylight.affinity.l2agent.IfL2Agent;
117 import org.opendaylight.affinity.nfchainagent.NFchainAgent;
118 import org.opendaylight.affinity.nfchainagent.NFchainconfig;
119 import org.opendaylight.affinity.affinity.InetAddressMask;
121 import org.slf4j.Logger;
122 import org.slf4j.LoggerFactory;
125 * Affinity configuration.
127 public class AffinityManagerImpl implements IAffinityManager, AffinityService, IfNewHostNotify,
128 IConfigurationContainerAware, IObjectReader, ICacheUpdateAware<Long, String> {
129 private static final Logger log = LoggerFactory.getLogger(AffinityManagerImpl.class);
131 private static String ROOT = GlobalConstants.STARTUPHOME.toString();
132 private static final String SAVE = "Save";
133 private String affinityLinkFileName = null;
134 private String affinityGroupFileName = null;
135 // private IForwardingRulesManager ruleManager;
136 private IFlowProgrammerService programmer = null;
137 private NFchainAgent nfchainagent = null;
139 private ISwitchManager switchManager = null;
140 private IfL2Agent l2agent = null;
141 private IfIptoHost hostTracker = null;
143 private ConcurrentMap<String, AffinityGroup> affinityGroupList;
144 private ConcurrentMap<String, AffinityLink> affinityLinkList;
145 private ConcurrentMap<Long, String> configSaveEvent;
148 private final Set<IAffinityManagerAware> affinityManagerAware = Collections
149 .synchronizedSet(new HashSet<IAffinityManagerAware>());
152 private static boolean hostRefresh = true;
153 private int hostRetryCount = 5;
154 private IClusterContainerServices clusterContainerService = null;
155 private String containerName = GlobalConstants.DEFAULT.toString();
156 private boolean isDefaultContainer = true;
157 private static final int REPLACE_RETRY = 1;
159 private static short REDIRECT_IPSWITCH_PRIORITY = 3;
161 public enum ReasonCode {
162 SUCCESS("Success"), FAILURE("Failure"), INVALID_CONF(
163 "Invalid Configuration"), EXIST("Entry Already Exist"), CONFLICT(
164 "Configuration Conflict with Existing Entry");
166 private final String name;
168 private ReasonCode(String name) {
173 public String toString() {
178 /* Only default container. */
179 public String getContainerName() {
180 return containerName;
183 public void startUp() {
184 // Initialize configuration file names
185 affinityLinkFileName = ROOT + "affinityConfig_link" + this.getContainerName()
187 affinityGroupFileName = ROOT + "affinityConfig_group" + this.getContainerName()
189 log.debug("configuration file names " + affinityLinkFileName + "and " + affinityGroupFileName);
190 // Instantiate cluster synced variables
195 * Read startup and build database if we have not already gotten the
196 * configurations synced from another node
198 if (affinityGroupList.isEmpty() || affinityLinkList.isEmpty()) {
199 loadAffinityConfiguration();
203 public void shutDown() {
206 @SuppressWarnings("deprecation")
207 private void allocateCaches() {
208 if (this.clusterContainerService == null) {
209 this.nonClusterObjectCreate();
210 log.warn("un-initialized clusterContainerService, can't create cache");
214 clusterContainerService.createCache(
215 "affinity.affinityGroupList",
216 EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
217 clusterContainerService.createCache(
218 "affinity.affinityLinkList",
219 EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
220 clusterContainerService.createCache(
221 "affinity.configSaveEvent",
222 EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
223 } catch (CacheConfigException cce) {
224 log.error("\nCache configuration invalid - check cache mode");
225 } catch (CacheExistException ce) {
226 log.error("\nCache already exits - destroy and recreate if needed");
230 @SuppressWarnings({ "unchecked", "deprecation" })
231 private void retrieveCaches() {
232 if (this.clusterContainerService == null) {
233 log.info("un-initialized clusterContainerService, can't retrieve cache");
236 affinityGroupList = (ConcurrentMap<String, AffinityGroup>) clusterContainerService
237 .getCache("affinity.affinityGroupList");
238 if (affinityGroupList == null) {
239 log.error("\nFailed to get cache for affinityGroupList");
241 affinityLinkList = (ConcurrentMap<String, AffinityLink>) clusterContainerService
242 .getCache("affinity.affinityLinkList");
243 if (affinityLinkList == null) {
244 log.error("\nFailed to get cache for affinityLinkList");
247 configSaveEvent = (ConcurrentMap<Long, String>) clusterContainerService
248 .getCache("affinity.configSaveEvent");
249 if (configSaveEvent == null) {
250 log.error("\nFailed to get cache for configSaveEvent");
254 private void nonClusterObjectCreate() {
255 affinityLinkList = new ConcurrentHashMap<String, AffinityLink>();
256 affinityGroupList = new ConcurrentHashMap<String, AffinityGroup>();
257 configSaveEvent = new ConcurrentHashMap<Long, String>();
261 void setHostTracker(IfIptoHost h) {
262 log.info("Setting hosttracker {}", h);
263 this.hostTracker = h;
266 void unsetHostTracker(IfIptoHost h) {
267 if (this.hostTracker.equals(h)) {
268 this.hostTracker = null;
271 /* public void setForwardingRulesManager(
272 IForwardingRulesManager forwardingRulesManager) {
273 log.debug("Setting ForwardingRulesManager");
274 this.ruleManager = forwardingRulesManager;
277 public void unsetForwardingRulesManager(
278 IForwardingRulesManager forwardingRulesManager) {
279 if (this.ruleManager == forwardingRulesManager) {
280 this.ruleManager = null;
284 public void setFlowProgrammerService(IFlowProgrammerService s)
289 public void unsetFlowProgrammerService(IFlowProgrammerService s) {
290 if (this.programmer == s) {
291 this.programmer = null;
295 void setNFchainAgent(NFchainAgent s)
297 log.info("Setting nfchainagent {}", s);
298 this.nfchainagent = s;
301 void unsetNFchainAgent(NFchainAgent s) {
302 if (this.nfchainagent == s) {
303 this.nfchainagent = null;
307 void setL2Agent(IfL2Agent s)
309 log.info("Setting l2agent {}", s);
313 void unsetL2Agent(IfL2Agent s) {
314 if (this.l2agent == s) {
319 void setSwitchManager(ISwitchManager s)
321 this.switchManager = s;
324 void unsetSwitchManager(ISwitchManager s) {
325 if (this.switchManager == s) {
326 this.switchManager = null;
331 public void setForwardingRulesManager(
332 IForwardingRulesManager forwardingRulesManager) {
333 this.ruleManager = forwardingRulesManager;
336 public void unsetForwardingRulesManager(
337 IForwardingRulesManager forwardingRulesManager) {
338 if (this.ruleManager == forwardingRulesManager) {
339 this.ruleManager = null;
344 public Status addAffinityLink(AffinityLink al) {
345 boolean putNewLink = false;
347 if (affinityLinkList.containsKey(al.getName())) {
348 return new Status(StatusCode.CONFLICT,
349 "AffinityLink with the specified name already configured.");
353 AffinityLink alCurr = affinityLinkList.get(al.getName());
354 if (alCurr == null) {
355 if (affinityLinkList.putIfAbsent(al.getName(), al) == null) {
359 putNewLink = affinityLinkList.replace(al.getName(), alCurr, al);
363 String msg = "Cluster conflict: Conflict while adding the subnet " + al.getName();
364 return new Status(StatusCode.CONFLICT, msg);
367 return new Status(StatusCode.SUCCESS);
370 /* public byte [] InetAddressToMAC(InetAddress inetAddr) {
372 log.debug("Find {} -> {} using hostTracker {}", inetAddr, host, hostTracker);
373 byte [] dst_mac = host.getDataLayerAddressBytes();
378 public Status removeAffinityLink(String name) {
379 affinityLinkList.remove(name);
380 return new Status(StatusCode.SUCCESS);
383 public Status removeAffinityLink(AffinityLink al) {
384 AffinityLink alCurr = affinityLinkList.get(al.getName());
385 if (alCurr != null) {
386 affinityLinkList.remove(alCurr);
387 return new Status(StatusCode.SUCCESS);
389 String msg = "Affinity Link with specified name does not exist." + al.getName();
390 return new Status(StatusCode.INTERNALERROR, msg);
395 public AffinityLink getAffinityLink(String linkName) {
396 return affinityLinkList.get(linkName);
400 public List<AffinityLink> getAllAffinityLinks() {
401 return new ArrayList<AffinityLink>(affinityLinkList.values());
405 public Status addAffinityGroup(AffinityGroup ag) {
406 boolean putNewGroup = false;
407 String name = ag.getName();
408 if (affinityGroupList.containsKey(name)) {
409 return new Status(StatusCode.CONFLICT,
410 "AffinityGroup with the specified name already configured.");
412 AffinityGroup agCurr = affinityGroupList.get(name);
413 if (agCurr == null) {
414 if (affinityGroupList.putIfAbsent(name, ag) == null) {
418 putNewGroup = affinityGroupList.replace(name, agCurr, ag);
422 String msg = "Cluster conflict: Conflict while adding the subnet " + name;
423 return new Status(StatusCode.CONFLICT, msg);
426 return new Status(StatusCode.SUCCESS);
429 /* Check for errors. */
431 public Status removeAffinityGroup(String name) {
432 affinityGroupList.remove(name);
433 return new Status(StatusCode.SUCCESS);
437 public AffinityGroup getAffinityGroup(String groupName) {
438 log.debug("getAffinityGroup" + groupName);
439 return affinityGroupList.get(groupName);
443 public List<AffinityGroup> getAllAffinityGroups() {
444 return new ArrayList<AffinityGroup>(affinityGroupList.values());
447 /* Find where this is used. */
449 public Object readObject(ObjectInputStream ois)
450 throws FileNotFoundException, IOException, ClassNotFoundException {
451 // Perform the class deserialization locally, from inside the package
452 // where the class is defined
453 return ois.readObject();
456 @SuppressWarnings("unchecked")
457 private void loadAffinityConfiguration() {
458 ObjectReader objReader = new ObjectReader();
459 ConcurrentMap<String, AffinityGroup> groupList = (ConcurrentMap<String, AffinityGroup>) objReader.read(this, affinityGroupFileName);
460 ConcurrentMap<String, AffinityLink> linkList = (ConcurrentMap<String, AffinityLink>) objReader.read(this, affinityLinkFileName);
463 if (groupList != null) {
464 for (AffinityGroup ag : groupList.values()) {
465 addAffinityGroup(ag);
470 if (linkList != null) {
471 for (AffinityLink al : linkList.values()) {
478 public ArrayList<AffinityIdentifier> getAllElementsByAffinityIdentifier(AffinityGroup ag) {
479 return ag.getAllElements();
483 public List<Host> getAllElementsByHost(AffinityGroup ag) {
484 List<Host> hostList= new ArrayList<Host>();
486 for (AffinityIdentifier h : ag.getAllElements()) {
487 /* TBD: Do not assume this to be an InetAddress. */
489 if (hostTracker != null) {
490 Host host1 = hostTracker.hostFind((InetAddress) h.get());
498 public List<Entry<Host, Host>> getAllFlowsByHost(AffinityLink al) {
499 List<Entry<Host,Host>> hostPairList= new ArrayList<Entry<Host, Host>>();
501 AffinityGroup fromGroup = al.getFromGroup();
502 AffinityGroup toGroup = al.getToGroup();
504 for (AffinityIdentifier h1 : fromGroup.getAllElements()) {
505 for (AffinityIdentifier h2 : toGroup.getAllElements()) {
506 if (hostTracker != null) {
507 Host host1 = hostTracker.hostFind((InetAddress) h1.get());
508 Host host2 = hostTracker.hostFind((InetAddress) h2.get());
509 log.debug("Flow between {}, {}", host1, host2);
510 Entry<Host, Host> hp1=new AbstractMap.SimpleEntry<Host, Host>(host1, host2);
511 hostPairList.add(hp1);
519 public List<Entry<AffinityIdentifier, AffinityIdentifier>> getAllFlowsByAffinityIdentifier(AffinityLink al) {
520 List<Entry<AffinityIdentifier, AffinityIdentifier>> hostPairList= new ArrayList<Entry<AffinityIdentifier, AffinityIdentifier>>();
522 AffinityGroup fromGroup = al.getFromGroup();
523 AffinityGroup toGroup = al.getToGroup();
525 for (AffinityIdentifier h1 : fromGroup.getAllElements()) {
526 for (AffinityIdentifier h2 : toGroup.getAllElements()) {
527 Entry<AffinityIdentifier, AffinityIdentifier> hp1=new AbstractMap.SimpleEntry<AffinityIdentifier, AffinityIdentifier>(h1, h2);
528 log.debug("Adding hostPair {} -> {}", h1, h2);
529 hostPairList.add(hp1);
535 private void notifyHostUpdate(HostNodeConnector host, boolean added) {
539 log.info("Host update received (new = {}).", added);
543 public void notifyHTClient(HostNodeConnector host) {
544 notifyHostUpdate(host, true);
548 public void notifyHTClientHostRemoved(HostNodeConnector host) {
549 notifyHostUpdate(host, false);
554 public Status saveConfiguration() {
555 return saveAffinityConfig();
559 public Status saveAffinityConfig() {
560 // Publish the save config event to the cluster nodes
561 configSaveEvent.put(new Date().getTime(), SAVE);
562 return saveAffinityConfigInternal();
565 public Status saveAffinityConfigInternal() {
566 Status retS = null, retP = null;
567 ObjectWriter objWriter = new ObjectWriter();
569 retS = objWriter.write(new ConcurrentHashMap<String, AffinityLink>(
570 affinityLinkList), affinityLinkFileName);
572 retP = objWriter.write(new ConcurrentHashMap<String, AffinityGroup>(
573 affinityGroupList), affinityGroupFileName);
575 if (retS.isSuccess() && retP.isSuccess()) {
576 return new Status(StatusCode.SUCCESS, "Configuration saved.");
578 return new Status(StatusCode.INTERNALERROR, "Save failed");
583 public void entryCreated(Long key, String cacheName, boolean local) {
587 public void entryUpdated(Long key, String new_value, String cacheName,
588 boolean originLocal) {
589 saveAffinityConfigInternal();
593 public void entryDeleted(Long key, String cacheName, boolean originLocal) {
597 * Function called by the dependency manager when all the required
598 * dependencies are satisfied
602 log.debug("INIT called!");
603 containerName = GlobalConstants.DEFAULT.toString();
608 * Function called by the dependency manager when at least one
609 * dependency become unsatisfied or when the component is shutting
610 * down because for example bundle is being stopped.
614 log.debug("DESTROY called!");
618 * Function called by dependency manager after "init ()" is called
619 * and after the services provided by the class are registered in
620 * the service registry
624 log.debug("START called!");
628 * Function called after registering the service in OSGi service registry.
631 // Retrieve current statistics so we don't have to wait for next refresh
632 IAffinityManager affinityManager = (IAffinityManager) ServiceHelper.getInstance(
633 IAffinityManager.class, this.getContainerName(), this);
634 if (affinityManager != null) {
635 log.debug("STARTED method called!");
640 * Function called by the dependency manager before the services
641 * exported by the component are unregistered, this will be
642 * followed by a "destroy ()" calls
646 log.debug("STOP called!");
649 void setClusterContainerService(IClusterContainerServices s) {
650 log.debug("Cluster Service set for affinity mgr");
651 this.clusterContainerService = s;
654 void unsetClusterContainerService(IClusterContainerServices s) {
655 if (this.clusterContainerService == s) {
656 log.debug("Cluster Service removed for affinity mgr!");
657 this.clusterContainerService = null;
661 /* Add a nfchain config for this affinity link. */
662 List<Flow> getFlowlist(AffinityLink al) {
663 InetAddress from = null, to = null;
665 log.info("get flowlist affinity link = {}", al.getName());
666 List<Flow> flowlist = new ArrayList<Flow>();
667 List<Entry<AffinityIdentifier,AffinityIdentifier>> hostPairList= getAllFlowsByAffinityIdentifier(al);
669 /* Create a Flow for each host pair in the affinity link. */
670 for (Entry<AffinityIdentifier,AffinityIdentifier> hostPair : hostPairList) {
671 log.info("Processing next hostPair {} ", hostPair);
673 Match match = new Match();
677 /* Set source fields. */
678 if (hostPair.getKey().get() instanceof InetAddress) {
679 addr = hostPair.getKey().get();
680 match.setField(new MatchField(MatchType.NW_SRC, (InetAddress) addr, null));
681 } else if (hostPair.getKey().get() instanceof InetAddressMask) {
682 addrmask = hostPair.getKey().get();
683 InetAddress faddr = ((InetAddressMask) addrmask).getNetworkAddress();
684 InetAddress fmask = NetUtils.getInetNetworkMask((int) ((InetAddressMask) addrmask).getMask(), false);
685 match.setField(new MatchField(MatchType.NW_SRC, faddr, fmask));
687 /* xxx mac address ... */
689 /* Set destination fields. */
690 if (hostPair.getValue().get() instanceof InetAddress) {
691 addr = (InetAddress) hostPair.getValue().get();
692 match.setField(new MatchField(MatchType.NW_DST, addr, null));
693 } else if (hostPair.getValue().get() instanceof InetAddressMask) {
694 addrmask = (InetAddressMask) hostPair.getValue().get();
695 InetAddress taddr = ((InetAddressMask) addrmask).getNetworkAddress();
696 InetAddress tmask = NetUtils.getInetNetworkMask((int) ((InetAddressMask) addrmask).getMask(), false);
697 match.setField(new MatchField(MatchType.NW_DST, taddr, tmask));
699 /* xxx mac address ... */
701 /* Set other fields. */
702 match.setField(MatchType.DL_TYPE, EtherTypes.IPv4.shortValue());
703 Flow flow = new Flow(match, null);
704 flow.setPriority(REDIRECT_IPSWITCH_PRIORITY);
710 /* From affinity link, create a nfc config. Pass this nfc config to nfchainagent. */
711 public Status addNfchain(AffinityLink al) {
712 List<Flow> flowlist = getFlowlist(al);
713 InetAddress waypoint = NetUtils.parseInetAddress(al.getWaypoint());
714 NFchainconfig nfcc = new NFchainconfig(al.getName(), flowlist, waypoint);
715 String key = al.getName();
716 nfchainagent.addNfchain(key, nfcc);
717 log.info("Added nfchain {}", al.getName());
718 return new Status(StatusCode.SUCCESS);
721 public Status enableRedirect(AffinityLink al) throws Exception {
722 String nfccname = al.getName();
723 return nfchainagent.enable(nfccname);
726 public Status disableRedirect(AffinityLink al) throws Exception {
727 String nfccname = al.getName();
728 return nfchainagent.disable(nfccname);
731 public Status removeNfchain(AffinityLink al) throws Exception {
732 String nfccname = al.getName();
733 return nfchainagent.removeNfchain(nfccname);
737 /* public methods for the yang service. */
738 public Future<RpcResult<Void>> creategroup(CreategroupInput input) {
739 AffinityGroup ag1 = new AffinityGroup(input.getName());
741 /* Correctly translate between status fields. */
742 Status ret = addAffinityGroup(ag1);
743 RpcResult<Void> result = Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
744 return Futures.immediateFuture(result);
747 public Future<RpcResult<Void>> addendpoint(AddendpointInput input) {
748 AffinityGroup ag = getAffinityGroup(input.getGroupname());
749 RpcResult<Void> result;
752 HostEndpoint endpoint = input.getEndpoint();
753 L2address l2address = endpoint.getL2address();
754 Ipv4Prefix l3address = endpoint.getL3address();
756 /* ag.addL2address(); */
757 ag.addInetMask(l3address.toString());
758 result = Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
760 result = Rpcs.<Void> getRpcResult(false, null, Collections.<RpcError> emptySet());
762 return Futures.immediateFuture(result);