Add missing test methods to IRouterAware and clean up unused imports.
[controller.git] / opendaylight / northbound / networkconfiguration / neutron / src / main / java / org / opendaylight / controller / networkconfig / neutron / northbound / NeutronSubnetsNorthbound.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 \r
12 import java.util.ArrayList;\r
13 import java.util.HashMap;\r
14 import java.util.Iterator;\r
15 import java.util.List;\r
16 import javax.ws.rs.Consumes;\r
17 import javax.ws.rs.DELETE;\r
18 import javax.ws.rs.GET;\r
19 import javax.ws.rs.POST;\r
20 import javax.ws.rs.PUT;\r
21 import javax.ws.rs.Path;\r
22 import javax.ws.rs.PathParam;\r
23 import javax.ws.rs.Produces;\r
24 import javax.ws.rs.QueryParam;\r
25 import javax.ws.rs.core.MediaType;\r
26 import javax.ws.rs.core.Response;\r
27 \r
28 import org.codehaus.enunciate.jaxrs.ResponseCode;\r
29 import org.codehaus.enunciate.jaxrs.StatusCodes;\r
30 import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;\r
31 import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetAware;\r
32 import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;\r
33 import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;\r
34 import org.opendaylight.controller.northbound.commons.RestMessages;\r
35 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;\r
36 import org.opendaylight.controller.sal.utils.ServiceHelper;\r
37 \r
38 /**\r
39  * Open DOVE Northbound REST APIs.<br>\r
40  * This class provides REST APIs for managing open DOVE internals related to Subnets\r
41  *\r
42  * <br>\r
43  * <br>\r
44  * Authentication scheme : <b>HTTP Basic</b><br>\r
45  * Authentication realm : <b>opendaylight</b><br>\r
46  * Transport : <b>HTTP and HTTPS</b><br>\r
47  * <br>\r
48  * HTTPS Authentication is disabled by default. Administrator can enable it in\r
49  * tomcat-server.xml after adding a proper keystore / SSL certificate from a\r
50  * trusted authority.<br>\r
51  * More info :\r
52  * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration\r
53  *\r
54  */\r
55 \r
56 @Path("/subnets")\r
57 public class NeutronSubnetsNorthbound {\r
58 \r
59     private NeutronSubnet extractFields(NeutronSubnet o, List<String> fields) {\r
60         return o.extractFields(fields);\r
61     }\r
62 \r
63 \r
64     /**\r
65      * Returns a list of all Subnets */\r
66     @GET\r
67     @Produces({ MediaType.APPLICATION_JSON })\r
68     //@TypeHint(OpenStackSubnets.class)\r
69     @StatusCodes({\r
70             @ResponseCode(code = 200, condition = "Operation successful"),\r
71             @ResponseCode(code = 401, condition = "Unauthorized"),\r
72             @ResponseCode(code = 501, condition = "Not Implemented") })\r
73     public Response listSubnets(\r
74             // return fields\r
75             @QueryParam("fields") List<String> fields,\r
76             // note: openstack isn't clear about filtering on lists, so we aren't handling them\r
77             @QueryParam("id") String queryID,\r
78             @QueryParam("network_id") String queryNetworkID,\r
79             @QueryParam("name") String queryName,\r
80             @QueryParam("ip_version") String queryIPVersion,\r
81             @QueryParam("cidr") String queryCIDR,\r
82             @QueryParam("gateway_ip") String queryGatewayIP,\r
83             @QueryParam("enable_dhcp") String queryEnableDHCP,\r
84             @QueryParam("tenant_id") String queryTenantID,\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         INeutronSubnetCRUD subnetInterface = NeutronNBInterfaces.getIfNBSubnetCRUD("default", this);\r
92         if (subnetInterface == null) {\r
93             throw new ServiceUnavailableException("Subnet CRUD Interface "\r
94                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
95         }\r
96         List<NeutronSubnet> allNetworks = subnetInterface.getAllSubnets();\r
97         List<NeutronSubnet> ans = new ArrayList<NeutronSubnet>();\r
98         Iterator<NeutronSubnet> i = allNetworks.iterator();\r
99         while (i.hasNext()) {\r
100             NeutronSubnet oSS = i.next();\r
101             if ((queryID == null || queryID.equals(oSS.getID())) &&\r
102                     (queryNetworkID == null || queryNetworkID.equals(oSS.getNetworkUUID())) &&\r
103                     (queryName == null || queryName.equals(oSS.getName())) &&\r
104                     (queryIPVersion == null || queryIPVersion.equals(oSS.getIpVersion())) &&\r
105                     (queryCIDR == null || queryCIDR.equals(oSS.getCidr())) &&\r
106                     (queryGatewayIP == null || queryGatewayIP.equals(oSS.getGatewayIP())) &&\r
107                     (queryEnableDHCP == null || queryEnableDHCP.equals(oSS.getEnableDHCP())) &&\r
108                     (queryTenantID == null || queryTenantID.equals(oSS.getTenantID()))) {\r
109                 if (fields.size() > 0)\r
110                     ans.add(extractFields(oSS,fields));\r
111                 else\r
112                     ans.add(oSS);\r
113             }\r
114         }\r
115         //TODO: apply pagination to results\r
116         return Response.status(200).entity(\r
117                 new NeutronSubnetRequest(ans)).build();\r
118     }\r
119 \r
120     /**\r
121      * Returns a specific Subnet */\r
122 \r
123     @Path("{subnetUUID}")\r
124     @GET\r
125     @Produces({ MediaType.APPLICATION_JSON })\r
126     //@TypeHint(OpenStackSubnets.class)\r
127     @StatusCodes({\r
128             @ResponseCode(code = 200, condition = "Operation successful"),\r
129             @ResponseCode(code = 401, condition = "Unauthorized"),\r
130             @ResponseCode(code = 404, condition = "Not Found"),\r
131             @ResponseCode(code = 501, condition = "Not Implemented") })\r
132     public Response showSubnet(\r
133             @PathParam("subnetUUID") String subnetUUID,\r
134             // return fields\r
135             @QueryParam("fields") List<String> fields) {\r
136         INeutronSubnetCRUD subnetInterface = NeutronNBInterfaces.getIfNBSubnetCRUD("default",this);\r
137         if (subnetInterface == null) {\r
138             throw new ServiceUnavailableException("Subnet CRUD Interface "\r
139                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
140         }\r
141         if (!subnetInterface.subnetExists(subnetUUID))\r
142             return Response.status(404).build();\r
143         if (fields.size() > 0) {\r
144             NeutronSubnet ans = subnetInterface.getSubnet(subnetUUID);\r
145             return Response.status(200).entity(\r
146                     new NeutronSubnetRequest(extractFields(ans, fields))).build();\r
147         } else\r
148             return Response.status(200).entity(\r
149                     new NeutronSubnetRequest(subnetInterface.getSubnet(subnetUUID))).build();\r
150     }\r
151 \r
152     /**\r
153      * Creates new Subnets */\r
154 \r
155     @POST\r
156     @Produces({ MediaType.APPLICATION_JSON })\r
157     @Consumes({ MediaType.APPLICATION_JSON })\r
158     //@TypeHint(OpenStackSubnets.class)\r
159     @StatusCodes({\r
160             @ResponseCode(code = 201, condition = "Created"),\r
161             @ResponseCode(code = 400, condition = "Bad Request"),\r
162             @ResponseCode(code = 401, condition = "Unauthorized"),\r
163             @ResponseCode(code = 403, condition = "Forbidden"),\r
164             @ResponseCode(code = 404, condition = "Not Found"),\r
165             @ResponseCode(code = 409, condition = "Conflict"),\r
166             @ResponseCode(code = 501, condition = "Not Implemented") })\r
167     public Response createSubnets(final NeutronSubnetRequest input) {\r
168         INeutronSubnetCRUD subnetInterface = NeutronNBInterfaces.getIfNBSubnetCRUD("default",this);\r
169         if (subnetInterface == null) {\r
170             throw new ServiceUnavailableException("Subnet CRUD Interface "\r
171                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
172         }\r
173         INeutronNetworkCRUD networkInterface = NeutronNBInterfaces.getIfNBNetworkCRUD("default", this);\r
174         if (networkInterface == null) {\r
175             throw new ServiceUnavailableException("Network CRUD Interface "\r
176                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
177         }\r
178         if (input.isSingleton()) {\r
179             NeutronSubnet singleton = input.getSingleton();\r
180 \r
181             /*\r
182              *  Verify that the subnet doesn't already exist (Issue: is a deeper check necessary?)\r
183              *  the specified network exists, the subnet has a valid network address,\r
184              *  and that the gateway IP doesn't overlap with the allocation pools\r
185              *  *then* add the subnet to the cache\r
186              */\r
187             if (subnetInterface.subnetExists(singleton.getID()))\r
188                 return Response.status(400).build();\r
189             if (!networkInterface.networkExists(singleton.getNetworkUUID()))\r
190                 return Response.status(404).build();\r
191             if (!singleton.isValidCIDR())\r
192                 return Response.status(400).build();\r
193             singleton.initDefaults();\r
194             if (singleton.gatewayIP_Pool_overlap())\r
195                 return Response.status(409).build();\r
196             Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null);\r
197             if (instances != null) {\r
198                 for (Object instance : instances) {\r
199                     INeutronSubnetAware service = (INeutronSubnetAware) instance;\r
200                     int status = service.canCreateSubnet(singleton);\r
201                     if (status < 200 || status > 299)\r
202                         return Response.status(status).build();\r
203                 }\r
204             }\r
205             subnetInterface.addSubnet(singleton);\r
206             if (instances != null) {\r
207                 for (Object instance : instances) {\r
208                     INeutronSubnetAware service = (INeutronSubnetAware) instance;\r
209                     service.neutronSubnetCreated(singleton);\r
210                 }\r
211             }\r
212         } else {\r
213             List<NeutronSubnet> bulk = input.getBulk();\r
214             Iterator<NeutronSubnet> i = bulk.iterator();\r
215             HashMap<String, NeutronSubnet> testMap = new HashMap<String, NeutronSubnet>();\r
216             Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null);\r
217             while (i.hasNext()) {\r
218                 NeutronSubnet test = i.next();\r
219 \r
220                 /*\r
221                  *  Verify that the subnet doesn't already exist (Issue: is a deeper check necessary?)\r
222                  *  the specified network exists, the subnet has a valid network address,\r
223                  *  and that the gateway IP doesn't overlap with the allocation pools,\r
224                  *  and that the bulk request doesn't already contain a subnet with this id\r
225                  */\r
226 \r
227                 test.initDefaults();\r
228                 if (subnetInterface.subnetExists(test.getID()))\r
229                     return Response.status(400).build();\r
230                 if (testMap.containsKey(test.getID()))\r
231                     return Response.status(400).build();\r
232                 testMap.put(test.getID(), test);\r
233                 if (!networkInterface.networkExists(test.getNetworkUUID()))\r
234                     return Response.status(404).build();\r
235                 if (!test.isValidCIDR())\r
236                     return Response.status(400).build();\r
237                 if (test.gatewayIP_Pool_overlap())\r
238                     return Response.status(409).build();\r
239                 if (instances != null) {\r
240                     for (Object instance : instances) {\r
241                         INeutronSubnetAware service = (INeutronSubnetAware) instance;\r
242                         int status = service.canCreateSubnet(test);\r
243                         if (status < 200 || status > 299)\r
244                             return Response.status(status).build();\r
245                     }\r
246                 }\r
247             }\r
248 \r
249             /*\r
250              * now, each element of the bulk request can be added to the cache\r
251              */\r
252             i = bulk.iterator();\r
253             while (i.hasNext()) {\r
254                 NeutronSubnet test = i.next();\r
255                 subnetInterface.addSubnet(test);\r
256                 if (instances != null) {\r
257                     for (Object instance : instances) {\r
258                         INeutronSubnetAware service = (INeutronSubnetAware) instance;\r
259                         service.neutronSubnetCreated(test);\r
260                     }\r
261                 }\r
262             }\r
263         }\r
264         return Response.status(201).entity(input).build();\r
265     }\r
266 \r
267     /**\r
268      * Updates a Subnet */\r
269 \r
270     @Path("{subnetUUID}")\r
271     @PUT\r
272     @Produces({ MediaType.APPLICATION_JSON })\r
273     @Consumes({ MediaType.APPLICATION_JSON })\r
274     //@TypeHint(OpenStackSubnets.class)\r
275     @StatusCodes({\r
276             @ResponseCode(code = 200, condition = "Operation successful"),\r
277             @ResponseCode(code = 400, condition = "Bad Request"),\r
278             @ResponseCode(code = 401, condition = "Unauthorized"),\r
279             @ResponseCode(code = 403, condition = "Forbidden"),\r
280             @ResponseCode(code = 404, condition = "Not Found"),\r
281             @ResponseCode(code = 501, condition = "Not Implemented") })\r
282     public Response updateSubnet(\r
283             @PathParam("subnetUUID") String subnetUUID, final NeutronSubnetRequest input\r
284             ) {\r
285         INeutronSubnetCRUD subnetInterface = NeutronNBInterfaces.getIfNBSubnetCRUD("default", this);\r
286         if (subnetInterface == null) {\r
287             throw new ServiceUnavailableException("Subnet CRUD Interface "\r
288                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
289         }\r
290 \r
291         /*\r
292          * verify the subnet exists and there is only one delta provided\r
293          */\r
294         if (!subnetInterface.subnetExists(subnetUUID))\r
295             return Response.status(404).build();\r
296         if (!input.isSingleton())\r
297             return Response.status(400).build();\r
298         NeutronSubnet delta = input.getSingleton();\r
299         NeutronSubnet original = subnetInterface.getSubnet(subnetUUID);\r
300 \r
301         /*\r
302          * updates restricted by Neutron\r
303          */\r
304         if (delta.getID() != null || delta.getTenantID() != null ||\r
305                 delta.getIpVersion() != null || delta.getCidr() != null ||\r
306                 delta.getAllocationPools() != null)\r
307             return Response.status(400).build();\r
308 \r
309         Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null);\r
310         if (instances != null) {\r
311             for (Object instance : instances) {\r
312                 INeutronSubnetAware service = (INeutronSubnetAware) instance;\r
313                 int status = service.canUpdateSubnet(delta, original);\r
314                 if (status < 200 || status > 299)\r
315                     return Response.status(status).build();\r
316             }\r
317         }\r
318 \r
319         /*\r
320          * update the object and return it\r
321          */\r
322         subnetInterface.updateSubnet(subnetUUID, delta);\r
323         NeutronSubnet updatedSubnet = subnetInterface.getSubnet(subnetUUID);\r
324         if (instances != null) {\r
325             for (Object instance : instances) {\r
326                 INeutronSubnetAware service = (INeutronSubnetAware) instance;\r
327                 service.neutronSubnetUpdated(updatedSubnet);\r
328             }\r
329         }\r
330         return Response.status(200).entity(\r
331                 new NeutronSubnetRequest(subnetInterface.getSubnet(subnetUUID))).build();\r
332     }\r
333 \r
334     /**\r
335      * Deletes a Subnet */\r
336 \r
337     @Path("{subnetUUID}")\r
338     @DELETE\r
339     @StatusCodes({\r
340             @ResponseCode(code = 204, condition = "No Content"),\r
341             @ResponseCode(code = 401, condition = "Unauthorized"),\r
342             @ResponseCode(code = 404, condition = "Not Found"),\r
343             @ResponseCode(code = 409, condition = "Conflict"),\r
344             @ResponseCode(code = 501, condition = "Not Implemented") })\r
345     public Response deleteSubnet(\r
346             @PathParam("subnetUUID") String subnetUUID) {\r
347         INeutronSubnetCRUD subnetInterface = NeutronNBInterfaces.getIfNBSubnetCRUD("default", this);\r
348         if (subnetInterface == null) {\r
349             throw new ServiceUnavailableException("Network CRUD Interface "\r
350                     + RestMessages.SERVICEUNAVAILABLE.toString());\r
351         }\r
352 \r
353         /*\r
354          * verify the subnet exists and it isn't currently in use\r
355          */\r
356         if (!subnetInterface.subnetExists(subnetUUID))\r
357             return Response.status(404).build();\r
358         if (subnetInterface.subnetInUse(subnetUUID))\r
359             return Response.status(409).build();\r
360         NeutronSubnet singleton = subnetInterface.getSubnet(subnetUUID);\r
361         Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null);\r
362         if (instances != null) {\r
363             for (Object instance : instances) {\r
364                 INeutronSubnetAware service = (INeutronSubnetAware) instance;\r
365                 int status = service.canDeleteSubnet(singleton);\r
366                 if (status < 200 || status > 299)\r
367                     return Response.status(status).build();\r
368             }\r
369         }\r
370 \r
371         /*\r
372          * remove it and return 204 status\r
373          */\r
374         subnetInterface.removeSubnet(subnetUUID);\r
375         if (instances != null) {\r
376             for (Object instance : instances) {\r
377                 INeutronSubnetAware service = (INeutronSubnetAware) instance;\r
378                 service.neutronSubnetDeleted(singleton);\r
379             }\r
380         }\r
381         return Response.status(204).build();\r
382     }\r
383 }\r