769461167c1036812ea33f17d0ffcf8f2b21a6c5
[controller.git] / opendaylight / northbound / hosttracker / src / main / java / org / opendaylight / controller / hosttracker / northbound / HostTrackerNorthbound.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.controller.hosttracker.northbound;
10
11 import java.net.InetAddress;
12 import java.net.UnknownHostException;
13 import java.util.HashSet;
14 import java.util.List;
15 import java.util.Set;
16
17 import javax.ws.rs.Consumes;
18 import javax.ws.rs.DELETE;
19 import javax.ws.rs.GET;
20 import javax.ws.rs.PUT;
21 import javax.ws.rs.Path;
22 import javax.ws.rs.PathParam;
23 import javax.ws.rs.Produces;
24 import javax.ws.rs.core.Context;
25 import javax.ws.rs.core.MediaType;
26 import javax.ws.rs.core.Response;
27 import javax.ws.rs.core.SecurityContext;
28 import javax.xml.bind.JAXBElement;
29
30 import org.codehaus.enunciate.jaxrs.ResponseCode;
31 import org.codehaus.enunciate.jaxrs.StatusCodes;
32 import org.codehaus.enunciate.jaxrs.TypeHint;
33 import org.opendaylight.controller.containermanager.IContainerManager;
34 import org.opendaylight.controller.hosttracker.IfIptoHost;
35 import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;
36 import org.opendaylight.controller.northbound.commons.RestMessages;
37 import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException;
38 import org.opendaylight.controller.northbound.commons.exception.ResourceConflictException;
39 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
40 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
41 import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
42 import org.opendaylight.controller.northbound.commons.exception.UnsupportedMediaTypeException;
43 import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
44 import org.opendaylight.controller.sal.authorization.Privilege;
45 import org.opendaylight.controller.sal.core.Node;
46 import org.opendaylight.controller.sal.core.NodeConnector;
47 import org.opendaylight.controller.sal.utils.GlobalConstants;
48 import org.opendaylight.controller.sal.utils.ServiceHelper;
49 import org.opendaylight.controller.sal.utils.Status;
50 import org.opendaylight.controller.sal.utils.StatusCode;
51 import org.opendaylight.controller.switchmanager.ISwitchManager;
52
53 /**
54  * Host Tracker Northbound REST APIs.<br>
55  * This class provides REST APIs to track host location in a network. Host
56  * Location is represented by Host node connector which is essentially a logical
57  * entity that represents a Switch/Port. A host is represented by it's
58  * IP-address and mac-address.
59  *
60  * <br>
61  * <br>
62  * Authentication scheme : <b>HTTP Basic</b><br>
63  * Authentication realm : <b>opendaylight</b><br>
64  * Transport : <b>HTTP and HTTPS</b><br>
65  * <br>
66  * HTTPS Authentication is disabled by default. Administrator can enable it in
67  * tomcat-server.xml after adding a proper keystore / SSL certificate from a
68  * trusted authority.<br>
69  * More info :
70  * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
71  *
72  */
73
74 @Path("/")
75 public class HostTrackerNorthbound {
76
77     private String username;
78
79     @Context
80     public void setSecurityContext(SecurityContext context) {
81         if (context != null && context.getUserPrincipal() != null) username = context.getUserPrincipal().getName();
82     }
83
84     protected String getUserName() {
85         return username;
86     }
87
88     private IfIptoHost getIfIpToHostService(String containerName) {
89         IContainerManager containerManager = (IContainerManager) ServiceHelper
90                 .getGlobalInstance(IContainerManager.class, this);
91         if (containerManager == null) {
92             throw new ServiceUnavailableException("Container "
93                     + RestMessages.SERVICEUNAVAILABLE.toString());
94         }
95
96         boolean found = false;
97         List<String> containerNames = containerManager.getContainerNames();
98         for (String cName : containerNames) {
99             if (cName.trim().equalsIgnoreCase(containerName.trim())) {
100                 found = true;
101             }
102         }
103
104         if (found == false) {
105             throw new ResourceNotFoundException(containerName + " "
106                     + RestMessages.NOCONTAINER.toString());
107         }
108
109         IfIptoHost hostTracker = (IfIptoHost) ServiceHelper.getInstance(
110                 IfIptoHost.class, containerName, this);
111
112         if (hostTracker == null) {
113             throw new ServiceUnavailableException("Host Tracker "
114                     + RestMessages.SERVICEUNAVAILABLE.toString());
115         }
116
117         return hostTracker;
118     }
119
120     private Hosts convertHosts(Set<HostNodeConnector> hostNodeConnectors) {
121         if(hostNodeConnectors == null) {
122             return null;
123         }
124         Set<HostConfig> hosts = new HashSet<HostConfig>();
125         for(HostNodeConnector hnc : hostNodeConnectors) {
126             hosts.add(HostConfig.convert(hnc));
127         }
128         return new Hosts(hosts);
129     }
130
131     /**
132      * Returns a list of all Hosts : both configured via PUT API and dynamically
133      * learnt on the network.
134      *
135      * @param containerName
136      *            Name of the Container. The Container name for the base
137      *            controller is "default".
138      * @return List of Active Hosts.
139      * <pre>
140      *
141      * Example:
142      *
143      * RequestURL:
144      *
145      * http://localhost:8080/controller/nb/v2/host/default
146      *
147      * Response in XML
148      *
149      * &lt;list&gt;
150      * &#x20;&lt;hostConfig&gt;
151      * &#x20;&#x20;&lt;dataLayerAddress&gt;00:00:00:00:01:01&lt;/dataLayerAddress&gt;
152      * &#x20;&#x20;&lt;networkAddress&gt;1.1.1.1&lt;/networkAddress&gt;
153      * &#x20;&#x20;&lt;nodeType&gt;OF&lt;/nodeType&gt;
154      * &#x20;&#x20;&lt;nodeId&gt;00:00:00:00:00:00:00:01&lt;/nodeId&gt;
155      * &#x20;&#x20;&lt;nodeConnectorType&gt;OF&lt;/nodeConnectorType&gt;
156      * &#x20;&#x20;&lt;nodeConnectorId&gt;9&lt;/nodeConnectorId&gt;
157      * &#x20;&#x20;&lt;vlan&gt;0&lt;/vlan&gt;
158      * &#x20;&#x20;&lt;staticHost&gt;false&lt;/staticHost&gt;
159      * &#x20;&lt;/hostConfig&gt;
160      * &#x20;&lt;hostConfig&gt;
161      * &#x20;&#x20;&lt;dataLayerAddress&gt;00:00:00:00:02:02&lt;/dataLayerAddress&gt;
162      * &#x20;&#x20;&lt;networkAddress&gt;2.2.2.2&lt;/networkAddress&gt;
163      * &#x20;&#x20;&lt;nodeType&gt;OF&lt;/nodeType&gt;
164      * &#x20;&#x20;&lt;nodeId&gt;00:00:00:00:00:00:00:02&lt;/nodeId&gt;
165      * &#x20;&#x20;&lt;nodeConnectorType&gt;OF&lt;/nodeConnectorType&gt;
166      * &#x20;&#x20;&lt;nodeConnectorId&gt;5&lt;/nodeConnectorId&gt;
167      * &#x20;&#x20;&lt;vlan&gt;0&lt;/vlan&gt;
168      * &#x20;&#x20;&lt;staticHost&gt;false&lt;/staticHost&gt;
169      * &#x20;&lt;/hostConfig&gt;
170      * &lt;/list&gt;
171      *
172      * Response in JSON:
173      *
174      * {
175      * &#x20;"hostConfig":[
176      * &#x20;&#x20;{
177      * &#x20;&#x20;&#x20;"dataLayerAddress":"00:00:00:00:01:01",
178      * &#x20;&#x20;&#x20;"nodeType":"OF",
179      * &#x20;&#x20;&#x20;"nodeId":"00:00:00:00:00:00:00:01",
180      * &#x20;&#x20;&#x20;"nodeConnectorType":"OF",
181      * &#x20;&#x20;&#x20;"nodeConnectorId":"9",
182      * &#x20;&#x20;&#x20;"vlan":"0",
183      * &#x20;&#x20;&#x20;"staticHost":"false",
184      * &#x20;&#x20;&#x20;"networkAddress":"1.1.1.1"
185      * &#x20;&#x20;},
186      * &#x20;&#x20;{
187      * &#x20;&#x20;&#x20;"dataLayerAddress":"00:00:00:00:02:02",
188      * &#x20;&#x20;&#x20;"nodeType":"OF",
189      * &#x20;&#x20;&#x20;"nodeId":"00:00:00:00:00:00:00:02",
190      * &#x20;&#x20;&#x20;"nodeConnectorType":"OF",
191      * &#x20;&#x20;&#x20;"nodeConnectorId":"5",
192      * &#x20;&#x20;&#x20;"vlan":"0",
193      * &#x20;&#x20;&#x20;"staticHost":"false",
194      * &#x20;&#x20;&#x20;"networkAddress":"2.2.2.2"
195      * &#x20;&#x20;}
196      * &#x20;]
197      * }
198      * </pre>
199      */
200     @Path("/{containerName}")
201     @GET
202     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
203     @TypeHint(Hosts.class)
204     @StatusCodes({
205             @ResponseCode(code = 200, condition = "Operation successful"),
206             @ResponseCode(code = 404, condition = "The containerName is not found"),
207             @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
208     public Hosts getActiveHosts(@PathParam("containerName") String containerName) {
209
210         if (!NorthboundUtils.isAuthorized(
211                 getUserName(), containerName, Privilege.READ, this)) {
212             throw new UnauthorizedException(
213                     "User is not authorized to perform this operation on container "
214                             + containerName);
215         }
216         IfIptoHost hostTracker = getIfIpToHostService(containerName);
217         if (hostTracker == null) {
218             throw new ServiceUnavailableException("Host Tracker "
219                     + RestMessages.SERVICEUNAVAILABLE.toString());
220         }
221         return convertHosts(hostTracker.getAllHosts());
222     }
223
224     /**
225      * Returns a list of Hosts that are statically configured and are connected
226      * to a NodeConnector that is down.
227      *
228      * @param containerName
229      *            Name of the Container. The Container name for the base
230      *            controller is "default".
231      * @return List of inactive Hosts.
232      * <pre>
233      *
234      * Example:
235      *
236      * RequestURL:
237      *
238      * http://localhost:8080/controller/nb/v2/host/default/inactive
239      *
240      * Response in XML
241      *
242      * &lt;list&gt;
243      * &#x20;&lt;hostConfig&gt;
244      * &#x20;&#x20;&lt;dataLayerAddress&gt;00:00:00:00:01:01&lt;/dataLayerAddress&gt;
245      * &#x20;&#x20;&lt;networkAddress&gt;1.1.1.1&lt;/networkAddress&gt;
246      * &#x20;&#x20;&lt;nodeType&gt;OF&lt;/nodeType&gt;
247      * &#x20;&#x20;&lt;nodeId&gt;00:00:00:00:00:00:00:01&lt;/nodeId&gt;
248      * &#x20;&#x20;&lt;nodeConnectorType&gt;OF&lt;/nodeConnectorType&gt;
249      * &#x20;&#x20;&lt;nodeConnectorId&gt;9&lt;/nodeConnectorId&gt;
250      * &#x20;&#x20;&lt;vlan&gt;0&lt;/vlan&gt;
251      * &#x20;&#x20;&lt;staticHost&gt;false&lt;/staticHost&gt;
252      * &#x20;&lt;/hostConfig&gt;
253      * &#x20;&lt;hostConfig&gt;
254      * &#x20;&#x20;&lt;dataLayerAddress&gt;00:00:00:00:02:02&lt;/dataLayerAddress&gt;
255      * &#x20;&#x20;&lt;networkAddress&gt;2.2.2.2&lt;/networkAddress&gt;
256      * &#x20;&#x20;&lt;nodeType&gt;OF&lt;/nodeType&gt;
257      * &#x20;&#x20;&lt;nodeId&gt;00:00:00:00:00:00:00:02&lt;/nodeId&gt;
258      * &#x20;&#x20;&lt;nodeConnectorType&gt;OF&lt;/nodeConnectorType&gt;
259      * &#x20;&#x20;&lt;nodeConnectorId&gt;5&lt;/nodeConnectorId&gt;
260      * &#x20;&#x20;&lt;vlan&gt;0&lt;/vlan&gt;
261      * &#x20;&#x20;&lt;staticHost&gt;false&lt;/staticHost&gt;
262      * &#x20;&lt;/hostConfig&gt;
263      * &lt;/list&gt;
264      *
265      * Response in JSON:
266      *
267      * {
268      * &#x20;"hostConfig":[
269      * &#x20;&#x20;{
270      * &#x20;&#x20;&#x20;"dataLayerAddress":"00:00:00:00:01:01",
271      * &#x20;&#x20;&#x20;"nodeType":"OF",
272      * &#x20;&#x20;&#x20;"nodeId":"00:00:00:00:00:00:00:01",
273      * &#x20;&#x20;&#x20;"nodeConnectorType":"OF",
274      * &#x20;&#x20;&#x20;"nodeConnectorId":"9",
275      * &#x20;&#x20;&#x20;"vlan":"0",
276      * &#x20;&#x20;&#x20;"staticHost":"false",
277      * &#x20;&#x20;&#x20;"networkAddress":"1.1.1.1"
278      * &#x20;&#x20;},
279      * &#x20;&#x20;{
280      * &#x20;&#x20;&#x20;"dataLayerAddress":"00:00:00:00:02:02",
281      * &#x20;&#x20;&#x20;"nodeType":"OF",
282      * &#x20;&#x20;&#x20;"nodeId":"00:00:00:00:00:00:00:02",
283      * &#x20;&#x20;&#x20;"nodeConnectorType":"OF",
284      * &#x20;&#x20;&#x20;"nodeConnectorId":"5",
285      * &#x20;&#x20;&#x20;"vlan":"0",
286      * &#x20;&#x20;&#x20;"staticHost":"false",
287      * &#x20;&#x20;&#x20;"networkAddress":"2.2.2.2"
288      * &#x20;&#x20;}
289      * &#x20;]
290      * }
291      * </pre>
292      */
293     @Path("/{containerName}/inactive")
294     @GET
295     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
296     @TypeHint(Hosts.class)
297     @StatusCodes({
298             @ResponseCode(code = 200, condition = "Operation successful"),
299             @ResponseCode(code = 404, condition = "The containerName is not found"),
300             @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
301     public Hosts getInactiveHosts(
302             @PathParam("containerName") String containerName) {
303         if (!NorthboundUtils.isAuthorized(
304                 getUserName(), containerName, Privilege.READ, this)) {
305             throw new UnauthorizedException(
306                     "User is not authorized to perform this operation on container "
307                             + containerName);
308         }
309         IfIptoHost hostTracker = getIfIpToHostService(containerName);
310         if (hostTracker == null) {
311             throw new ServiceUnavailableException("Host Tracker "
312                     + RestMessages.SERVICEUNAVAILABLE.toString());
313         }
314         return convertHosts(hostTracker.getInactiveStaticHosts());
315     }
316
317     /**
318      * Returns a host that matches the IP Address value passed as parameter.
319      *
320      * @param containerName
321      *            Name of the Container. The Container name for the base
322      *            controller is "default".
323      * @param networkAddress
324      *            IP Address being looked up
325      * @return host that matches the IP Address
326      * <pre>
327      *
328      * Example:
329      *
330      * RequestURL:
331      *
332      * http://localhost:8080/controller/nb/v2/host/default/1.1.1.1
333      *
334      * Response in XML
335      *
336      * &lt;hostConfig&gt;
337      * &#x20;&lt;dataLayerAddress&gt;00:00:00:00:01:01&lt;/dataLayerAddress&gt;
338      * &#x20;&lt;networkAddress&gt;1.1.1.1&lt;/networkAddress&gt;
339      * &#x20;&lt;nodeType&gt;OF&lt;/nodeType&gt;
340      * &#x20;&lt;nodeId&gt;00:00:00:00:00:00:00:01&lt;/nodeId&gt;
341      * &#x20;&lt;nodeConnectorType&gt;OF&lt;/nodeConnectorType&gt;
342      * &#x20;&lt;nodeConnectorId&gt;9&lt;/nodeConnectorId&gt;
343      * &#x20;&lt;vlan&gt;0&lt;/vlan&gt;
344      * &#x20;&lt;staticHost&gt;false&lt;/staticHost&gt;
345      * &lt;/hostConfig&gt;
346      *
347      * Response in JSON:
348      *
349      * {
350      * &#x20;"dataLayerAddress":"00:00:00:00:01:01",
351      * &#x20;"nodeType":"OF",
352      * &#x20;"nodeId":"00:00:00:00:00:00:00:01",
353      * &#x20;"nodeConnectorType":"OF",
354      * &#x20;"nodeConnectorId":"9",
355      * &#x20;"vlan":"0",
356      * &#x20;"staticHost":"false",
357      * &#x20;"networkAddress":"1.1.1.1"
358      * }
359      * </pre>
360      */
361     @Path("/{containerName}/{networkAddress}")
362     @GET
363     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
364     @TypeHint(HostConfig.class)
365     @StatusCodes({
366             @ResponseCode(code = 200, condition = "Operation successful"),
367             @ResponseCode(code = 404, condition = "The containerName is not found"),
368             @ResponseCode(code = 415, condition = "Invalid IP Address passed in networkAddress parameter"),
369             @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
370     public HostConfig getHostDetails(
371             @PathParam("containerName") String containerName,
372             @PathParam("networkAddress") String networkAddress) {
373         if (!NorthboundUtils.isAuthorized(
374                 getUserName(), containerName, Privilege.READ, this)) {
375             throw new UnauthorizedException(
376                     "User is not authorized to perform this operation on container "
377                             + containerName);
378         }
379         IfIptoHost hostTracker = getIfIpToHostService(containerName);
380         if (hostTracker == null) {
381             throw new ServiceUnavailableException("Host Tracker "
382                     + RestMessages.SERVICEUNAVAILABLE.toString());
383         }
384
385         InetAddress ip;
386         try {
387             ip = InetAddress.getByName(networkAddress);
388         } catch (UnknownHostException e) {
389             throw new UnsupportedMediaTypeException(networkAddress + " "
390                     + RestMessages.INVALIDADDRESS.toString());
391         }
392         for (HostNodeConnector host : hostTracker.getAllHosts()) {
393             if (host.getNetworkAddress().equals(ip)) {
394                 return HostConfig.convert(host);
395             }
396         }
397         throw new ResourceNotFoundException(RestMessages.NOHOST.toString());
398     }
399
400     /**
401      * Add a Static Host configuration
402      *
403      * @param containerName
404      *            Name of the Container. The Container name for the base
405      *            controller is "default".
406      * @param networkAddress
407      *            Host IP Address
408      * @param hostConfig
409      *            Host Config Details
410      * @return Response as dictated by the HTTP Response Status code
411      *
412      * <pre>
413      *
414      * Example:
415      *
416      * RequestURL:
417      *
418      * http://localhost:8080/controller/nb/v2/host/default/1.1.1.1
419      *
420      * Request in XML
421      *
422      * &lt;hostConfig&gt;
423      * &#x20;&lt;dataLayerAddress&gt;00:00:00:00:01:01&lt;/dataLayerAddress&gt;
424      * &#x20;&lt;networkAddress&gt;1.1.1.1&lt;/networkAddress&gt;
425      * &#x20;&lt;nodeType&gt;OF&lt;/nodeType&gt;
426      * &#x20;&lt;nodeId&gt;00:00:00:00:00:00:00:01&lt;/nodeId&gt;
427      * &#x20;&lt;nodeConnectorType&gt;OF&lt;/nodeConnectorType&gt;
428      * &#x20;&lt;nodeConnectorId&gt;9&lt;/nodeConnectorId&gt;
429      * &#x20;&lt;vlan&gt;0&lt;/vlan&gt;
430      * &#x20;&lt;staticHost&gt;false&lt;/staticHost&gt;
431      * &lt;/hostConfig&gt;
432      *
433      * Request in JSON:
434      *
435      * {
436      * &#x20;"dataLayerAddress":"00:00:00:00:01:01",
437      * &#x20;"nodeType":"OF",
438      * &#x20;"nodeId":"00:00:00:00:00:00:00:01",
439      * &#x20;"nodeConnectorType":"OF",
440      * &#x20;"nodeConnectorId":"9",
441      * &#x20;"vlan":"0",
442      * &#x20;"staticHost":"false",
443      * &#x20;"networkAddress":"1.1.1.1"
444      * }
445      * </pre>
446      */
447
448     @Path("/{containerName}/{networkAddress}")
449     @PUT
450     @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
451     @StatusCodes({
452             @ResponseCode(code = 201, condition = "Static host created successfully"),
453             @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
454             @ResponseCode(code = 406, condition = "Cannot operate on Default Container when other Containers are active"),
455             @ResponseCode(code = 415, condition = "Invalid IP Address passed in networkAddress parameter"),
456             @ResponseCode(code = 500, condition = "Failed to create Static Host entry. Failure Reason included in HTTP Error response"),
457             @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
458     public Response addHost(@PathParam("containerName") String containerName,
459             @PathParam("networkAddress") String networkAddress,
460             @TypeHint(HostConfig.class) JAXBElement<HostConfig> hostConfig) {
461
462         if (!NorthboundUtils.isAuthorized(
463                 getUserName(), containerName, Privilege.WRITE, this)) {
464             throw new UnauthorizedException(
465                     "User is not authorized to perform this operation on container "
466                             + containerName);
467         }
468         handleDefaultDisabled(containerName);
469
470         IfIptoHost hostTracker = getIfIpToHostService(containerName);
471         if (hostTracker == null) {
472             throw new ServiceUnavailableException("Host Tracker "
473                     + RestMessages.SERVICEUNAVAILABLE.toString());
474         }
475
476         HostConfig hc = hostConfig.getValue();
477         Node node = handleNodeAvailability(containerName, hc.getNodeType(), hc.getNodeId());
478         if (node == null) {
479             throw new InternalServerErrorException(
480                     RestMessages.NONODE.toString());
481         }
482
483         try {
484             InetAddress.getByName(networkAddress);
485         } catch (UnknownHostException e) {
486             throw new UnsupportedMediaTypeException(networkAddress + " "
487                     + RestMessages.INVALIDADDRESS.toString());
488         }
489         if(!networkAddress.equals(hc.getNetworkAddress())) {
490             throw new UnsupportedMediaTypeException(networkAddress + " is not the same as "
491                     + hc.getNetworkAddress());
492         }
493         if(!hc.isStaticHost()) {
494             throw new UnsupportedMediaTypeException("StaticHost flag must be true");
495         }
496         NodeConnector nc = NodeConnector.fromStringNoNode(hc.getNodeConnectorType(), hc.getNodeConnectorId(), node);
497         if (nc == null) {
498             throw new ResourceNotFoundException(hc.getNodeConnectorType() + "|"
499                     + hc.getNodeConnectorId() + " : " + RestMessages.NONODE.toString());
500         }
501         Status status = hostTracker.addStaticHost(networkAddress,
502                 hc.getDataLayerAddress(), nc, hc.getVlan());
503         if (status.isSuccess()) {
504             NorthboundUtils.auditlog("Static Host", username, "added", networkAddress, containerName);
505             return Response.status(Response.Status.CREATED).build();
506         } else if (status.getCode().equals(StatusCode.BADREQUEST)) {
507             throw new UnsupportedMediaTypeException(status.getDescription());
508         }
509         throw new InternalServerErrorException(status.getDescription());
510     }
511
512     /**
513      * Delete a Static Host configuration
514      *
515      * @param containerName
516      *            Name of the Container. The Container name for the base
517      *            controller is "default".
518      * @param networkAddress
519      *            IP Address
520      * @return Response as dictated by the HTTP Response code.
521      */
522
523     @Path("/{containerName}/{networkAddress}")
524     @DELETE
525     @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
526     @StatusCodes({
527             @ResponseCode(code = 200, condition = "Flow Config deleted successfully"),
528             @ResponseCode(code = 404, condition = "The Container Name or Node-id or Flow Name passed is not found"),
529             @ResponseCode(code = 406, condition = "Cannot operate on Default Container when other Containers are active"),
530             @ResponseCode(code = 415, condition = "Invalid IP Address passed in networkAddress parameter"),
531             @ResponseCode(code = 500, condition = "Failed to delete Flow config. Failure Reason included in HTTP Error response"),
532             @ResponseCode(code = 503, condition = "One or more of Controller service is unavailable") })
533     public Response deleteFlow(
534             @PathParam(value = "containerName") String containerName,
535             @PathParam(value = "networkAddress") String networkAddress) {
536
537         if (!NorthboundUtils.isAuthorized(
538                 getUserName(), containerName, Privilege.WRITE, this)) {
539             throw new UnauthorizedException(
540                     "User is not authorized to perform this operation on container "
541                             + containerName);
542         }
543         handleDefaultDisabled(containerName);
544         IfIptoHost hostTracker = getIfIpToHostService(containerName);
545         if (hostTracker == null) {
546             throw new ServiceUnavailableException("Host Tracker "
547                     + RestMessages.SERVICEUNAVAILABLE.toString());
548         }
549
550         try {
551             InetAddress.getByName(networkAddress);
552         } catch (UnknownHostException e) {
553             throw new UnsupportedMediaTypeException(networkAddress + " "
554                     + RestMessages.INVALIDADDRESS.toString());
555         }
556
557         Status status = hostTracker.removeStaticHost(networkAddress);
558         if (status.isSuccess()) {
559             NorthboundUtils.auditlog("Static Host", username, "removed", networkAddress, containerName);
560             return Response.ok().build();
561         }
562         throw new InternalServerErrorException(status.getDescription());
563
564     }
565
566     private void handleDefaultDisabled(String containerName) {
567         IContainerManager containerManager = (IContainerManager) ServiceHelper
568                 .getGlobalInstance(IContainerManager.class, this);
569         if (containerManager == null) {
570             throw new InternalServerErrorException(
571                     RestMessages.INTERNALERROR.toString());
572         }
573         if (containerName.equals(GlobalConstants.DEFAULT.toString())
574                 && containerManager.hasNonDefaultContainer()) {
575             throw new ResourceConflictException(
576                     RestMessages.DEFAULTDISABLED.toString());
577         }
578     }
579
580     private Node handleNodeAvailability(String containerName, String nodeType,
581             String nodeId) {
582
583         Node node = Node.fromString(nodeType, nodeId);
584         if (node == null) {
585             throw new ResourceNotFoundException(nodeId + " : "
586                     + RestMessages.NONODE.toString());
587         }
588
589         ISwitchManager sm = (ISwitchManager) ServiceHelper.getInstance(
590                 ISwitchManager.class, containerName, this);
591
592         if (sm == null) {
593             throw new ServiceUnavailableException("Switch Manager "
594                     + RestMessages.SERVICEUNAVAILABLE.toString());
595         }
596
597         if (!sm.getNodes().contains(node)) {
598             throw new ResourceNotFoundException(node.toString() + " : "
599                     + RestMessages.NONODE.toString());
600         }
601         return node;
602     }
603
604 }