propagate datastore exceptions all the way to northbound
[neutron.git] / northbound-api / src / main / java / org / opendaylight / neutron / northbound / api / NeutronLoadBalancerPoolNorthbound.java
1 /*
2  * Copyright (c) 2014, 2015 SDN Hub, LLC. 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 package org.opendaylight.neutron.northbound.api;
9
10 import static java.net.HttpURLConnection.HTTP_OK;
11
12 import java.net.HttpURLConnection;
13 import java.util.ArrayList;
14 import java.util.List;
15 import javax.inject.Inject;
16 import javax.inject.Singleton;
17 import javax.ws.rs.Consumes;
18 import javax.ws.rs.DELETE;
19 import javax.ws.rs.GET;
20 import javax.ws.rs.POST;
21 import javax.ws.rs.PUT;
22 import javax.ws.rs.Path;
23 import javax.ws.rs.PathParam;
24 import javax.ws.rs.Produces;
25 import javax.ws.rs.QueryParam;
26 import javax.ws.rs.core.MediaType;
27 import javax.ws.rs.core.Response;
28 import org.codehaus.enunciate.jaxrs.ResponseCode;
29 import org.codehaus.enunciate.jaxrs.StatusCodes;
30 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
31 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
32 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
33 import org.opendaylight.neutron.spi.INeutronLoadBalancerPoolCRUD;
34 import org.opendaylight.neutron.spi.NeutronLoadBalancerPool;
35 import org.opendaylight.neutron.spi.NeutronLoadBalancerPoolMember;
36 import org.opendaylight.yangtools.yang.common.OperationFailedException;
37 import org.ops4j.pax.cdi.api.OsgiService;
38
39 /**
40  * Neutron Northbound REST APIs for LoadBalancerPool Policies.
41  *
42  * <p>For now, the LB pool member data is maintained with the INeutronLoadBalancerPoolCRUD,
43  * and not duplicated within the INeutronLoadBalancerPoolMemberCRUD's cache.
44  */
45 @Singleton
46 @Path("/lbaas/pools")
47 public final class NeutronLoadBalancerPoolNorthbound extends AbstractNeutronNorthbound<NeutronLoadBalancerPool,
48         NeutronLoadBalancerPoolRequest, INeutronLoadBalancerPoolCRUD> {
49
50     private static final String RESOURCE_NAME = "LoadBalancerPool";
51
52     private final DataBroker dataBroker;
53
54     @Inject
55     public NeutronLoadBalancerPoolNorthbound(
56             @OsgiService INeutronLoadBalancerPoolCRUD neutronCRUD,
57             @OsgiService DataBroker dataBroker) {
58         super(neutronCRUD);
59         this.dataBroker = dataBroker;
60     }
61
62     @Override
63     protected String getResourceName() {
64         return RESOURCE_NAME;
65     }
66
67     /**
68      * Returns a list of all LoadBalancerPool.
69      * */
70     @GET
71     @Produces({ MediaType.APPLICATION_JSON })
72     @StatusCodes({ @ResponseCode(code = HttpURLConnection.HTTP_OK, condition = "Operation successful"),
73             @ResponseCode(code = HttpURLConnection.HTTP_UNAUTHORIZED, condition = "Unauthorized"),
74             @ResponseCode(code = HttpURLConnection.HTTP_NOT_IMPLEMENTED, condition = "Not Implemented"),
75             @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
76     public Response listGroups(
77             // return fields
78             @QueryParam("fields") List<String> fields,
79             // OpenStack LoadBalancerPool attributes
80             @QueryParam("id") String queryLoadBalancerPoolID,
81             @QueryParam("tenant_id") String queryLoadBalancerPoolTenantID,
82             @QueryParam("name") String queryLoadBalancerPoolName,
83             @QueryParam("protocol") String queryLoadBalancerProtocol,
84             @QueryParam("lb_algorithm") String queryLoadBalancerPoolLbAlgorithm,
85             @QueryParam("healthmonitor_id") String queryLoadBalancerPoolHealthMonitorID,
86             @QueryParam("admin_state_up") Boolean queryLoadBalancerIsAdminStateUp,
87             @QueryParam("members") List<NeutronLoadBalancerPoolMember> queryLoadBalancerPoolMembers,
88             // pagination
89             @QueryParam("limit") String limit,
90             @QueryParam("marker") String marker,
91             @QueryParam("page_reverse") String pageReverse
92     // sorting not supported
93     ) {
94         INeutronLoadBalancerPoolCRUD loadBalancerPoolInterface = getNeutronCRUD();
95         List<NeutronLoadBalancerPool> allLoadBalancerPools = loadBalancerPoolInterface.getAll();
96         List<NeutronLoadBalancerPool> ans = new ArrayList<>();
97         for (NeutronLoadBalancerPool nsg : allLoadBalancerPools) {
98             if ((queryLoadBalancerPoolID == null || queryLoadBalancerPoolID.equals(nsg.getID()))
99                     && (queryLoadBalancerPoolTenantID == null
100                             || queryLoadBalancerPoolTenantID.equals(nsg.getTenantID()))
101                     && (queryLoadBalancerPoolName == null
102                             || queryLoadBalancerPoolName.equals(nsg.getName()))
103                     && (queryLoadBalancerPoolLbAlgorithm == null
104                             || queryLoadBalancerPoolLbAlgorithm.equals(nsg.getLoadBalancerPoolLbAlgorithm()))
105                     && (queryLoadBalancerPoolHealthMonitorID == null || queryLoadBalancerPoolHealthMonitorID
106                             .equals(nsg.getLoadBalancerPoolHealthMonitorID()))
107                     && (queryLoadBalancerIsAdminStateUp == null
108                             || queryLoadBalancerIsAdminStateUp.equals(nsg.getLoadBalancerPoolAdminIsStateIsUp()))
109                     && (queryLoadBalancerPoolMembers.size() == 0
110                             || queryLoadBalancerPoolMembers.equals(nsg.getLoadBalancerPoolMembers()))) {
111                 if (fields.size() > 0) {
112                     ans.add(nsg.extractFields(fields));
113                 } else {
114                     ans.add(nsg);
115                 }
116             }
117         }
118         return Response.status(HttpURLConnection.HTTP_OK).entity(new NeutronLoadBalancerPoolRequest(ans)).build();
119     }
120
121     /**
122      * Returns a specific LoadBalancerPool.
123      */
124     @Path("{loadBalancerPoolID}")
125     @GET
126     @Produces({ MediaType.APPLICATION_JSON })
127     @StatusCodes({ @ResponseCode(code = HttpURLConnection.HTTP_OK, condition = "Operation successful"),
128             @ResponseCode(code = HttpURLConnection.HTTP_UNAUTHORIZED, condition = "Unauthorized"),
129             @ResponseCode(code = HttpURLConnection.HTTP_NOT_FOUND, condition = "Not Found"),
130             @ResponseCode(code = HttpURLConnection.HTTP_NOT_IMPLEMENTED, condition = "Not Implemented"),
131             @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
132     public Response showLoadBalancerPool(@PathParam("loadBalancerPoolID") String loadBalancerPoolID,
133             // return fields
134             @QueryParam("fields") List<String> fields) {
135         return show(loadBalancerPoolID, fields);
136     }
137
138     /**
139      * Creates new LoadBalancerPool.
140      */
141     @POST
142     @Produces({ MediaType.APPLICATION_JSON })
143     @Consumes({ MediaType.APPLICATION_JSON })
144     @StatusCodes({ @ResponseCode(code = HttpURLConnection.HTTP_CREATED, condition = "Created"),
145             @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
146     public Response createLoadBalancerPools(final NeutronLoadBalancerPoolRequest input) {
147         return create(input);
148     }
149
150     /**
151      * Updates a LoadBalancerPool Policy.
152      */
153     @Path("{loadBalancerPoolID}")
154     @PUT
155     @Produces({ MediaType.APPLICATION_JSON })
156     @Consumes({ MediaType.APPLICATION_JSON })
157     @StatusCodes({ @ResponseCode(code = HttpURLConnection.HTTP_OK, condition = "Operation successful"),
158             @ResponseCode(code = HttpURLConnection.HTTP_NOT_FOUND, condition = "Not Found"),
159             @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
160     public Response updateLoadBalancerPool(@PathParam("loadBalancerPoolID") String loadBalancerPoolID,
161             final NeutronLoadBalancerPoolRequest input) {
162         return update(loadBalancerPoolID, input);
163     }
164
165     /**
166      * Deletes a LoadBalancerPool.
167      */
168     @Path("{loadBalancerPoolUUID}")
169     @DELETE
170     @StatusCodes({ @ResponseCode(code = HttpURLConnection.HTTP_NO_CONTENT, condition = "No Content"),
171             @ResponseCode(code = HttpURLConnection.HTTP_NOT_FOUND, condition = "Not Found"),
172             @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
173     public Response deleteLoadBalancerPool(@PathParam("loadBalancerPoolUUID") String loadBalancerPoolUUID) {
174         return delete(loadBalancerPoolUUID);
175     }
176
177     /**
178      * Returns a list of all LoadBalancerPoolMembers in specified pool.
179      */
180     @Path("{loadBalancerPoolUUID}/members")
181     @GET
182     @Produces({ MediaType.APPLICATION_JSON })
183     @StatusCodes({ @ResponseCode(code = HttpURLConnection.HTTP_OK, condition = "Operation successful"),
184             @ResponseCode(code = HttpURLConnection.HTTP_UNAUTHORIZED, condition = "Unauthorized"),
185             @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
186     public Response listMembers(
187             //Path param
188             @PathParam("loadBalancerPoolUUID") String loadBalancerPoolUUID,
189
190             // return fields
191             @QueryParam("fields") List<String> fields,
192
193             // OpenStack LoadBalancerPool attributes
194             @QueryParam("id") String queryLoadBalancerPoolMemberID,
195             @QueryParam("tenant_id") String queryLoadBalancerPoolMemberTenantID,
196             @QueryParam("address") String queryLoadBalancerPoolMemberAddress,
197             @QueryParam("protocol_port") String queryLoadBalancerPoolMemberProtoPort,
198             @QueryParam("admin_state_up") Boolean queryLoadBalancerPoolMemberAdminStateUp,
199             @QueryParam("weight") Integer queryLoadBalancerPoolMemberWeight,
200             @QueryParam("subnet_id") String queryLoadBalancerPoolMemberSubnetID,
201
202             // pagination
203             @QueryParam("limit") String limit,
204             @QueryParam("marker") String marker,
205             @QueryParam("page_reverse") String pageReverse
206     // sorting not supported
207     ) {
208         INeutronLoadBalancerPoolCRUD loadBalancerPoolInterface = getNeutronCRUD();
209         try {
210             try (ReadOnlyTransaction tx = dataBroker.newReadOnlyTransaction()) {
211                 if (!loadBalancerPoolInterface.exists(loadBalancerPoolUUID, tx)) {
212                     throw new ResourceNotFoundException(uuidNoExist());
213                 }
214             }
215             List<NeutronLoadBalancerPoolMember> members = loadBalancerPoolInterface.get(loadBalancerPoolUUID)
216                     .getLoadBalancerPoolMembers();
217             List<NeutronLoadBalancerPoolMember> ans = new ArrayList<>();
218             for (NeutronLoadBalancerPoolMember nsg : members) {
219                 if ((queryLoadBalancerPoolMemberID == null || queryLoadBalancerPoolMemberID.equals(nsg.getID()))
220                         && loadBalancerPoolUUID.equals(nsg.getPoolID())
221                         && (queryLoadBalancerPoolMemberTenantID == null
222                                 || queryLoadBalancerPoolMemberTenantID.equals(nsg.getTenantID()))
223                         && (queryLoadBalancerPoolMemberAddress == null
224                                 || queryLoadBalancerPoolMemberAddress.equals(nsg.getPoolMemberAddress()))
225                         && (queryLoadBalancerPoolMemberAdminStateUp == null
226                                 || queryLoadBalancerPoolMemberAdminStateUp.equals(nsg.getPoolMemberAdminStateIsUp()))
227                         && (queryLoadBalancerPoolMemberWeight == null
228                                 || queryLoadBalancerPoolMemberWeight.equals(nsg.getPoolMemberWeight()))
229                         && (queryLoadBalancerPoolMemberSubnetID == null
230                                 || queryLoadBalancerPoolMemberSubnetID.equals(nsg.getPoolMemberSubnetID()))) {
231                     if (fields.size() > 0) {
232                         ans.add(nsg.extractFields(fields));
233                     } else {
234                         ans.add(nsg);
235                     }
236                 }
237             }
238             return Response.status(HTTP_OK).entity(new NeutronLoadBalancerPoolMemberRequest(ans)).build();
239         } catch (ReadFailedException e) {
240             throw new DatastoreOperationFailedWebApplicationException(e);
241         }
242     }
243
244     /**
245      * Returns a specific LoadBalancerPoolMember.
246      */
247     @Path("{loadBalancerPoolUUID}/members/{loadBalancerPoolMemberUUID}")
248     @GET
249     @Produces({ MediaType.APPLICATION_JSON })
250     //@TypeHint(OpenStackLoadBalancerPoolMembers.class)
251     @StatusCodes({ @ResponseCode(code = HttpURLConnection.HTTP_OK, condition = "Operation successful"),
252             @ResponseCode(code = HttpURLConnection.HTTP_UNAUTHORIZED, condition = "Unauthorized"),
253             @ResponseCode(code = HttpURLConnection.HTTP_NOT_FOUND, condition = "Not Found"),
254             @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
255     public Response showLoadBalancerPoolMember(@PathParam("loadBalancerPoolUUID") String loadBalancerPoolUUID,
256             @PathParam("loadBalancerPoolMemberUUID") String loadBalancerPoolMemberUUID,
257             // return fields
258             @QueryParam("fields") List<String> fields) {
259
260         try {
261             INeutronLoadBalancerPoolCRUD loadBalancerPoolInterface = getNeutronCRUD();
262             try (ReadOnlyTransaction tx = dataBroker.newReadOnlyTransaction()) {
263                 if (!loadBalancerPoolInterface.exists(loadBalancerPoolUUID, tx)) {
264                     throw new ResourceNotFoundException(uuidNoExist());
265                 }
266             }
267             List<NeutronLoadBalancerPoolMember> members = loadBalancerPoolInterface.get(loadBalancerPoolUUID)
268                     .getLoadBalancerPoolMembers();
269             for (NeutronLoadBalancerPoolMember ans : members) {
270                 if (!ans.getID().equals(loadBalancerPoolMemberUUID)) {
271                     continue;
272                 }
273
274                 if (fields.size() > 0) {
275                     return Response.status(HttpURLConnection.HTTP_OK)
276                             .entity(new NeutronLoadBalancerPoolMemberRequest(ans.extractFields(fields))).build();
277                 } else {
278                     return Response.status(HttpURLConnection.HTTP_OK)
279                             .entity(new NeutronLoadBalancerPoolMemberRequest(ans)).build();
280                 }
281             }
282             throw new ResourceNotFoundException(uuidNoExist());
283         } catch (ReadFailedException e) {
284             throw new DatastoreOperationFailedWebApplicationException(e);
285         }
286     }
287
288     /**
289      * Adds a Member to an LBaaS Pool member.
290      */
291     @Path("{loadBalancerPoolUUID}/members")
292     @POST
293     @Produces({ MediaType.APPLICATION_JSON })
294     @Consumes({ MediaType.APPLICATION_JSON })
295     @StatusCodes({ @ResponseCode(code = HttpURLConnection.HTTP_OK, condition = "Operation successful"),
296             @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
297     public Response createLoadBalancerPoolMember(@PathParam("loadBalancerPoolUUID") String loadBalancerPoolUUID,
298             final NeutronLoadBalancerPoolMemberRequest input) {
299         try {
300             INeutronLoadBalancerPoolCRUD loadBalancerPoolInterface = getNeutronCRUD();
301
302             if (input.isSingleton()) {
303                 NeutronLoadBalancerPoolMember singleton = input.getSingleton();
304                 singleton.setPoolID(loadBalancerPoolUUID);
305                 /**
306                  * Add the member from the neutron load balancer pool as well
307                  */
308
309                 loadBalancerPoolInterface.addNeutronLoadBalancerPoolMember(loadBalancerPoolUUID, singleton);
310             } else {
311                 /*
312                  * now, each element of the bulk request can be added to the cache
313                  */
314                 for (NeutronLoadBalancerPoolMember test : input.getBulk()) {
315                     loadBalancerPoolInterface.addNeutronLoadBalancerPoolMember(loadBalancerPoolUUID, test);
316                 }
317             }
318             return Response.status(HttpURLConnection.HTTP_CREATED).entity(input).build();
319         } catch (OperationFailedException e) {
320             throw new DatastoreOperationFailedWebApplicationException(e);
321         }
322     }
323
324     /**
325      * Updates a LB member pool.
326      */
327     @Path("{loadBalancerPoolUUID}/members/{loadBalancerPoolMemberUUID}")
328     @PUT
329     @Produces({ MediaType.APPLICATION_JSON })
330     @Consumes({ MediaType.APPLICATION_JSON })
331     @StatusCodes({ @ResponseCode(code = HttpURLConnection.HTTP_OK, condition = "Operation successful"),
332             @ResponseCode(code = HttpURLConnection.HTTP_NOT_FOUND, condition = "Not Found") })
333     public Response updateLoadBalancerPoolMember(@PathParam("loadBalancerPoolUUID") String loadBalancerPoolUUID,
334             @PathParam("loadBalancerPoolMemberUUID") String loadBalancerPoolMemberUUID,
335             final NeutronLoadBalancerPoolMemberRequest input) {
336         try {
337             INeutronLoadBalancerPoolCRUD loadBalancerPoolInterface = getNeutronCRUD();
338             NeutronLoadBalancerPool singletonPool = loadBalancerPoolInterface.get(loadBalancerPoolUUID);
339             NeutronLoadBalancerPoolMember singleton = input.getSingleton();
340             singleton.setPoolID(loadBalancerPoolUUID);
341
342             if (singletonPool == null) {
343                 throw new ResourceNotFoundException("Pool doesn't Exist");
344             }
345             loadBalancerPoolInterface.updateNeutronLoadBalancerPoolMember(loadBalancerPoolUUID,
346                     loadBalancerPoolMemberUUID, singleton);
347             return Response.status(HttpURLConnection.HTTP_OK).entity(input).build();
348         } catch (OperationFailedException e) {
349             throw new DatastoreOperationFailedWebApplicationException(e);
350         }
351     }
352
353     /**
354      * Deletes a LoadBalancerPoolMember.
355      */
356     @Path("{loadBalancerPoolUUID}/members/{loadBalancerPoolMemberUUID}")
357     @DELETE
358     @StatusCodes({ @ResponseCode(code = HttpURLConnection.HTTP_NO_CONTENT, condition = "No Content"),
359             @ResponseCode(code = HttpURLConnection.HTTP_NOT_FOUND, condition = "Not Found"),
360             @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
361     public Response deleteLoadBalancerPoolMember(@PathParam("loadBalancerPoolUUID") String loadBalancerPoolUUID,
362             @PathParam("loadBalancerPoolMemberUUID") String loadBalancerPoolMemberUUID) {
363         try {
364             INeutronLoadBalancerPoolCRUD loadBalancerPoolInterface = getNeutronCRUD();
365             // Verify that the LB pool member exists
366             NeutronLoadBalancerPoolMember singleton = null;
367             List<NeutronLoadBalancerPoolMember> members = loadBalancerPoolInterface.get(loadBalancerPoolUUID)
368                     .getLoadBalancerPoolMembers();
369             for (NeutronLoadBalancerPoolMember member : members) {
370                 if (member.getID().equals(loadBalancerPoolMemberUUID)) {
371                     singleton = member;
372                     break;
373                 }
374             }
375             if (singleton == null) {
376                 throw new BadRequestException("LoadBalancerPoolMember UUID does not exist.");
377             }
378
379             /**
380              * Remove the member from the neutron load balancer pool
381              */
382             loadBalancerPoolInterface.removeNeutronLoadBalancerPoolMember(loadBalancerPoolUUID,
383                     loadBalancerPoolMemberUUID);
384
385             return Response.status(HttpURLConnection.HTTP_NO_CONTENT).build();
386         } catch (OperationFailedException e) {
387             throw new DatastoreOperationFailedWebApplicationException(e);
388         }
389     }
390 }