Clean all unused and redundant imports in controller.
[controller.git] / opendaylight / samples / northbound / loadbalancer / src / main / java / org / opendaylight / controller / samples / loadbalancer / northbound / LoadBalancerNorthbound.java
1 /*
2  * Copyright IBM Corporation, 2013.  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.controller.samples.loadbalancer.northbound;
9
10 import java.util.List;
11
12 import javax.ws.rs.Consumes;
13 import javax.ws.rs.DELETE;
14 import javax.ws.rs.GET;
15 import javax.ws.rs.POST;
16 import javax.ws.rs.PUT;
17 import javax.ws.rs.Path;
18 import javax.ws.rs.PathParam;
19 import javax.ws.rs.Produces;
20 import javax.ws.rs.core.MediaType;
21 import javax.ws.rs.core.Response;
22
23 import org.codehaus.enunciate.jaxrs.ResponseCode;
24 import org.codehaus.enunciate.jaxrs.StatusCodes;
25 import org.codehaus.enunciate.jaxrs.TypeHint;
26 import org.opendaylight.controller.containermanager.IContainerManager;
27 import org.opendaylight.controller.samples.loadbalancer.entities.Pool;
28 import org.opendaylight.controller.samples.loadbalancer.entities.PoolMember;
29 import org.opendaylight.controller.samples.loadbalancer.entities.VIP;
30 import org.opendaylight.controller.northbound.commons.RestMessages;
31 import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException;
32 import org.opendaylight.controller.northbound.commons.exception.MethodNotAllowedException;
33 import org.opendaylight.controller.northbound.commons.exception.ResourceConflictException;
34 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
35 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
36 import org.opendaylight.controller.northbound.commons.exception.UnsupportedMediaTypeException;
37 import org.opendaylight.controller.sal.utils.ServiceHelper;
38 import org.opendaylight.controller.samples.loadbalancer.IConfigManager;
39
40 /**
41  * This class exposes North bound REST APIs for the Load Balancer Service.
42  * Following APIs are exposed by the Load Balancer Service:
43  *
44  * Data retrieval REST APIs::
45  *      1. Get details of all existing pools
46  *              Type : GET
47  *              URI : /one/nb/v2/lb/{container-name}/
48  *      NOTE: Current implementation of the opendaylight usage 'default' as a container-name
49  *      e.g : http://localhost:8080/one/nb/v2/lb/default will give you list of all the pools
50  *
51  *      2. Get details of all the existing VIPs
52  *              Type : GET
53  *              URI:  /one/nb/v2/lb/{container-name}/vips
54  *
55  * Pool related REST APIs::
56  *      1. Create Pool :
57  *              Type : POST
58  *              URI : /one/nb/v2/lb/{container-name}/create/pool
59  *              Request body :
60  *                      {
61  *                              "name":"",
62  *                              "lbmethod":""
63  *                      }
64  *              Currently, two load balancing policies are allowed {"roundrobin" and "random" }
65  *
66  *      2. Delete Pool :
67  *              Type : DELETE
68  *              URI : /one/nb/v2/lb/{container-name}/delete/pool/{pool-name}
69  *
70  * VIP related REST APIs::
71  *      1. Create VIP:
72  *              Type : POST
73  *              URI : /one/nb/v2/lb/{container-name}/create/vip
74  *              Request body :
75  *                      {
76  *                              "name":"",
77  *                              "ip":"ip in (xxx.xxx.xxx.xxx) format",
78  *                              "protocol":"TCP/UDP",
79  *                              "port":"any valid port number",
80  *                              "poolname":"" (optional)
81  *                       }
82  *              The pool name is optional and can be set up at a later stage (using the REST API given below).
83  *
84  *      2. Update VIP: Update pool name of the VIP
85  *              Type : PUT
86  *              URI : /one/nb/v2/lb/{container-name}/update/vip
87  *              Request body :
88  *                      {
89  *                              "name":"",
90  *                              "poolname":""
91  *                       }
92  *              Currently, we only allow update of the VIP pool name (if a VIP does not have an attached pool)
93  *              and not of the VIP name itself.
94  *              The specified pool name must already exist. If the specified VIP is already attached to a pool, the update
95  *              will fail.
96  *
97  *      3. Delete VIP :
98  *              Type : DELETE
99  *              URI : /one/nb/v2/lb/{container-name}/delete/vip/{vip-name}
100  *
101  * Pool member related REST APIs::
102  *      1. Create pool member:
103  *              Type : POST
104  *              URI : /one/nb/v2/lb/default/create/poolmember
105  *              Request body :
106  *                      {
107  *                              "name":"",
108  *                              "ip":"ip in (xxx.xxx.xxx.xxx) format",
109  *                              "poolname":"existing pool name"
110  *                       }
111  *
112  *      2. Delete pool member:
113  *              Type : DELETE
114  *              URI : /one/nb/v2/lb/{container-name}/delete/poolmember/{pool-member-name}/{pool-name}
115  *
116  *  NOTE: Property "name" of each individual entity must be unique.
117  *  All the above REST APIs throw appropriate response codes in case of error/success.
118  *  Please consult the respective methods to get details of various response codes.
119  */
120
121 @Path("/")
122 public class LoadBalancerNorthbound {
123
124     /*
125      * Method returns the Load balancer service instance running within
126      * 'default' container.
127      */
128     private IConfigManager getConfigManagerService(String containerName) {
129         IContainerManager containerManager = (IContainerManager) ServiceHelper
130                 .getGlobalInstance(IContainerManager.class, this);
131         if (containerManager == null) {
132             throw new ServiceUnavailableException("Container "
133                     + RestMessages.SERVICEUNAVAILABLE.toString());
134         }
135
136         boolean found = false;
137         List<String> containerNames = containerManager.getContainerNames();
138         for (String cName : containerNames) {
139             if (cName.trim().equalsIgnoreCase(containerName.trim())) {
140                 found = true;
141             }
142         }
143
144         if (found == false) {
145             throw new ResourceNotFoundException(containerName + " "
146                     + RestMessages.NOCONTAINER.toString());
147         }
148
149         IConfigManager configManager = (IConfigManager) ServiceHelper.getInstance(
150                         IConfigManager.class, containerName, this);
151
152         if (configManager == null) {
153             throw new ServiceUnavailableException("Load Balancer"
154                     + RestMessages.SERVICEUNAVAILABLE.toString());
155         }
156
157         return configManager;
158     }
159
160     @Path("/{containerName}")
161     @GET
162     @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
163     @TypeHint(Pools.class)
164     @StatusCodes( {
165         @ResponseCode(code = 200, condition = "Operation successful"),
166         @ResponseCode(code = 404, condition = "The containerName is not found"),
167         @ResponseCode(code = 503, condition = "Load balancer service is unavailable") })
168     public Pools getAllPools(
169             @PathParam("containerName") String containerName) {
170
171         IConfigManager configManager = getConfigManagerService(containerName);
172         if (configManager == null) {
173             throw new ServiceUnavailableException("Load Balancer "
174                                                     + RestMessages.SERVICEUNAVAILABLE.toString());
175         }
176
177         return new Pools(configManager.getAllPools());
178     }
179
180     @Path("/{containerName}/vips")
181     @GET
182     @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
183     @TypeHint(VIPs.class)
184     @StatusCodes( {
185         @ResponseCode(code = 200, condition = "Operation successful"),
186         @ResponseCode(code = 404, condition = "The containerName is not found"),
187         @ResponseCode(code = 503, condition = "Load balancer service is unavailable") })
188     public VIPs getAllVIPs(
189             @PathParam("containerName") String containerName) {
190
191         IConfigManager configManager = getConfigManagerService(containerName);
192         if (configManager == null) {
193             throw new ServiceUnavailableException("Load Balancer "
194                     + RestMessages.SERVICEUNAVAILABLE.toString());
195         }
196
197         return new VIPs(configManager.getAllVIPs());
198     }
199
200     @Path("/{containerName}/create/vip")
201     @POST
202     @Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
203     @StatusCodes( {
204         @ResponseCode(code = 201, condition = "VIP created successfully"),
205         @ResponseCode(code = 404, condition = "The Container Name not found"),
206         @ResponseCode(code = 503, condition = "Load balancer service is unavailable"),
207         @ResponseCode(code = 409, condition = "VIP already exist"),
208         @ResponseCode(code = 415, condition = "Invalid input data")})
209     public Response addVIP(@PathParam("containerName") String containerName,
210             @TypeHint(VIP.class) VIP inVIP){
211
212         VIP vipInput = inVIP;
213         String name = vipInput.getName();
214         String ip = vipInput.getIp();
215         String protocol = vipInput.getProtocol();
216         short protocolPort = vipInput.getPort();
217         String poolName = vipInput.getPoolName();
218         if(name.isEmpty() ||
219                 ip.isEmpty()||
220                 protocol.isEmpty()||
221                 protocolPort < 0 ){
222             throw new UnsupportedMediaTypeException(RestMessages.INVALIDDATA.toString());
223         }
224
225         IConfigManager configManager = getConfigManagerService(containerName);
226
227         if (configManager == null) {
228             throw new ServiceUnavailableException("Load Balancer "
229                     + RestMessages.SERVICEUNAVAILABLE.toString());
230         }
231
232         if(!configManager.vipExists(name, ip, protocol, protocolPort, poolName)){
233
234             VIP vip = configManager.createVIP(name, ip, protocol, protocolPort, poolName);
235             if ( vip != null){
236                 return Response.status(Response.Status.CREATED).build();
237             }
238         }else{
239             throw new ResourceConflictException(NBConst.RES_VIP_ALREADY_EXIST);
240         }
241         throw new InternalServerErrorException(NBConst.RES_VIP_CREATION_FAILED);
242     }
243
244     @Path("/{containerName}/update/vip")
245     @PUT
246     @Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
247     @StatusCodes( {
248         @ResponseCode(code = 201, condition = "VIP updated successfully"),
249         @ResponseCode(code = 404, condition = "The containerName not found"),
250         @ResponseCode(code = 503, condition = "VIP not found"),
251         @ResponseCode(code = 404, condition = "Pool not found"),
252         @ResponseCode(code = 405, condition = "Pool already attached to the VIP"),
253         @ResponseCode(code = 415, condition = "Invalid input name")})
254     public Response updateVIP(@PathParam("containerName") String containerName,
255             @TypeHint(VIP.class) VIP inVIP) {
256
257         VIP vipInput = inVIP;
258         String name = vipInput.getName();
259         String poolName = vipInput.getPoolName();
260         if(name.isEmpty() ||
261                 poolName.isEmpty()){
262             throw new UnsupportedMediaTypeException(RestMessages.INVALIDDATA.toString());
263         }
264
265         IConfigManager configManager = getConfigManagerService(containerName);
266         if (configManager == null) {
267             throw new ServiceUnavailableException("Load Balancer "
268                                                 + RestMessages.SERVICEUNAVAILABLE.toString());
269         }
270
271         if(!configManager.poolExists(poolName))
272             throw new ResourceNotFoundException(NBConst.RES_POOL_NOT_FOUND);
273
274         if(configManager.getVIPAttachedPool(name)!=null)
275             throw new MethodNotAllowedException(NBConst.RES_VIP_POOL_EXIST);
276
277         if(configManager.updateVIP(name, poolName)!= null)
278             return Response.status(Response.Status.ACCEPTED).build();
279
280         throw new InternalServerErrorException(NBConst.RES_VIP_UPDATE_FAILED);
281     }
282
283     @Path("/{containerName}/delete/vip/{vipName}")
284     @DELETE
285     @Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
286     @StatusCodes( {
287         @ResponseCode(code = 200, condition = "VIP deleted successfully"),
288         @ResponseCode(code = 404, condition = "The containerName not found"),
289         @ResponseCode(code = 503, condition = "Load balancer service is unavailable"),
290         @ResponseCode(code = 404, condition = "VIP not found"),
291         @ResponseCode(code = 500, condition = "Failed to delete VIP")})
292     public Response deleteVIP(
293             @PathParam(value = "containerName") String containerName,
294             @PathParam(value = "vipName") String vipName) {
295
296         if(vipName.isEmpty())
297             throw new UnsupportedMediaTypeException(RestMessages.INVALIDDATA.toString());
298
299         IConfigManager configManager = getConfigManagerService(containerName);
300         if (configManager == null) {
301             throw new ServiceUnavailableException("Load Balancer"
302                                             + RestMessages.SERVICEUNAVAILABLE.toString());
303         }
304
305         if(!configManager.vipExists(vipName))
306             throw new ResourceNotFoundException(NBConst.RES_VIP_NOT_FOUND);
307
308         for(VIP vip : configManager.getAllVIPs()){
309             if(vip.getName().equals(vipName)){
310                 configManager.deleteVIP(vipName);
311                 return Response.ok().build();
312             }
313         }
314         throw new InternalServerErrorException(NBConst.RES_VIP_DELETION_FAILED);
315     }
316
317     @Path("/{containerName}/create/pool")
318     @POST
319     @Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
320     @StatusCodes( {
321         @ResponseCode(code = 201, condition = "Pool created successfully"),
322         @ResponseCode(code = 404, condition = "The containerName not found"),
323         @ResponseCode(code = 503, condition = "Load balancer service is unavailable"),
324         @ResponseCode(code = 409, condition = "Pool already exist"),
325         @ResponseCode(code = 415, condition = "Invalid input data")})
326     public Response addPool(@PathParam("containerName") String containerName,
327             @TypeHint(Pool.class) Pool inPool) {
328
329         Pool poolInput = inPool;
330         String name = poolInput.getName();
331         String lbMethod =poolInput.getLbMethod();
332         if(name.isEmpty() ||
333                 lbMethod.isEmpty()){
334             throw new UnsupportedMediaTypeException(RestMessages.INVALIDDATA.toString());
335         }
336
337         IConfigManager configManager = getConfigManagerService(containerName);
338         if (configManager == null) {
339             throw new ServiceUnavailableException("Load Balancer "
340                                             + RestMessages.SERVICEUNAVAILABLE.toString());
341         }
342
343         if(!configManager.poolExists(name)){
344
345             Pool pool = configManager.createPool(name, lbMethod);
346             if ( pool != null){
347                 return Response.status(Response.Status.CREATED).build();
348             }
349         }else{
350             throw new ResourceConflictException(NBConst.RES_POOL_ALREADY_EXIST);
351         }
352         throw new InternalServerErrorException(NBConst.RES_POOL_CREATION_FAILED);
353     }
354
355     @Path("/{containerName}/delete/pool/{poolName}")
356     @DELETE
357     @Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
358     @StatusCodes( {
359         @ResponseCode(code = 200, condition = "Pool deleted successfully"),
360         @ResponseCode(code = 404, condition = "The containerName not found"),
361         @ResponseCode(code = 503, condition = "Load balancer service is unavailable"),
362         @ResponseCode(code = 404, condition = "Pool not found"),
363         @ResponseCode(code = 500, condition = "Failed to delete Pool")})
364     public Response deletePool(
365             @PathParam(value = "containerName") String containerName,
366             @PathParam(value = "poolName") String poolName) {
367
368         if(poolName.isEmpty())
369             throw new UnsupportedMediaTypeException(RestMessages.INVALIDDATA.toString());
370
371         IConfigManager configManager = getConfigManagerService(containerName);
372         if (configManager == null) {
373             throw new ServiceUnavailableException("Load Balancer"
374                                         + RestMessages.SERVICEUNAVAILABLE.toString());
375         }
376
377         if(!configManager.poolExists(poolName))
378             throw new ResourceNotFoundException(NBConst.RES_POOL_NOT_FOUND);
379
380         for(Pool pool:configManager.getAllPools()){
381             if(pool.getName().equals(poolName)){
382                 configManager.deletePool(poolName);
383                 return Response.ok().build();
384             }
385         }
386         throw new InternalServerErrorException(NBConst.RES_POOL_DELETION_FAILED);
387     }
388
389     @Path("/{containerName}/create/poolmember")
390     @POST
391     @Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
392     @StatusCodes( {
393         @ResponseCode(code = 201, condition = "Pool member created successfully"),
394         @ResponseCode(code = 404, condition = "The containerName not found"),
395         @ResponseCode(code = 503, condition = "Load balancer service is unavailable"),
396         @ResponseCode(code = 404, condition = "Pool not found"),
397         @ResponseCode(code = 409, condition = "Pool member already exist"),
398         @ResponseCode(code = 415, condition = "Invalid input data")})
399     public Response addPoolMember(@PathParam("containerName") String containerName,
400             @TypeHint(PoolMember.class) PoolMember inPoolMember){
401
402         PoolMember pmInput = inPoolMember;
403         String name = pmInput.getName();
404         String memberIP = pmInput.getIp();
405         String poolName = pmInput.getPoolName();
406
407         if(name.isEmpty() ||
408                 memberIP.isEmpty()||
409                 poolName.isEmpty()){
410             throw new UnsupportedMediaTypeException(RestMessages.INVALIDDATA.toString());
411         }
412
413         IConfigManager configManager = getConfigManagerService(containerName);
414         if (configManager == null) {
415             throw new ServiceUnavailableException("Load Balancer "
416                                         + RestMessages.SERVICEUNAVAILABLE.toString());
417         }
418
419         if(!configManager.poolExists(poolName))
420             throw new ResourceNotFoundException(NBConst.RES_POOL_NOT_FOUND);
421
422         if(!configManager.memberExists(name, memberIP, poolName)){
423
424             PoolMember poolMember = configManager.addPoolMember(name, memberIP, poolName);
425             if ( poolMember != null){
426                 return Response.status(Response.Status.CREATED).build();
427             }
428         }else{
429             throw new ResourceConflictException(NBConst.RES_POOLMEMBER_ALREADY_EXIST);
430         }
431         throw new InternalServerErrorException(NBConst.RES_POOLMEMBER_CREATION_FAILED);
432     }
433
434     @Path("/{containerName}/delete/poolmember/{poolMemberName}/{poolName}")
435     @DELETE
436     @Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
437     @StatusCodes( {
438         @ResponseCode(code = 200, condition = "Pool member deleted successfully"),
439         @ResponseCode(code = 404, condition = "The containerName not found"),
440         @ResponseCode(code = 503, condition = "Load balancer service is unavailable"),
441         @ResponseCode(code = 404, condition = "Pool member not found"),
442         @ResponseCode(code = 404, condition = "Pool not found")})
443     public Response deletePoolMember(
444             @PathParam(value = "containerName") String containerName,
445             @PathParam(value = "poolMemberName") String poolMemberName,
446             @PathParam(value = "poolName") String poolName) {
447
448         if(poolMemberName.isEmpty()||
449                 poolName.isEmpty())
450             throw new UnsupportedMediaTypeException(RestMessages.INVALIDDATA.toString());
451
452         IConfigManager configManager = getConfigManagerService(containerName);
453
454         if (configManager == null) {
455             throw new ServiceUnavailableException("Load Balancer"
456                                         + RestMessages.SERVICEUNAVAILABLE.toString());
457         }
458
459         if(!configManager.poolExists(poolName))
460             throw new ResourceNotFoundException(NBConst.RES_POOL_NOT_FOUND);
461
462         if(configManager.memberExists(poolMemberName, poolName)){
463
464             configManager.removePoolMember(poolMemberName, poolName);
465
466             return Response.ok().build();
467         }
468         throw new ResourceNotFoundException(NBConst.RES_POOLMEMBER_NOT_FOUND);
469     }
470 }