Fix create of LBaaS pool members
[neutron.git] / northbound-api / src / main / java / org / opendaylight / neutron / northbound / api / NeutronLoadBalancerPoolMembersNorthbound.java
1 /*
2  * Copyright (C) 2014 SDN Hub, LLC.
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  * Authors : Srini Seetharaman
9  */
10
11 package org.opendaylight.neutron.northbound.api;
12
13 import java.net.HttpURLConnection;
14
15 import java.util.ArrayList;
16 import java.util.HashMap;
17 import java.util.Iterator;
18 import java.util.List;
19 import java.util.Map;
20
21 import javax.ws.rs.Consumes;
22 import javax.ws.rs.DELETE;
23 import javax.ws.rs.GET;
24 import javax.ws.rs.POST;
25 import javax.ws.rs.PUT;
26 import javax.ws.rs.Path;
27 import javax.ws.rs.PathParam;
28 import javax.ws.rs.Produces;
29 import javax.ws.rs.QueryParam;
30 import javax.ws.rs.core.MediaType;
31 import javax.ws.rs.core.Response;
32
33 import org.codehaus.enunciate.jaxrs.ResponseCode;
34 import org.codehaus.enunciate.jaxrs.StatusCodes;
35 import org.opendaylight.neutron.spi.INeutronLoadBalancerPoolCRUD;
36 import org.opendaylight.neutron.spi.INeutronLoadBalancerPoolMemberAware;
37 import org.opendaylight.neutron.spi.NeutronCRUDInterfaces;
38 import org.opendaylight.neutron.spi.NeutronLoadBalancerPool;
39 import org.opendaylight.neutron.spi.NeutronLoadBalancerPoolMember;
40
41 @Path("/lbaas/pools/{loadBalancerPoolUUID}/members")
42 public class NeutronLoadBalancerPoolMembersNorthbound {
43     private static final int HTTP_OK_BOTTOM = 200;
44     private static final int HTTP_OK_TOP = 299;
45     private static final String INTERFACE_NAME = "LoadBalancerPool CRUD Interface";
46     private static final String UUID_NO_EXIST = "LoadBalancerPool UUID does not exist.";
47     private static final String NO_PROVIDERS = "No providers registered.  Please try again later";
48     private static final String NO_PROVIDER_LIST = "Couldn't get providers list.  Please try again later";
49
50     private NeutronLoadBalancerPoolMember extractFields(NeutronLoadBalancerPoolMember o, List<String> fields) {
51         return o.extractFields(fields);
52     }
53
54     private NeutronCRUDInterfaces getNeutronInterfaces() {
55         NeutronCRUDInterfaces answer = new NeutronCRUDInterfaces().fetchINeutronLoadBalancerPoolCRUD(this);
56         if (answer.getLoadBalancerPoolInterface() == null) {
57             throw new ServiceUnavailableException(INTERFACE_NAME
58                 + RestMessages.SERVICEUNAVAILABLE.toString());
59         }
60         return answer;
61     }
62
63 /**
64  * Returns a list of all LoadBalancerPoolMembers in specified pool
65  */
66 @GET
67 @Produces({MediaType.APPLICATION_JSON})
68 @StatusCodes({
69         @ResponseCode(code = HttpURLConnection.HTTP_OK, condition = "Operation successful"),
70         @ResponseCode(code = HttpURLConnection.HTTP_UNAUTHORIZED, condition = "Unauthorized"),
71         @ResponseCode(code = HttpURLConnection.HTTP_NOT_IMPLEMENTED, condition = "Not Implemented"),
72         @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
73
74 public Response listMembers(
75         //Path param
76         @PathParam("loadBalancerPoolUUID") String loadBalancerPoolUUID,
77
78         // return fields
79         @QueryParam("fields") List<String> fields,
80
81         // OpenStack LoadBalancerPool attributes
82         @QueryParam("id") String queryLoadBalancerPoolMemberID,
83         @QueryParam("tenant_id") String queryLoadBalancerPoolMemberTenantID,
84         @QueryParam("address") String queryLoadBalancerPoolMemberAddress,
85         @QueryParam("protocol_port") String queryLoadBalancerPoolMemberProtoPort,
86         @QueryParam("admin_state_up") String queryLoadBalancerPoolMemberAdminStateUp,
87         @QueryParam("weight") String queryLoadBalancerPoolMemberWeight,
88         @QueryParam("subnet_id") String queryLoadBalancerPoolMemberSubnetID,
89
90         // pagination
91         @QueryParam("limit") String limit,
92         @QueryParam("marker") String marker,
93         @QueryParam("page_reverse") String pageReverse
94         // sorting not supported
95 ) {
96     INeutronLoadBalancerPoolCRUD loadBalancerPoolInterface = getNeutronInterfaces().getLoadBalancerPoolInterface();
97     if (!loadBalancerPoolInterface.neutronLoadBalancerPoolExists(loadBalancerPoolUUID)) {
98         throw new ResourceNotFoundException(UUID_NO_EXIST);
99     }
100     List<NeutronLoadBalancerPoolMember> members =
101                 loadBalancerPoolInterface.getNeutronLoadBalancerPool(loadBalancerPoolUUID).getLoadBalancerPoolMembers();
102     List<NeutronLoadBalancerPoolMember> ans = new ArrayList<NeutronLoadBalancerPoolMember>();
103     Iterator<NeutronLoadBalancerPoolMember> i = members.iterator();
104     while (i.hasNext()) {
105         NeutronLoadBalancerPoolMember nsg = i.next();
106         if ((queryLoadBalancerPoolMemberID == null ||
107                 queryLoadBalancerPoolMemberID.equals(nsg.getPoolMemberID())) &&
108                 loadBalancerPoolUUID.equals(nsg.getPoolID()) &&
109                 (queryLoadBalancerPoolMemberTenantID == null ||
110                         queryLoadBalancerPoolMemberTenantID.equals(nsg.getPoolMemberTenantID())) &&
111                 (queryLoadBalancerPoolMemberAddress == null ||
112                         queryLoadBalancerPoolMemberAddress.equals(nsg.getPoolMemberAddress())) &&
113                 (queryLoadBalancerPoolMemberAdminStateUp == null ||
114                         queryLoadBalancerPoolMemberAdminStateUp.equals(nsg.getPoolMemberAdminStateIsUp())) &&
115                 (queryLoadBalancerPoolMemberWeight == null ||
116                         queryLoadBalancerPoolMemberWeight.equals(nsg.getPoolMemberWeight())) &&
117                 (queryLoadBalancerPoolMemberSubnetID == null ||
118                         queryLoadBalancerPoolMemberSubnetID.equals(nsg.getPoolMemberSubnetID()))) {
119             if (fields.size() > 0) {
120                 ans.add(extractFields(nsg, fields));
121             } else {
122                 ans.add(nsg);
123             }
124         }
125     }
126     return Response.status(HttpURLConnection.HTTP_OK).entity(
127             new NeutronLoadBalancerPoolMemberRequest(ans)).build();
128 }
129
130 /**
131  * Returns a specific LoadBalancerPoolMember
132  */
133
134 @Path("{loadBalancerPoolMemberUUID}")
135 @GET
136 @Produces({ MediaType.APPLICATION_JSON })
137 //@TypeHint(OpenStackLoadBalancerPoolMembers.class)
138 @StatusCodes({
139     @ResponseCode(code = HttpURLConnection.HTTP_OK, condition = "Operation successful"),
140     @ResponseCode(code = HttpURLConnection.HTTP_UNAUTHORIZED, condition = "Unauthorized"),
141     @ResponseCode(code = HttpURLConnection.HTTP_NOT_FOUND, condition = "Not Found"),
142     @ResponseCode(code = HttpURLConnection.HTTP_NOT_IMPLEMENTED, condition = "Not Implemented"),
143     @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
144 public Response showLoadBalancerPoolMember(
145         @PathParam("loadBalancerPoolUUID") String loadBalancerPoolUUID,
146         @PathParam("loadBalancerPoolMemberUUID") String loadBalancerPoolMemberUUID,
147         // return fields
148         @QueryParam("fields") List<String> fields ) {
149
150     INeutronLoadBalancerPoolCRUD loadBalancerPoolInterface = getNeutronInterfaces().getLoadBalancerPoolInterface();
151     if (!loadBalancerPoolInterface.neutronLoadBalancerPoolExists(loadBalancerPoolUUID)) {
152         throw new ResourceNotFoundException(UUID_NO_EXIST);
153     }
154     List<NeutronLoadBalancerPoolMember> members =
155                 loadBalancerPoolInterface.getNeutronLoadBalancerPool(loadBalancerPoolUUID).getLoadBalancerPoolMembers();
156     for (NeutronLoadBalancerPoolMember ans: members) {
157         if (!ans.getPoolMemberID().equals(loadBalancerPoolMemberUUID)) {
158             continue;
159         }
160
161         if (fields.size() > 0) {
162             return Response.status(HttpURLConnection.HTTP_OK).entity(
163                 new NeutronLoadBalancerPoolMemberRequest(extractFields(ans, fields))).build();
164         } else {
165             return Response.status(HttpURLConnection.HTTP_OK).entity(
166                 new NeutronLoadBalancerPoolMemberRequest(ans)).build();
167         }
168     }
169     return Response.status(HttpURLConnection.HTTP_NO_CONTENT).build();
170 }
171
172 /**
173  * Adds a Member to an LBaaS Pool member
174  */
175 @POST
176 @Produces({MediaType.APPLICATION_JSON})
177 @Consumes({MediaType.APPLICATION_JSON})
178 @StatusCodes({
179         @ResponseCode(code = HttpURLConnection.HTTP_OK, condition = "Operation successful"),
180         @ResponseCode(code = HttpURLConnection.HTTP_UNAUTHORIZED, condition = "Unauthorized"),
181         @ResponseCode(code = HttpURLConnection.HTTP_NOT_FOUND, condition = "Not Found"),
182         @ResponseCode(code = HttpURLConnection.HTTP_NOT_IMPLEMENTED, condition = "Not Implemented"),
183         @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
184 public Response createLoadBalancerPoolMember(
185         @PathParam("loadBalancerPoolUUID") String loadBalancerPoolUUID,
186         final NeutronLoadBalancerPoolMemberRequest input) {
187
188     INeutronLoadBalancerPoolCRUD loadBalancerPoolInterface = getNeutronInterfaces().getLoadBalancerPoolInterface();
189     // Verify that the loadBalancerPool exists, for the member to be added to its cache
190     if (!loadBalancerPoolInterface.neutronLoadBalancerPoolExists(loadBalancerPoolUUID)) {
191         throw new ResourceNotFoundException(UUID_NO_EXIST);
192     }
193     NeutronLoadBalancerPool singletonPool = loadBalancerPoolInterface.getNeutronLoadBalancerPool(loadBalancerPoolUUID);
194
195     if (input.isSingleton()) {
196         NeutronLoadBalancerPoolMember singleton = input.getSingleton();
197         singleton.setPoolID(loadBalancerPoolUUID);
198         String loadBalancerPoolMemberUUID = singleton.getPoolMemberID();
199
200         /*
201          *  Verify that the LoadBalancerPoolMember doesn't already exist.
202          */
203         if (singletonPool.getLoadBalancerPoolMembers() != null) {
204             List<NeutronLoadBalancerPoolMember> members = singletonPool.getLoadBalancerPoolMembers();
205             for (NeutronLoadBalancerPoolMember member: members) {
206                 if (member.getPoolMemberID().equals(loadBalancerPoolMemberUUID)) {
207                     throw new BadRequestException("LoadBalancerPoolMember UUID already exists");
208                 }
209             }
210         }
211
212         Object[] instances = NeutronUtil.getInstances(INeutronLoadBalancerPoolMemberAware.class, this);
213         if (instances != null) {
214             if (instances.length > 0) {
215                 for (Object instance : instances) {
216                     INeutronLoadBalancerPoolMemberAware service = (INeutronLoadBalancerPoolMemberAware) instance;
217                     int status = service.canCreateNeutronLoadBalancerPoolMember(singleton);
218                     if (status < HTTP_OK_BOTTOM || status > HTTP_OK_TOP) {
219                         return Response.status(status).build();
220                     }
221                 }
222             } else {
223                 throw new ServiceUnavailableException(NO_PROVIDERS);
224             }
225         } else {
226             throw new ServiceUnavailableException(NO_PROVIDER_LIST);
227         }
228
229         if (instances != null) {
230             for (Object instance : instances) {
231                 INeutronLoadBalancerPoolMemberAware service = (INeutronLoadBalancerPoolMemberAware) instance;
232                 service.neutronLoadBalancerPoolMemberCreated(singleton);
233             }
234         }
235
236         /**
237          * Add the member from the neutron load balancer pool as well
238          */
239         singletonPool.addLoadBalancerPoolMember(singleton);
240
241     } else {
242         List<NeutronLoadBalancerPoolMember> bulk = input.getBulk();
243         Iterator<NeutronLoadBalancerPoolMember> i = bulk.iterator();
244         Map<String, NeutronLoadBalancerPoolMember> testMap = new HashMap<String, NeutronLoadBalancerPoolMember>();
245         Object[] instances = NeutronUtil.getInstances(INeutronLoadBalancerPoolMemberAware.class, this);
246         while (i.hasNext()) {
247             NeutronLoadBalancerPoolMember test = i.next();
248             String loadBalancerPoolMemberUUID = test.getPoolMemberID();
249
250             /*
251              *  Verify that the LoadBalancerPoolMember doesn't already exist.
252              */
253             List<NeutronLoadBalancerPoolMember> members = singletonPool.getLoadBalancerPoolMembers();
254             for (NeutronLoadBalancerPoolMember member: members) {
255                 if (member.getPoolMemberID().equals(loadBalancerPoolMemberUUID)) {
256                     throw new BadRequestException("LoadBalancerPoolMember UUID already exists");
257                 }
258             }
259
260             if (testMap.containsKey(test.getPoolMemberID())) {
261                 throw new BadRequestException("Load Balancer PoolMember UUID already exists");
262             }
263             if (instances != null) {
264                 if (instances.length > 0) {
265                     for (Object instance : instances) {
266                         INeutronLoadBalancerPoolMemberAware service = (INeutronLoadBalancerPoolMemberAware) instance;
267                         int status = service.canCreateNeutronLoadBalancerPoolMember(test);
268                         if (status < HTTP_OK_BOTTOM || status > HTTP_OK_TOP) {
269                             return Response.status(status).build();
270                         }
271                     }
272                 } else {
273                     throw new ServiceUnavailableException(NO_PROVIDERS);
274                 }
275             } else {
276                 throw new ServiceUnavailableException(NO_PROVIDER_LIST);
277             }
278         }
279         /*
280          * now, each element of the bulk request can be added to the cache
281          */
282         i = bulk.iterator();
283         while (i.hasNext()) {
284             NeutronLoadBalancerPoolMember test = i.next();
285             if (instances != null) {
286                 for (Object instance : instances) {
287                     INeutronLoadBalancerPoolMemberAware service = (INeutronLoadBalancerPoolMemberAware) instance;
288                     service.neutronLoadBalancerPoolMemberCreated(test);
289                 }
290             }
291             singletonPool.addLoadBalancerPoolMember(test);
292         }
293     }
294     return Response.status(HttpURLConnection.HTTP_CREATED).entity(input).build();
295 }
296
297 /**
298  * Updates a LB member pool
299  */
300
301 @Path("{loadBalancerPoolMemberUUID}")
302 @PUT
303 @Produces({ MediaType.APPLICATION_JSON })
304 @Consumes({ MediaType.APPLICATION_JSON })
305 @StatusCodes({
306         @ResponseCode(code = HttpURLConnection.HTTP_OK, condition = "Operation successful"),
307         @ResponseCode(code = HttpURLConnection.HTTP_BAD_REQUEST, condition = "Bad Request"),
308         @ResponseCode(code = HttpURLConnection.HTTP_UNAUTHORIZED, condition = "Unauthorized"),
309         @ResponseCode(code = HttpURLConnection.HTTP_FORBIDDEN, condition = "Forbidden"),
310         @ResponseCode(code = HttpURLConnection.HTTP_NOT_FOUND, condition = "Not Found"),
311         @ResponseCode(code = HttpURLConnection.HTTP_NOT_IMPLEMENTED, condition = "Not Implemented") })
312 public Response updateLoadBalancerPoolMember(
313         @PathParam("loadBalancerPoolUUID") String loadBalancerPoolUUID,
314         @PathParam("loadBalancerPoolMemberUUID") String loadBalancerPoolMemberUUID,
315         final NeutronLoadBalancerPoolMemberRequest input) {
316
317     //TODO: Implement update LB member pool
318     return Response.status(HttpURLConnection.HTTP_NOT_IMPLEMENTED).entity(input).build();
319 }
320
321 /**
322  * Deletes a LoadBalancerPoolMember
323  */
324
325 @Path("{loadBalancerPoolMemberUUID}")
326 @DELETE
327 @StatusCodes({
328     @ResponseCode(code = HttpURLConnection.HTTP_NO_CONTENT, condition = "No Content"),
329     @ResponseCode(code = HttpURLConnection.HTTP_UNAUTHORIZED, condition = "Unauthorized"),
330     @ResponseCode(code = HttpURLConnection.HTTP_FORBIDDEN, condition = "Forbidden"),
331     @ResponseCode(code = HttpURLConnection.HTTP_NOT_FOUND, condition = "Not Found"),
332     @ResponseCode(code = HttpURLConnection.HTTP_NOT_IMPLEMENTED, condition = "Not Implemented"),
333     @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
334 public Response deleteLoadBalancerPoolMember(
335         @PathParam("loadBalancerPoolUUID") String loadBalancerPoolUUID,
336         @PathParam("loadBalancerPoolMemberUUID") String loadBalancerPoolMemberUUID) {
337     INeutronLoadBalancerPoolCRUD loadBalancerPoolInterface = getNeutronInterfaces().getLoadBalancerPoolInterface();
338
339     // Verify that the loadBalancerPool exists, for the member to be removed from its cache
340     if (!loadBalancerPoolInterface.neutronLoadBalancerPoolExists(loadBalancerPoolUUID)) {
341         throw new ResourceNotFoundException(UUID_NO_EXIST);
342     }
343
344     //Verify that the LB pool member exists
345     NeutronLoadBalancerPoolMember singleton = null;
346     List<NeutronLoadBalancerPoolMember> members =
347             loadBalancerPoolInterface.getNeutronLoadBalancerPool(loadBalancerPoolUUID).getLoadBalancerPoolMembers();
348     for (NeutronLoadBalancerPoolMember member: members) {
349         if (member.getPoolMemberID().equals(loadBalancerPoolMemberUUID)) {
350             singleton = member;
351             break;
352         }
353     }
354     if (singleton == null) {
355         throw new BadRequestException("LoadBalancerPoolMember UUID does not exist.");
356     }
357
358     Object[] instances = NeutronUtil.getInstances(INeutronLoadBalancerPoolMemberAware.class, this);
359     if (instances != null) {
360         if (instances.length > 0) {
361             for (Object instance : instances) {
362                 INeutronLoadBalancerPoolMemberAware service = (INeutronLoadBalancerPoolMemberAware) instance;
363                 int status = service.canDeleteNeutronLoadBalancerPoolMember(singleton);
364                 if (status < HTTP_OK_BOTTOM || status > HTTP_OK_TOP) {
365                     return Response.status(status).build();
366                 }
367             }
368         } else {
369             throw new ServiceUnavailableException(NO_PROVIDERS);
370         }
371     } else {
372         throw new ServiceUnavailableException(NO_PROVIDER_LIST);
373     }
374
375     if (instances != null) {
376         for (Object instance : instances) {
377             INeutronLoadBalancerPoolMemberAware service = (INeutronLoadBalancerPoolMemberAware) instance;
378             service.neutronLoadBalancerPoolMemberDeleted(singleton);
379         }
380     }
381
382     /**
383      * Remove the member from the neutron load balancer pool
384      */
385     NeutronLoadBalancerPool singletonPool = loadBalancerPoolInterface.getNeutronLoadBalancerPool(loadBalancerPoolUUID);
386     singletonPool.removeLoadBalancerPoolMember(singleton);
387
388     return Response.status(HttpURLConnection.HTTP_NO_CONTENT).build();
389 }
390 }