Initial push of Neutron interface
[controller.git] / opendaylight / northbound / networkconfiguration / neutron / src / main / java / org / opendaylight / controller / networkconfig / neutron / northbound / NeutronNetworksNorthbound.java
1 /*\r
2  * Copyright IBM Corporation, 2013.  All rights reserved.\r
3  *\r
4  * This program and the accompanying materials are made available under the\r
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
6  * and is available at http://www.eclipse.org/legal/epl-v10.html\r
7  */\r
8 \r
9 package org.opendaylight.controller.networkconfig.neutron.northbound;\r
10 \r
11 import java.util.ArrayList;\r
12 import java.util.HashMap;\r
13 import java.util.Iterator;\r
14 import java.util.List;\r
15 import javax.ws.rs.Consumes;\r
16 import javax.ws.rs.DELETE;\r
17 import javax.ws.rs.GET;\r
18 import javax.ws.rs.POST;\r
19 import javax.ws.rs.PUT;\r
20 import javax.ws.rs.Path;\r
21 import javax.ws.rs.PathParam;\r
22 import javax.ws.rs.Produces;\r
23 import javax.ws.rs.QueryParam;\r
24 import javax.ws.rs.core.MediaType;\r
25 import javax.ws.rs.core.Response;\r
26 \r
27 import org.codehaus.enunciate.jaxrs.ResponseCode;\r
28 import org.codehaus.enunciate.jaxrs.StatusCodes;\r
29 import org.codehaus.enunciate.jaxrs.TypeHint;\r
30 import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkAware;\r
31 import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;\r
32 import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;\r
33 import org.opendaylight.controller.northbound.commons.RestMessages;\r
34 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;\r
35 import org.opendaylight.controller.sal.utils.ServiceHelper;\r
36 \r
37 /**\r
38  * Open DOVE Northbound REST APIs for Network.<br>\r
39  * This class provides REST APIs for managing open DOVE internals related to Networks\r
40  *\r
41  * <br>\r
42  * <br>\r
43  * Authentication scheme : <b>HTTP Basic</b><br>\r
44  * Authentication realm : <b>opendaylight</b><br>\r
45  * Transport : <b>HTTP and HTTPS</b><br>\r
46  * <br>\r
47  * HTTPS Authentication is disabled by default. Administrator can enable it in\r
48  * tomcat-server.xml after adding a proper keystore / SSL certificate from a\r
49  * trusted authority.<br>\r
50  * More info :\r
51  * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration\r
52  *\r
53  */\r
54 \r
55 @Path("/networks")\r
56 public class NeutronNetworksNorthbound {\r
57 \r
58     private NeutronNetwork extractFields(NeutronNetwork o, List<String> fields) {\r
59         return o.extractFields(fields);\r
60     }\r
61 \r
62     /**\r
63      * Returns a list of all Networks */\r
64 \r
65     @GET\r
66     @Produces({ MediaType.APPLICATION_JSON })\r
67     //@TypeHint(OpenStackNetworks.class)\r
68     @StatusCodes({\r
69             @ResponseCode(code = 200, condition = "Operation successful"),\r
70             @ResponseCode(code = 401, condition = "Unauthorized") })\r
71     public Response listNetworks(\r
72             // return fields\r
73             @QueryParam("fields") List<String> fields,\r
74             // note: openstack isn't clear about filtering on lists, so we aren't handling them\r
75             @QueryParam("id") String queryID,\r
76             @QueryParam("name") String queryName,\r
77             @QueryParam("admin_state_up") String queryAdminStateUp,\r
78             @QueryParam("status") String queryStatus,\r
79             @QueryParam("shared") String queryShared,\r
80             @QueryParam("tenant_id") String queryTenantID,\r
81             @QueryParam("router_external") String queryRouterExternal,\r
82             @QueryParam("provider_network_type") String queryProviderNetworkType,\r
83             @QueryParam("provider_physical_network") String queryProviderPhysicalNetwork,\r
84             @QueryParam("provider_segmentation_id") String queryProviderSegmentationID,\r
85             // pagination\r
86             @QueryParam("limit") String limit,\r
87             @QueryParam("marker") String marker,\r
88             @QueryParam("page_reverse") String pageReverse\r
89             // sorting not supported\r
90         ) {\r
91         INeutronNetworkCRUD networkInterface = NeutronNBInterfaces.getIfNBNetworkCRUD("default", this);\r
92         if (networkInterface == null) {\r
93             throw new ServiceUnavailableException("Network CRUD Interface "\r
94                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
95         }\r
96         List<NeutronNetwork> allNetworks = networkInterface.getAllNetworks();\r
97         List<NeutronNetwork> ans = new ArrayList<NeutronNetwork>();\r
98         Iterator<NeutronNetwork> i = allNetworks.iterator();\r
99         while (i.hasNext()) {\r
100             NeutronNetwork oSN = i.next();\r
101             //match filters: TODO provider extension\r
102             Boolean bAdminStateUp = null;\r
103             Boolean bShared = null;\r
104             Boolean bRouterExternal = null;\r
105             if (queryAdminStateUp != null)\r
106                 bAdminStateUp = new Boolean(queryAdminStateUp);\r
107             if (queryShared != null)\r
108                 bShared = new Boolean(queryShared);\r
109             if (queryRouterExternal != null)\r
110                 bRouterExternal = new Boolean(queryRouterExternal);\r
111             if ((queryID == null || queryID.equals(oSN.getID())) &&\r
112                     (queryName == null || queryName.equals(oSN.getNetworkName())) &&\r
113                     (bAdminStateUp == null || bAdminStateUp.booleanValue() == oSN.isAdminStateUp()) &&\r
114                     (queryStatus == null || queryStatus.equals(oSN.getStatus())) &&\r
115                     (bShared == null || bShared.booleanValue() == oSN.isShared()) &&\r
116                     (bRouterExternal == null || bRouterExternal.booleanValue() == oSN.isRouterExternal()) &&\r
117                     (queryTenantID == null || queryTenantID.equals(oSN.getTenantID()))) {\r
118                 if (fields.size() > 0)\r
119                     ans.add(extractFields(oSN,fields));\r
120                 else\r
121                     ans.add(oSN);\r
122             }\r
123         }\r
124         //TODO: apply pagination to results\r
125         return Response.status(200).entity(\r
126                 new NeutronNetworkRequest(ans)).build();\r
127     }\r
128 \r
129     /**\r
130      * Returns a specific Network */\r
131 \r
132     @Path("{netUUID}")\r
133     @GET\r
134     @Produces({ MediaType.APPLICATION_JSON })\r
135     //@TypeHint(OpenStackNetworks.class)\r
136     @StatusCodes({\r
137             @ResponseCode(code = 200, condition = "Operation successful"),\r
138             @ResponseCode(code = 401, condition = "Unauthorized"),\r
139             @ResponseCode(code = 404, condition = "Not Found") })\r
140     public Response showNetwork(\r
141             @PathParam("netUUID") String netUUID,\r
142             // return fields\r
143             @QueryParam("fields") List<String> fields\r
144             ) {\r
145         INeutronNetworkCRUD networkInterface = NeutronNBInterfaces.getIfNBNetworkCRUD("default", this);\r
146         if (networkInterface == null) {\r
147             throw new ServiceUnavailableException("Network CRUD Interface "\r
148                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
149         }\r
150         if (!networkInterface.networkExists(netUUID))\r
151             return Response.status(404).build();\r
152         if (fields.size() > 0) {\r
153             NeutronNetwork ans = networkInterface.getNetwork(netUUID);\r
154             return Response.status(200).entity(\r
155                     new NeutronNetworkRequest(extractFields(ans, fields))).build();\r
156         } else\r
157             return Response.status(200).entity(\r
158                     new NeutronNetworkRequest(networkInterface.getNetwork(netUUID))).build();\r
159     }\r
160 \r
161     /**\r
162      * Creates new Networks */\r
163     @POST\r
164     @Produces({ MediaType.APPLICATION_JSON })\r
165     @Consumes({ MediaType.APPLICATION_JSON })\r
166     @TypeHint(NeutronNetwork.class)\r
167     @StatusCodes({\r
168             @ResponseCode(code = 201, condition = "Created"),\r
169             @ResponseCode(code = 400, condition = "Bad Request"),\r
170             @ResponseCode(code = 401, condition = "Unauthorized") })\r
171     public Response createNetworks(final NeutronNetworkRequest input) {\r
172         INeutronNetworkCRUD networkInterface = NeutronNBInterfaces.getIfNBNetworkCRUD("default", this);\r
173         if (networkInterface == null) {\r
174             throw new ServiceUnavailableException("Network CRUD Interface "\r
175                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
176         }\r
177         if (input.isSingleton()) {\r
178             NeutronNetwork singleton = input.getSingleton();\r
179 \r
180             /*\r
181              * network ID can't already exist\r
182              */\r
183             if (networkInterface.networkExists(singleton.getID()))\r
184                 return Response.status(400).build();\r
185 \r
186             Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);\r
187             if (instances != null) {\r
188                 for (Object instance : instances) {\r
189                     INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
190                     int status = service.canCreateNetwork(singleton);\r
191                     if (status < 200 || status > 299)\r
192                         return Response.status(status).build();\r
193                 }\r
194             }\r
195 \r
196             // add network to cache\r
197             networkInterface.addNetwork(singleton);\r
198             if (instances != null) {\r
199                 for (Object instance : instances) {\r
200                     INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
201                     service.neutronNetworkCreated(singleton);\r
202                 }\r
203             }\r
204 \r
205         } else {\r
206             List<NeutronNetwork> bulk = input.getBulk();\r
207             Iterator<NeutronNetwork> i = bulk.iterator();\r
208             HashMap<String, NeutronNetwork> testMap = new HashMap<String, NeutronNetwork>();\r
209             Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);\r
210             while (i.hasNext()) {\r
211                 NeutronNetwork test = i.next();\r
212 \r
213                 /*\r
214                  * network ID can't already exist, nor can there be an entry for this UUID\r
215                  * already in this bulk request\r
216                  */\r
217                 if (networkInterface.networkExists(test.getID()))\r
218                     return Response.status(400).build();\r
219                 if (testMap.containsKey(test.getID()))\r
220                     return Response.status(400).build();\r
221                 if (instances != null) {\r
222                     for (Object instance: instances) {\r
223                         INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
224                         int status = service.canCreateNetwork(test);\r
225                         if (status < 200 || status > 299)\r
226                             return Response.status(status).build();\r
227                     }\r
228                 }\r
229                 testMap.put(test.getID(),test);\r
230             }\r
231 \r
232             // now that everything passed, add items to the cache\r
233             i = bulk.iterator();\r
234             while (i.hasNext()) {\r
235                 NeutronNetwork test = i.next();\r
236                 test.initDefaults();\r
237                 networkInterface.addNetwork(test);\r
238                 if (instances != null) {\r
239                     for (Object instance: instances) {\r
240                         INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
241                         service.neutronNetworkCreated(test);\r
242                     }\r
243                 }\r
244             }\r
245         }\r
246         return Response.status(201).entity(input).build();\r
247     }\r
248 \r
249     /**\r
250      * Updates a Network */\r
251     @Path("{netUUID}")\r
252     @PUT\r
253     @Produces({ MediaType.APPLICATION_JSON })\r
254     @Consumes({ MediaType.APPLICATION_JSON })\r
255     //@TypeHint(OpenStackNetworks.class)\r
256     @StatusCodes({\r
257             @ResponseCode(code = 200, condition = "Operation successful"),\r
258             @ResponseCode(code = 400, condition = "Bad Request"),\r
259             @ResponseCode(code = 403, condition = "Forbidden"),\r
260             @ResponseCode(code = 404, condition = "Not Found"), })\r
261     public Response updateNetwork(\r
262             @PathParam("netUUID") String netUUID, final NeutronNetworkRequest input\r
263             ) {\r
264         INeutronNetworkCRUD networkInterface = NeutronNBInterfaces.getIfNBNetworkCRUD("default", this);\r
265         if (networkInterface == null) {\r
266             throw new ServiceUnavailableException("Network CRUD Interface "\r
267                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
268         }\r
269 \r
270         /*\r
271          * network has to exist and only a single delta is supported\r
272          */\r
273         if (!networkInterface.networkExists(netUUID))\r
274             return Response.status(404).build();\r
275         if (!input.isSingleton())\r
276             return Response.status(400).build();\r
277         NeutronNetwork delta = input.getSingleton();\r
278 \r
279         /*\r
280          * transitions forbidden by Neutron\r
281          */\r
282         if (delta.getID() != null || delta.getTenantID() != null ||\r
283                 delta.getStatus() != null)\r
284             return Response.status(400).build();\r
285 \r
286         Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);\r
287         if (instances != null) {\r
288             for (Object instance : instances) {\r
289                 INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
290                 NeutronNetwork original = networkInterface.getNetwork(netUUID);\r
291                 int status = service.canUpdateNetwork(delta, original);\r
292                 if (status < 200 || status > 299)\r
293                     return Response.status(status).build();\r
294             }\r
295         }\r
296 \r
297         // update network object and return the modified object\r
298         networkInterface.updateNetwork(netUUID, delta);\r
299         NeutronNetwork updatedSingleton = networkInterface.getNetwork(netUUID);\r
300         if (instances != null) {\r
301             for (Object instance : instances) {\r
302                 INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
303                 service.neutronNetworkUpdated(updatedSingleton);\r
304             }\r
305         }\r
306         return Response.status(200).entity(\r
307                 new NeutronNetworkRequest(networkInterface.getNetwork(netUUID))).build();\r
308     }\r
309 \r
310     /**\r
311      * Deletes a Network */\r
312 \r
313     @Path("{netUUID}")\r
314     @DELETE\r
315     @StatusCodes({\r
316             @ResponseCode(code = 204, condition = "No Content"),\r
317             @ResponseCode(code = 401, condition = "Unauthorized"),\r
318             @ResponseCode(code = 404, condition = "Not Found"),\r
319             @ResponseCode(code = 409, condition = "Network In Use") })\r
320     public Response deleteNetwork(\r
321             @PathParam("netUUID") String netUUID) {\r
322         INeutronNetworkCRUD networkInterface = NeutronNBInterfaces.getIfNBNetworkCRUD("default", this);\r
323         if (networkInterface == null) {\r
324             throw new ServiceUnavailableException("Network CRUD Interface "\r
325                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
326         }\r
327 \r
328         /*\r
329          * network has to exist and not be in use before it can be removed\r
330          */\r
331         if (!networkInterface.networkExists(netUUID))\r
332             return Response.status(404).build();\r
333         if (networkInterface.networkInUse(netUUID))\r
334             return Response.status(409).build();\r
335 \r
336         NeutronNetwork singleton = networkInterface.getNetwork(netUUID);\r
337         Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);\r
338         if (instances != null) {\r
339             for (Object instance : instances) {\r
340                 INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
341                 int status = service.canDeleteNetwork(singleton);\r
342                 if (status < 200 || status > 299)\r
343                     return Response.status(status).build();\r
344             }\r
345         }\r
346         networkInterface.removeNetwork(netUUID);\r
347         if (instances != null) {\r
348             for (Object instance : instances) {\r
349                 INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
350                 service.neutronNetworkDeleted(singleton);\r
351             }\r
352         }\r
353         return Response.status(204).build();\r
354     }\r
355 }\r