BUG 1853 : Clustered Data Store causes Out of Memory
[controller.git] / opendaylight / northbound / networkconfiguration / neutron / src / main / java / org / opendaylight / controller / networkconfig / neutron / northbound / NeutronLoadBalancerNorthbound.java
1 /*
2  * Copyright (C) 2014 Red Hat, Inc.
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
9 package org.opendaylight.controller.networkconfig.neutron.northbound;
10
11
12 import org.codehaus.enunciate.jaxrs.ResponseCode;
13 import org.codehaus.enunciate.jaxrs.StatusCodes;
14 import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerAware;
15 import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerCRUD;
16 import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
17 import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancer;
18 import org.opendaylight.controller.northbound.commons.RestMessages;
19 import org.opendaylight.controller.northbound.commons.exception.BadRequestException;
20 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
21 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
22 import org.opendaylight.controller.sal.utils.ServiceHelper;
23
24 import javax.ws.rs.Consumes;
25 import javax.ws.rs.DELETE;
26 import javax.ws.rs.GET;
27 import javax.ws.rs.POST;
28 import javax.ws.rs.PUT;
29 import javax.ws.rs.Path;
30 import javax.ws.rs.PathParam;
31 import javax.ws.rs.Produces;
32 import javax.ws.rs.QueryParam;
33 import javax.ws.rs.core.MediaType;
34 import javax.ws.rs.core.Response;
35 import java.util.ArrayList;
36 import java.util.HashMap;
37 import java.util.Iterator;
38 import java.util.List;
39
40 /**
41  * Neutron Northbound REST APIs for LoadBalancer Policies.<br>
42  * This class provides REST APIs for managing neutron LoadBalancer Policies
43  *
44  * <br>
45  * <br>
46  * Authentication scheme : <b>HTTP Basic</b><br>
47  * Authentication realm : <b>opendaylight</b><br>
48  * Transport : <b>HTTP and HTTPS</b><br>
49  * <br>
50  * HTTPS Authentication is disabled by default. Administrator can enable it in
51  * tomcat-server.xml after adding a proper keystore / SSL certificate from a
52  * trusted authority.<br>
53  * More info :
54  * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
55  *
56  */
57 @Path("/loadbalancers")
58 public class NeutronLoadBalancerNorthbound {
59
60     private NeutronLoadBalancer extractFields(NeutronLoadBalancer o, List<String> fields) {
61         return o.extractFields(fields);
62     }
63
64     /**
65      * Returns a list of all LoadBalancer */
66     @GET
67     @Produces({ MediaType.APPLICATION_JSON })
68     @StatusCodes({
69             @ResponseCode(code = 200, condition = "Operation successful"),
70             @ResponseCode(code = 401, condition = "Unauthorized"),
71             @ResponseCode(code = 501, condition = "Not Implemented") })
72
73     public Response listGroups(
74             // return fields
75             @QueryParam("fields") List<String> fields,
76             // OpenStack LoadBalancer attributes
77             @QueryParam("id") String queryLoadBalancerID,
78             @QueryParam("tenant_id") String queryLoadBalancerTenantID,
79             @QueryParam("name") String queryLoadBalancerName,
80             @QueryParam("description") String queryLoadBalancerDescription,
81             @QueryParam("status") String queryLoadBalancerStatus,
82             @QueryParam("vip_address") String queryLoadBalancerVipAddress,
83             @QueryParam("vip_subnet") String queryLoadBalancerVipSubnet,
84             // pagination
85             @QueryParam("limit") String limit,
86             @QueryParam("marker") String marker,
87             @QueryParam("page_reverse") String pageReverse
88             // sorting not supported
89     ) {
90         INeutronLoadBalancerCRUD loadBalancerPoolInterface = NeutronCRUDInterfaces.getINeutronLoadBalancerCRUD(
91                 this);
92         //        INeutronLoadBalancerRuleCRUD firewallRuleInterface = NeutronCRUDInterfaces.getINeutronLoadBalancerRuleCRUD(this);
93
94         if (loadBalancerPoolInterface == null) {
95             throw new ServiceUnavailableException("LoadBalancer CRUD Interface "
96                     + RestMessages.SERVICEUNAVAILABLE.toString());
97         }
98         List<NeutronLoadBalancer> allLoadBalancers = loadBalancerPoolInterface.getAllNeutronLoadBalancers();
99         //        List<NeutronLoadBalancerRule> allLoadBalancerRules = firewallRuleInterface.getAllNeutronLoadBalancerRules();
100         List<NeutronLoadBalancer> ans = new ArrayList<NeutronLoadBalancer>();
101         //        List<NeutronLoadBalancerRule> rules = new ArrayList<NeutronLoadBalancerRule>();
102         Iterator<NeutronLoadBalancer> i = allLoadBalancers.iterator();
103         while (i.hasNext()) {
104             NeutronLoadBalancer nsg = i.next();
105             if ((queryLoadBalancerID == null ||
106                     queryLoadBalancerID.equals(nsg.getLoadBalancerID())) &&
107                     (queryLoadBalancerTenantID == null ||
108                             queryLoadBalancerTenantID.equals(nsg.getLoadBalancerTenantID())) &&
109                     (queryLoadBalancerName == null ||
110                             queryLoadBalancerName.equals(nsg.getLoadBalancerName())) &&
111                     (queryLoadBalancerDescription == null ||
112                             queryLoadBalancerDescription.equals(nsg.getLoadBalancerDescription())) &&
113                     (queryLoadBalancerVipAddress == null ||
114                             queryLoadBalancerVipAddress.equals(nsg.getLoadBalancerVipAddress())) &&
115                     (queryLoadBalancerVipSubnet == null ||
116                             queryLoadBalancerVipSubnet.equals(nsg.getLoadBalancerVipSubnetID()))) {
117                 if (fields.size() > 0) {
118                     ans.add(extractFields(nsg,fields));
119                 } else {
120                     ans.add(nsg);
121                 }
122             }
123         }
124         return Response.status(200).entity(
125                 new NeutronLoadBalancerRequest(ans)).build();
126     }
127
128     /**
129      * Returns a specific LoadBalancer */
130
131     @Path("{loadBalancerPoolID}")
132     @GET
133     @Produces({ MediaType.APPLICATION_JSON })
134
135     @StatusCodes({
136             @ResponseCode(code = 200, condition = "Operation successful"),
137             @ResponseCode(code = 401, condition = "Unauthorized"),
138             @ResponseCode(code = 404, condition = "Not Found"),
139             @ResponseCode(code = 501, condition = "Not Implemented") })
140     public Response showLoadBalancer(@PathParam("loadBalancerPoolID") String loadBalancerPoolID,
141             // return fields
142             @QueryParam("fields") List<String> fields) {
143         INeutronLoadBalancerCRUD loadBalancerPoolInterface = NeutronCRUDInterfaces.getINeutronLoadBalancerCRUD(
144                 this);
145         if (loadBalancerPoolInterface == null) {
146             throw new ServiceUnavailableException("LoadBalancer CRUD Interface "
147                     + RestMessages.SERVICEUNAVAILABLE.toString());
148         }
149         if (!loadBalancerPoolInterface.neutronLoadBalancerExists(loadBalancerPoolID)) {
150             throw new ResourceNotFoundException("LoadBalancer UUID does not exist.");
151         }
152         if (fields.size() > 0) {
153             NeutronLoadBalancer ans = loadBalancerPoolInterface.getNeutronLoadBalancer(loadBalancerPoolID);
154             return Response.status(200).entity(
155                     new NeutronLoadBalancerRequest(extractFields(ans, fields))).build();
156         } else {
157             return Response.status(200).entity(new NeutronLoadBalancerRequest(loadBalancerPoolInterface.getNeutronLoadBalancer(
158                     loadBalancerPoolID))).build();
159         }
160     }
161
162     /**
163      * Creates new LoadBalancer */
164
165     @POST
166     @Produces({ MediaType.APPLICATION_JSON })
167     @Consumes({ MediaType.APPLICATION_JSON })
168
169     @StatusCodes({
170             @ResponseCode(code = 201, condition = "Created"),
171             @ResponseCode(code = 400, condition = "Bad Request"),
172             @ResponseCode(code = 401, condition = "Unauthorized"),
173             @ResponseCode(code = 403, condition = "Forbidden"),
174             @ResponseCode(code = 404, condition = "Not Found"),
175             @ResponseCode(code = 409, condition = "Conflict"),
176             @ResponseCode(code = 501, condition = "Not Implemented") })
177     public Response createLoadBalancers(final NeutronLoadBalancerRequest input) {
178         INeutronLoadBalancerCRUD loadBalancerPoolInterface = NeutronCRUDInterfaces.getINeutronLoadBalancerCRUD(
179                 this);
180         if (loadBalancerPoolInterface == null) {
181             throw new ServiceUnavailableException("LoadBalancer CRUD Interface "
182                     + RestMessages.SERVICEUNAVAILABLE.toString());
183         }
184         if (input.isSingleton()) {
185             NeutronLoadBalancer singleton = input.getSingleton();
186
187             /*
188              *  Verify that the LoadBalancer doesn't already exist.
189              */
190             if (loadBalancerPoolInterface.neutronLoadBalancerExists(singleton.getLoadBalancerID())) {
191                 throw new BadRequestException("LoadBalancer UUID already exists");
192             }
193             loadBalancerPoolInterface.addNeutronLoadBalancer(singleton);
194
195             Object[] instances = ServiceHelper.getGlobalInstances(INeutronLoadBalancerAware.class, this, null);
196             if (instances != null) {
197                 for (Object instance : instances) {
198                     INeutronLoadBalancerAware service = (INeutronLoadBalancerAware) instance;
199                     int status = service.canCreateNeutronLoadBalancer(singleton);
200                     if (status < 200 || status > 299) {
201                         return Response.status(status).build();
202                     }
203                 }
204             }
205             loadBalancerPoolInterface.addNeutronLoadBalancer(singleton);
206             if (instances != null) {
207                 for (Object instance : instances) {
208                     INeutronLoadBalancerAware service = (INeutronLoadBalancerAware) instance;
209                     service.neutronLoadBalancerCreated(singleton);
210                 }
211             }
212         } else {
213             List<NeutronLoadBalancer> bulk = input.getBulk();
214             Iterator<NeutronLoadBalancer> i = bulk.iterator();
215             HashMap<String, NeutronLoadBalancer> testMap = new HashMap<String, NeutronLoadBalancer>();
216             Object[] instances = ServiceHelper.getGlobalInstances(INeutronLoadBalancerAware.class, this, null);
217             while (i.hasNext()) {
218                 NeutronLoadBalancer test = i.next();
219
220                 /*
221                  *  Verify that the firewall policy doesn't already exist
222                  */
223
224                 if (loadBalancerPoolInterface.neutronLoadBalancerExists(test.getLoadBalancerID())) {
225                     throw new BadRequestException("Load Balancer Pool UUID already is already created");
226                 }
227                 if (testMap.containsKey(test.getLoadBalancerID())) {
228                     throw new BadRequestException("Load Balancer Pool UUID already exists");
229                 }
230                 if (instances != null) {
231                     for (Object instance : instances) {
232                         INeutronLoadBalancerAware service = (INeutronLoadBalancerAware) instance;
233                         int status = service.canCreateNeutronLoadBalancer(test);
234                         if (status < 200 || status > 299) {
235                             return Response.status(status).build();
236                         }
237                     }
238                 }
239             }
240             /*
241              * now, each element of the bulk request can be added to the cache
242              */
243             i = bulk.iterator();
244             while (i.hasNext()) {
245                 NeutronLoadBalancer test = i.next();
246                 loadBalancerPoolInterface.addNeutronLoadBalancer(test);
247                 if (instances != null) {
248                     for (Object instance : instances) {
249                         INeutronLoadBalancerAware service = (INeutronLoadBalancerAware) instance;
250                         service.neutronLoadBalancerCreated(test);
251                     }
252                 }
253             }
254         }
255         return Response.status(201).entity(input).build();
256     }
257
258     /**
259      * Updates a LoadBalancer Policy
260      */
261     @Path("{loadBalancerPoolID}")
262     @PUT
263     @Produces({ MediaType.APPLICATION_JSON })
264     @Consumes({ MediaType.APPLICATION_JSON })
265
266     @StatusCodes({
267             @ResponseCode(code = 200, condition = "Operation successful"),
268             @ResponseCode(code = 400, condition = "Bad Request"),
269             @ResponseCode(code = 401, condition = "Unauthorized"),
270             @ResponseCode(code = 403, condition = "Forbidden"),
271             @ResponseCode(code = 404, condition = "Not Found"),
272             @ResponseCode(code = 501, condition = "Not Implemented") })
273     public Response updateLoadBalancer(
274             @PathParam("loadBalancerPoolID") String loadBalancerPoolID, final NeutronLoadBalancerRequest input) {
275         INeutronLoadBalancerCRUD loadBalancerPoolInterface = NeutronCRUDInterfaces.getINeutronLoadBalancerCRUD(
276                 this);
277         if (loadBalancerPoolInterface == null) {
278             throw new ServiceUnavailableException("LoadBalancer CRUD Interface "
279                     + RestMessages.SERVICEUNAVAILABLE.toString());
280         }
281
282         /*
283          * verify the LoadBalancer exists and there is only one delta provided
284          */
285         if (!loadBalancerPoolInterface.neutronLoadBalancerExists(loadBalancerPoolID)) {
286             throw new ResourceNotFoundException("LoadBalancer UUID does not exist.");
287         }
288         if (!input.isSingleton()) {
289             throw new BadRequestException("Only singleton edit supported");
290         }
291         NeutronLoadBalancer delta = input.getSingleton();
292         NeutronLoadBalancer original = loadBalancerPoolInterface.getNeutronLoadBalancer(loadBalancerPoolID);
293
294         /*
295          * updates restricted by Neutron
296          */
297         if (delta.getLoadBalancerID() != null ||
298                 delta.getLoadBalancerTenantID() != null ||
299                 delta.getLoadBalancerName() != null ||
300                 delta.getLoadBalancerDescription() != null ||
301                 delta.getLoadBalancerStatus() != null ||
302                 delta.getLoadBalancerVipAddress() != null ||
303                 delta.getLoadBalancerVipSubnetID() != null) {
304             throw new BadRequestException("Attribute edit blocked by Neutron");
305         }
306
307         Object[] instances = ServiceHelper.getGlobalInstances(INeutronLoadBalancerAware.class, this, null);
308         if (instances != null) {
309             for (Object instance : instances) {
310                 INeutronLoadBalancerAware service = (INeutronLoadBalancerAware) instance;
311                 int status = service.canUpdateNeutronLoadBalancer(delta, original);
312                 if (status < 200 || status > 299) {
313                     return Response.status(status).build();
314                 }
315             }
316         }
317
318         /*
319          * update the object and return it
320          */
321         loadBalancerPoolInterface.updateNeutronLoadBalancer(loadBalancerPoolID, delta);
322         NeutronLoadBalancer updatedLoadBalancer = loadBalancerPoolInterface.getNeutronLoadBalancer(
323                 loadBalancerPoolID);
324         if (instances != null) {
325             for (Object instance : instances) {
326                 INeutronLoadBalancerAware service = (INeutronLoadBalancerAware) instance;
327                 service.neutronLoadBalancerUpdated(updatedLoadBalancer);
328             }
329         }
330         return Response.status(200).entity(new NeutronLoadBalancerRequest(loadBalancerPoolInterface.getNeutronLoadBalancer(
331                 loadBalancerPoolID))).build();
332     }
333
334     /**
335      * Deletes a LoadBalancer */
336
337     @Path("{loadBalancerPoolID}")
338     @DELETE
339     @StatusCodes({
340             @ResponseCode(code = 204, condition = "No Content"),
341             @ResponseCode(code = 401, condition = "Unauthorized"),
342             @ResponseCode(code = 404, condition = "Not Found"),
343             @ResponseCode(code = 409, condition = "Conflict"),
344             @ResponseCode(code = 501, condition = "Not Implemented") })
345     public Response deleteLoadBalancer(
346             @PathParam("loadBalancerPoolID") String loadBalancerPoolID) {
347         INeutronLoadBalancerCRUD loadBalancerPoolInterface = NeutronCRUDInterfaces.getINeutronLoadBalancerCRUD(
348                 this);
349         if (loadBalancerPoolInterface == null) {
350             throw new ServiceUnavailableException("LoadBalancer CRUD Interface "
351                     + RestMessages.SERVICEUNAVAILABLE.toString());
352         }
353
354         /*
355          * verify the LoadBalancer exists and it isn't currently in use
356          */
357         if (!loadBalancerPoolInterface.neutronLoadBalancerExists(loadBalancerPoolID)) {
358             throw new ResourceNotFoundException("LoadBalancer UUID does not exist.");
359         }
360         if (loadBalancerPoolInterface.neutronLoadBalancerInUse(loadBalancerPoolID)) {
361             return Response.status(409).build();
362         }
363         NeutronLoadBalancer singleton = loadBalancerPoolInterface.getNeutronLoadBalancer(loadBalancerPoolID);
364         Object[] instances = ServiceHelper.getGlobalInstances(INeutronLoadBalancerAware.class, this, null);
365         if (instances != null) {
366             for (Object instance : instances) {
367                 INeutronLoadBalancerAware service = (INeutronLoadBalancerAware) instance;
368                 int status = service.canDeleteNeutronLoadBalancer(singleton);
369                 if (status < 200 || status > 299) {
370                     return Response.status(status).build();
371                 }
372             }
373         }
374
375         loadBalancerPoolInterface.removeNeutronLoadBalancer(loadBalancerPoolID);
376         if (instances != null) {
377             for (Object instance : instances) {
378                 INeutronLoadBalancerAware service = (INeutronLoadBalancerAware) instance;
379                 service.neutronLoadBalancerDeleted(singleton);
380             }
381         }
382         return Response.status(204).build();
383     }
384 }