d539cfc15e49c272726896c3fd1ee4006ba31a7b
[affinity.git] / analytics / northbound / src / main / java / org / opendaylight / affinity / analytics / northbound / AnalyticsNorthbound.java
1 /*
2  * Copyright (c) 2013 Plexxi, 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.affinity.analytics.northbound;
10
11 import java.net.InetAddress;
12 import java.net.UnknownHostException;
13 import java.util.List;
14 import java.util.Set;
15 import java.util.Map;
16
17 import javax.ws.rs.GET;
18 import javax.ws.rs.Path;
19 import javax.ws.rs.PathParam;
20 import javax.ws.rs.Produces;
21 import javax.ws.rs.core.Context;
22 import javax.ws.rs.core.MediaType;
23 import javax.ws.rs.core.SecurityContext;
24
25 import org.codehaus.enunciate.jaxrs.ResponseCode;
26 import org.codehaus.enunciate.jaxrs.StatusCodes;
27 import org.codehaus.enunciate.jaxrs.TypeHint;
28
29 import org.opendaylight.affinity.affinity.AffinityLink;
30 import org.opendaylight.affinity.affinity.IAffinityManager;
31 import org.opendaylight.affinity.analytics.IAnalyticsManager;
32 import org.opendaylight.controller.containermanager.IContainerManager;
33 import org.opendaylight.controller.hosttracker.IfIptoHost;
34 import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;
35 import org.opendaylight.controller.northbound.commons.RestMessages;
36 import org.opendaylight.controller.northbound.commons.exception.*;
37 import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
38 import org.opendaylight.controller.sal.authorization.Privilege;
39 import org.opendaylight.controller.sal.core.Host;
40 import org.opendaylight.controller.sal.utils.GlobalConstants;
41 import org.opendaylight.controller.sal.utils.IPProtocols;
42 import org.opendaylight.controller.sal.utils.ServiceHelper;
43 import org.opendaylight.controller.switchmanager.ISwitchManager;
44
45 /**
46  * Northbound APIs that returns various Analytics exposed by the Southbound
47  * plugins such as Openflow.
48  *
49  * <br>
50  * <br>
51  * Authentication scheme : <b>HTTP Basic</b><br>
52  * Authentication realm : <b>opendaylight</b><br>
53  * Transport : <b>HTTP and HTTPS</b><br>
54  * <br>
55  * HTTPS Authentication is disabled by default. Administrator can enable it in
56  * tomcat-server.xml after adding a proper keystore / SSL certificate from a
57  * trusted authority.<br>
58  * More info :
59  * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
60  *
61  */
62 @Path("/")
63 public class AnalyticsNorthbound {
64
65     private String username;
66
67     @Context
68     public void setSecurityContext(SecurityContext context) {
69         username = context.getUserPrincipal().getName();
70     }
71
72     protected String getUserName() {
73         return username;
74     }
75
76     private IAnalyticsManager getAnalyticsService(String containerName) {
77         IContainerManager containerManager = (IContainerManager) ServiceHelper.getGlobalInstance(IContainerManager.class, this);
78         if (containerManager == null)
79             throw new ServiceUnavailableException("Container " + RestMessages.SERVICEUNAVAILABLE.toString());
80
81         boolean found = false;
82         List<String> containerNames = containerManager.getContainerNames();
83         for (String cName : containerNames)
84             if (cName.trim().equalsIgnoreCase(containerName.trim()))
85                 found = true;
86         if (found == false)
87             throw new ResourceNotFoundException(containerName + " " + RestMessages.NOCONTAINER.toString());
88
89         IAnalyticsManager analyticsManager = (IAnalyticsManager) ServiceHelper.getInstance(IAnalyticsManager.class, containerName, this);
90         if (analyticsManager == null)
91             throw new ServiceUnavailableException("Analytics " + RestMessages.SERVICEUNAVAILABLE.toString());
92         return analyticsManager;
93     }
94
95     /**
96      * @param containerName: Name of the Container
97      * @param dataLayerAddr: DataLayerAddress for the host
98      * @param networkAddr: NetworkAddress for the host
99      * @return Statistics for a (src, dst) pair.
100      */
101     @Path("/{containerName}/hoststats/{srcNetworkAddr}/{dstNetworkAddr}")
102     @GET
103     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
104     @TypeHint(Statistics.class)
105     @StatusCodes({
106             @ResponseCode(code = 200, condition = "Operation successful"),
107             @ResponseCode(code = 404, condition = "The containerName is not found"),
108             @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
109     public Statistics getHostStatistics(
110            @PathParam("containerName") String containerName,
111            @PathParam("srcNetworkAddr") String srcNetworkAddr,
112            @PathParam("dstNetworkAddr") String dstNetworkAddr) {
113         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this))
114             throw new UnauthorizedException("User is not authorized to perform this operation on container " + containerName);
115         handleDefaultDisabled(containerName);
116
117         IAnalyticsManager analyticsManager = getAnalyticsService(containerName);
118         if (analyticsManager == null)
119             throw new ServiceUnavailableException("Analytics " + RestMessages.SERVICEUNAVAILABLE.toString());
120
121         Host srcHost = handleHostAvailability(containerName, srcNetworkAddr);
122         Host dstHost = handleHostAvailability(containerName, dstNetworkAddr);
123         long byteCount = analyticsManager.getByteCount(srcHost, dstHost);
124         double bitRate = analyticsManager.getBitRate(srcHost, dstHost);
125
126         return new Statistics(byteCount, bitRate);
127     }
128
129     /**
130      * @param containerName: Name of the Container
131      * @param srcIP: Source IP
132      * @param dstIP: Destination IP
133      * @param protocol: IP protocol
134      * @return Statistics for a (src, dst) pair and a particular protocol
135      */
136     @Path("/{containerName}/hoststats/{srcIP}/{dstIP}/{protocol}")
137     @GET
138     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
139     @TypeHint(Statistics.class)
140     @StatusCodes({
141         @ResponseCode(code = 200, condition = "Operation successful"),
142         @ResponseCode(code = 404, condition = "The containerName is not found"),
143         @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
144     public Statistics getHostStatistics(
145         @PathParam("containerName") String containerName,
146         @PathParam("srcIP") String srcIP,
147         @PathParam("dstIP") String dstIP,
148         @PathParam("protocol") String protocol) {
149         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this))
150             throw new UnauthorizedException("User is not authorized to perform this operation on container " + containerName);
151         handleDefaultDisabled(containerName);
152
153         IAnalyticsManager analyticsManager = getAnalyticsService(containerName);
154         if (analyticsManager == null)
155             throw new ServiceUnavailableException("Analytics " + RestMessages.SERVICEUNAVAILABLE.toString());
156
157         Host srcHost = handleHostAvailability(containerName, srcIP);
158         Host dstHost = handleHostAvailability(containerName, dstIP);
159         long byteCount = analyticsManager.getByteCount(srcHost, dstHost, IPProtocols.getProtocolNumberByte(protocol));
160         double bitRate = analyticsManager.getBitRate(srcHost, dstHost, IPProtocols.getProtocolNumberByte(protocol));
161
162         return new Statistics(byteCount, bitRate);
163     }
164
165     /**
166      * @param containerName: Name of the Container
167      * @param srcIP: Source IP
168      * @param dstIP: Destination IP
169      * @return All statistics for a (src, dst) pair
170      */
171     @Path("/{containerName}/hoststats/{srcIP}/{dstIP}/all")
172     @GET
173     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
174     @TypeHint(AllStatistics.class)
175     @StatusCodes({
176         @ResponseCode(code = 200, condition = "Operation successful"),
177         @ResponseCode(code = 404, condition = "The containerName is not found"),
178         @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
179     public AllStatistics getAllHostStatistics(
180         @PathParam("containerName") String containerName,
181         @PathParam("srcIP") String srcIP,
182         @PathParam("dstIP") String dstIP) {
183         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this))
184             throw new UnauthorizedException("User is not authorized to perform this operation on container " + containerName);
185         handleDefaultDisabled(containerName);
186
187         IAnalyticsManager analyticsManager = getAnalyticsService(containerName);
188         if (analyticsManager == null)
189             throw new ServiceUnavailableException("Analytics " + RestMessages.SERVICEUNAVAILABLE.toString());
190
191         Host srcHost = handleHostAvailability(containerName, srcIP);
192         Host dstHost = handleHostAvailability(containerName, dstIP);
193         Map<Byte, Long> byteCounts = analyticsManager.getAllByteCounts(srcHost, dstHost);
194         Map<Byte, Double> bitRates = analyticsManager.getAllBitRates(srcHost, dstHost);
195         return new AllStatistics(byteCounts, bitRates);
196     }
197
198     /**
199      * @param containerName: Name of the Container
200      * @param linkName: AffinityLink name
201      * @return Statistics for an affinity link
202      */
203     @Path("/{containerName}/affinitylinkstats/{linkName}")
204     @GET
205     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
206     @TypeHint(Statistics.class)
207     @StatusCodes({
208         @ResponseCode(code = 200, condition = "Operation successful"),
209         @ResponseCode(code = 404, condition = "The containerName is not found"),
210         @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
211    public Statistics getAffinityLinkStatistics(
212         @PathParam("containerName") String containerName,
213         @PathParam("linkName") String affinityLinkName) {
214         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this))
215             throw new UnauthorizedException("User is not authorized to perform this operation on container " + containerName);
216         handleDefaultDisabled(containerName);
217
218         IAnalyticsManager analyticsManager = getAnalyticsService(containerName);
219         if (analyticsManager == null)
220             throw new ServiceUnavailableException("Analytics " + RestMessages.SERVICEUNAVAILABLE.toString());
221
222         AffinityLink al = handleAffinityLinkAvailability(containerName, affinityLinkName);
223         long byteCount = analyticsManager.getByteCount(al);
224         double bitRate = analyticsManager.getBitRate(al);
225
226         return new Statistics(byteCount, bitRate);
227     }
228
229     /**
230      * @param containerName: Name of the Container
231      * @param linkName: AffinityLink name
232      * @param protocol: IP Protocol
233      * @return Statistics for an affinity link and a particular protocol
234      */
235     @Path("/{containerName}/affinitylinkstats/{linkName}/{protocol}")
236     @GET
237     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
238     @TypeHint(Statistics.class)
239     @StatusCodes({
240         @ResponseCode(code = 200, condition = "Operation successful"),
241         @ResponseCode(code = 404, condition = "The containerName is not found"),
242         @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
243     public Statistics getAffinityLinkStatistics(
244         @PathParam("containerName") String containerName,
245         @PathParam("linkName") String affinityLinkName,
246         @PathParam("protocol") String protocol) {
247         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this))
248             throw new UnauthorizedException("User is not authorized to perform this operation on container " + containerName);
249         handleDefaultDisabled(containerName);
250
251         IAnalyticsManager analyticsManager = getAnalyticsService(containerName);
252         if (analyticsManager == null)
253             throw new ServiceUnavailableException("Analytics " + RestMessages.SERVICEUNAVAILABLE.toString());
254
255         AffinityLink al = handleAffinityLinkAvailability(containerName, affinityLinkName);
256         long byteCount = analyticsManager.getByteCount(al, IPProtocols.getProtocolNumberByte(protocol));
257         double bitRate = analyticsManager.getBitRate(al, IPProtocols.getProtocolNumberByte(protocol));
258
259         return new Statistics(byteCount, bitRate);
260     }
261
262     /**
263      * @param containerName: Name of the Container
264      * @param linkName: AffinityLink name
265      * @return All statistics for an affinity link
266      */
267     @Path("/{containerName}/affinitylinkstats/{linkName}/all")
268     @GET
269     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
270     @TypeHint(AllStatistics.class)
271     @StatusCodes({
272         @ResponseCode(code = 200, condition = "Operation successful"),
273         @ResponseCode(code = 404, condition = "The containerName is not found"),
274         @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
275     public AllStatistics getAllAffinityLinkStatistics(
276         @PathParam("containerName") String containerName,
277         @PathParam("linkName") String affinityLinkName) {
278         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this))
279             throw new UnauthorizedException("User is not authorized to perform this operation on container " + containerName);
280         handleDefaultDisabled(containerName);
281
282         IAnalyticsManager analyticsManager = getAnalyticsService(containerName);
283         if (analyticsManager == null)
284             throw new ServiceUnavailableException("Analytics " + RestMessages.SERVICEUNAVAILABLE.toString());
285
286         AffinityLink al = handleAffinityLinkAvailability(containerName, affinityLinkName);
287         Map<Byte, Long> byteCounts = analyticsManager.getAllByteCounts(al);
288         Map<Byte, Double> bitRates = analyticsManager.getAllBitRates(al);
289         return new AllStatistics(byteCounts, bitRates);
290     }
291
292     /**
293      * @param containerName: Name of the Container
294      * @param srcIP: Source IP prefix
295      * @param srcMask: Source mask
296      * @param dstIP: Destination IP prefix
297      * @param dstMask: Destination mask
298      * @return Statistics between subnets
299      */
300     @Path("/{containerName}/subnetstats/{srcIP}/{srcMask}/{dstIP}/{dstMask}")
301     @GET
302     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
303     @TypeHint(Statistics.class)
304     @StatusCodes({
305         @ResponseCode(code = 200, condition = "Operation successful"),
306         @ResponseCode(code = 404, condition = "The containerName is not found"),
307         @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
308     public Statistics getSubnetStatistics(
309         @PathParam("containerName") String containerName,
310         @PathParam("srcIP") String srcIP,
311         @PathParam("srcMask") String srcMask,
312         @PathParam("dstIP") String dstIP,
313         @PathParam("dstMask") String dstMask) {
314         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this))
315             throw new UnauthorizedException("User is not authorized to perform this operation on container " + containerName);
316         handleDefaultDisabled(containerName);
317
318         IAnalyticsManager analyticsManager = getAnalyticsService(containerName);
319         if (analyticsManager == null)
320             throw new ServiceUnavailableException("Analytics " + RestMessages.SERVICEUNAVAILABLE.toString());
321
322         String srcString = srcIP + "/" + srcMask;
323         String dstString = dstIP + "/" + dstMask;
324         // TODO: This is hardly the most elegant way to handle null prefixes
325         if (srcString.equals("null/null"))
326             srcString = null;
327         if (dstString.equals("null/null"))
328             dstString = null;
329         long byteCount = analyticsManager.getByteCount(srcString, dstString);
330         double bitRate = analyticsManager.getBitRate(srcString, dstString);
331
332         return new Statistics(byteCount, bitRate);
333     }
334
335     /**
336      * @param containerName: Name of the Container
337      * @param srcIP: Source IP prefix
338      * @param srcMask: Source mask
339      * @param dstIP: Destination IP prefix
340      * @param dstMask: Destination mask
341      * @param protocol: IP protocol
342      * @return Statistics between subnets for a particular protocol
343      */
344     @Path("/{containerName}/subnetstats/{srcIP}/{srcMask}/{dstIP}/{dstMask}/{protocol}")
345     @GET
346     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
347     @TypeHint(Statistics.class)
348     @StatusCodes({
349         @ResponseCode(code = 200, condition = "Operation successful"),
350         @ResponseCode(code = 404, condition = "The containerName is not found"),
351         @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
352     public Statistics getSubnetStatistics(
353         @PathParam("containerName") String containerName,
354         @PathParam("srcIP") String srcIP,
355         @PathParam("srcMask") String srcMask,
356         @PathParam("dstIP") String dstIP,
357         @PathParam("dstMask") String dstMask,
358         @PathParam("protocol") String protocol) {
359         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this))
360             throw new UnauthorizedException("User is not authorized to perform this operation on container " + containerName);
361         handleDefaultDisabled(containerName);
362
363         IAnalyticsManager analyticsManager = getAnalyticsService(containerName);
364         if (analyticsManager == null)
365             throw new ServiceUnavailableException("Analytics " + RestMessages.SERVICEUNAVAILABLE.toString());
366
367         String srcString = srcIP + "/" + srcMask;
368         String dstString = dstIP + "/" + dstMask;
369         // TODO: This is hardly the most elegant way to handle null prefixes
370         if (srcString.equals("null/null"))
371             srcString = null;
372         if (dstString.equals("null/null"))
373             dstString = null;
374         long byteCount = analyticsManager.getByteCount(srcString, dstString, IPProtocols.getProtocolNumberByte(protocol));
375         double bitRate = analyticsManager.getBitRate(srcString, dstString, IPProtocols.getProtocolNumberByte(protocol));
376
377         return new Statistics(byteCount, bitRate);
378     }
379     /**
380      * @param containerName: Name of the Container
381      * @param srcIP: Source IP prefix
382      * @param srcMask: Source mask
383      * @param dstIP: Destination IP prefix
384      * @param dstMask: Destination mask
385      * @return Statistics between subnets for a particular protocol
386      */
387     @Path("/{containerName}/subnetstats/{srcIP}/{srcMask}/{dstIP}/{dstMask}/all")
388     @GET
389     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
390     @TypeHint(AllStatistics.class)
391     @StatusCodes({
392         @ResponseCode(code = 200, condition = "Operation successful"),
393         @ResponseCode(code = 404, condition = "The containerName is not found"),
394         @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
395     public AllStatistics getAllSubnetStatistics(
396         @PathParam("containerName") String containerName,
397         @PathParam("srcIP") String srcIP,
398         @PathParam("srcMask") String srcMask,
399         @PathParam("dstIP") String dstIP,
400         @PathParam("dstMask") String dstMask) {
401         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this))
402             throw new UnauthorizedException("User is not authorized to perform this operation on container " + containerName);
403         handleDefaultDisabled(containerName);
404
405         IAnalyticsManager analyticsManager = getAnalyticsService(containerName);
406         if (analyticsManager == null)
407             throw new ServiceUnavailableException("Analytics " + RestMessages.SERVICEUNAVAILABLE.toString());
408
409         String srcString = srcIP + "/" + srcMask;
410         String dstString = dstIP + "/" + dstMask;
411         // TODO: This is hardly the most elegant way to handle null prefixes
412         if (srcString.equals("null/null"))
413             srcString = null;
414         if (dstString.equals("null/null"))
415             dstString = null;
416
417         Map<Byte, Long> byteCounts = analyticsManager.getAllByteCounts(srcString, dstString);
418         Map<Byte, Double> bitRates = analyticsManager.getAllBitRates(srcString, dstString);
419         return new AllStatistics(byteCounts, bitRates);
420     }
421
422     /**
423      * @param containerName: Name of the Container
424      * @param ip: IP prefix
425      * @param mask: Mask
426      * @return Hosts that sent data into this subnet
427      */
428     @Path("/{containerName}/subnetstats/incoming/{ip}/{mask}/")
429     @GET
430     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
431     @TypeHint(IncomingHostData.class)
432     @StatusCodes({
433         @ResponseCode(code = 200, condition = "Operation successful"),
434         @ResponseCode(code = 404, condition = "The containerName is not found"),
435         @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
436     public IncomingHostData getIncomingHostByteCounts(
437         @PathParam("containerName") String containerName,
438         @PathParam("ip") String ip,
439         @PathParam("mask") String mask) {
440         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this))
441             throw new UnauthorizedException("User is not authorized to perform this operation on container " + containerName);
442         handleDefaultDisabled(containerName);
443
444         IAnalyticsManager analyticsManager = getAnalyticsService(containerName);
445         if (analyticsManager == null)
446             throw new ServiceUnavailableException("Analytics " + RestMessages.SERVICEUNAVAILABLE.toString());
447
448         Map<Host, Long> hosts = analyticsManager.getIncomingHostByteCounts(ip + "/" + mask);
449         return new IncomingHostData(hosts);
450     }
451
452     /**
453      * @param containerName: Name of the Container
454      * @param ip: IP prefix
455      * @param mask: Mask
456      * @param protocol: IP protocol
457      * @return Hosts that sent data into this subnet using this protocol
458      */
459     @Path("/{containerName}/subnetstats/incoming/{ip}/{mask}/{protocol}")
460     @GET
461     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
462     @TypeHint(IncomingHostData.class)
463     @StatusCodes({
464         @ResponseCode(code = 200, condition = "Operation successful"),
465         @ResponseCode(code = 404, condition = "The containerName is not found"),
466         @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
467     public IncomingHostData getIncomingHostByteCounts(
468         @PathParam("containerName") String containerName,
469         @PathParam("ip") String ip,
470         @PathParam("mask") String mask,
471         @PathParam("protocol") String protocol) {
472         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this))
473             throw new UnauthorizedException("User is not authorized to perform this operation on container " + containerName);
474         handleDefaultDisabled(containerName);
475
476         IAnalyticsManager analyticsManager = getAnalyticsService(containerName);
477         if (analyticsManager == null)
478             throw new ServiceUnavailableException("Analytics " + RestMessages.SERVICEUNAVAILABLE.toString());
479
480         Map<Host, Long> hosts = analyticsManager.getIncomingHostByteCounts(ip + "/" + mask, IPProtocols.getProtocolNumberByte(protocol));
481         return new IncomingHostData(hosts);
482     }
483
484     private void handleDefaultDisabled(String containerName) {
485         IContainerManager containerManager = (IContainerManager) ServiceHelper.getGlobalInstance(IContainerManager.class, this);
486         if (containerManager == null)
487             throw new InternalServerErrorException(RestMessages.INTERNALERROR.toString());
488         if (containerName.equals(GlobalConstants.DEFAULT.toString()) && containerManager.hasNonDefaultContainer())
489             throw new ResourceConflictException(RestMessages.DEFAULTDISABLED.toString());
490     }
491
492     private AffinityLink handleAffinityLinkAvailability(String containerName, String linkName) {
493         IAffinityManager affinityManager = (IAffinityManager) ServiceHelper.getInstance(IAffinityManager.class, containerName, this);
494         if (affinityManager == null)
495             throw new ServiceUnavailableException("Affinity manager " + RestMessages.SERVICEUNAVAILABLE.toString());
496         AffinityLink al = affinityManager.getAffinityLink(linkName);
497         if (al == null)
498             throw new ResourceNotFoundException(linkName + " : AffinityLink does not exist");
499         return al;
500     }
501
502
503     private Host handleHostAvailability(String containerName, String networkAddr) {
504         IfIptoHost hostTracker = (IfIptoHost) ServiceHelper.getInstance(IfIptoHost.class, containerName, this);
505         if (hostTracker == null)
506             throw new ServiceUnavailableException("Host tracker " + RestMessages.SERVICEUNAVAILABLE.toString());
507
508         Set<HostNodeConnector> allHosts = hostTracker.getAllHosts();
509         if (allHosts == null)
510             throw new ResourceNotFoundException(networkAddr + " : " + RestMessages.NOHOST.toString());
511
512         Host host = null;
513         try {
514             InetAddress networkAddress = InetAddress.getByName(networkAddr);
515             for (Host h : allHosts) {
516                 if (h.getNetworkAddress().equals(networkAddress)) {
517                     host = h;
518                     break;
519                 }
520             }
521         } catch (UnknownHostException e) {
522         }
523
524         if (host == null)
525             throw new ResourceNotFoundException(networkAddr + " : " + RestMessages.NOHOST.toString());
526         return host;
527     }
528 }