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