* Moved all l2 forwarding services based on OF to a separate OSGi
[affinity.git] / affinity / northbound / src / main / java / org / opendaylight / affinity / affinity / northbound / AffinityNorthbound.java
1 /*
2  * Copyright (c) 2013 Plexxi, Inc. 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
9 package org.opendaylight.affinity.affinity.northbound;
10
11 import java.util.ArrayList;
12 import java.util.HashSet;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.Set;
16
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.core.Context;
26 import javax.ws.rs.core.MediaType;
27 import javax.ws.rs.core.Response;
28 import javax.ws.rs.core.SecurityContext;
29
30 import org.codehaus.enunciate.jaxrs.ResponseCode;
31 import org.codehaus.enunciate.jaxrs.StatusCodes;
32 import org.codehaus.enunciate.jaxrs.TypeHint;
33 import org.opendaylight.controller.containermanager.IContainerManager;
34 import org.opendaylight.controller.northbound.commons.RestMessages;
35 import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException;
36 import org.opendaylight.controller.northbound.commons.exception.ResourceConflictException;
37 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
38 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
39 import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
40 import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
41 import org.opendaylight.controller.sal.authorization.Privilege;
42 import org.opendaylight.controller.sal.utils.GlobalConstants;
43 import org.opendaylight.controller.sal.utils.ServiceHelper;
44 import org.opendaylight.controller.sal.utils.Status;
45 import org.opendaylight.affinity.affinity.IAffinityManager;
46 import org.opendaylight.affinity.affinity.AffinityLink;
47 import org.opendaylight.affinity.affinity.AffinityGroup;
48
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51
52 /**
53  * The class provides Northbound REST APIs to access affinity configuration.
54  *
55  */
56
57 @Path("/")
58 public class AffinityNorthbound {
59
60     private String username;
61     private static final Logger log = LoggerFactory.getLogger(AffinityNorthbound.class);
62
63     @Context
64     public void setSecurityContext(SecurityContext context) {
65         username = context.getUserPrincipal().getName();
66     }
67
68     protected String getUserName() {
69         return username;
70     }
71
72     private IAffinityManager getIfAffinityManagerService(String containerName) {
73         log.debug("In getIfAffinityManager");
74
75         IContainerManager containerManager = (IContainerManager) ServiceHelper
76                 .getGlobalInstance(IContainerManager.class, this);
77         if (containerManager == null) {
78             throw new ServiceUnavailableException("Container "
79                     + RestMessages.SERVICEUNAVAILABLE.toString());
80         }
81
82         boolean found = false;
83         List<String> containerNames = containerManager.getContainerNames();
84         for (String cName : containerNames) {
85             if (cName.trim().equalsIgnoreCase(containerName.trim())) {
86                 found = true;
87                 break;
88             }
89         }
90
91         if (found == false) {
92             throw new ResourceNotFoundException(containerName + " "
93                     + RestMessages.SERVICEUNAVAILABLE.toString());
94         }
95
96         IAffinityManager affinityManager = (IAffinityManager) ServiceHelper
97                 .getInstance(IAffinityManager.class, containerName, this);
98
99         if (affinityManager == null) {
100             throw new ServiceUnavailableException("Affinity Manager "
101                     + RestMessages.SERVICEUNAVAILABLE.toString());
102         }
103
104         return affinityManager;
105     }
106
107     /**
108      * Add an affinity to the configuration database
109      *
110      * @param containerName
111      *            Name of the Container
112      * @param affinityGroupName
113      *            Name of the new affinity group being added
114      * @return Response as dictated by the HTTP Response Status code
115      */
116
117     @Path("/{containerName}/create/group/{affinityGroupName}")
118     @PUT
119     @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
120     @TypeHint(Response.class)
121     @StatusCodes({
122             @ResponseCode(code = 200, condition = "Operation successful"),
123             @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
124             @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
125     public Response createAffinityGroup(
126             @PathParam("containerName") String containerName,
127             @PathParam("affinityGroupName") String affinityGroupName) {
128
129         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
130             throw new UnauthorizedException("User is not authorized to perform this operation on container "
131                                             + containerName);
132         }
133         log.info("add a new affinitygroup = {}, containerName = {}",  affinityGroupName, containerName);
134         IAffinityManager affinityManager = getIfAffinityManagerService(containerName);
135         if (affinityManager == null) {
136             throw new ServiceUnavailableException("Affinity Manager "
137                                                   + RestMessages.SERVICEUNAVAILABLE.toString());
138         }
139
140         AffinityGroup ag1 = new AffinityGroup(affinityGroupName);
141         Status ret = affinityManager.addAffinityGroup(ag1);
142         
143         return Response.status(Response.Status.CREATED).build();
144     }
145
146     /**
147      * Returns details of an affinity group.
148      *
149      * @param containerName
150      *            Name of the Container. The Container name for the base
151      *            controller is "default".
152      * @param affinityGroupName
153      *            Name of the affinity group being retrieved.
154      * @return affinity configuration that matches the affinity name.
155      */
156     @Path("/{containerName}/group/{affinityGroupName}")
157     @GET
158     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
159     @TypeHint(AffinityGroup.class)
160     @StatusCodes({
161             @ResponseCode(code = 200, condition = "Operation successful"),
162             @ResponseCode(code = 404, condition = "The containerName is not found"),
163             @ResponseCode(code = 415, condition = "Affinity name is not found"),
164             @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
165     public AffinityGroup getAffinityGroupDetails(
166             @PathParam("containerName") String containerName,
167             @PathParam("affinityGroupName") String affinityGroupName) {
168         if (!NorthboundUtils.isAuthorized(
169                 getUserName(), containerName, Privilege.READ, this)) {
170             throw new UnauthorizedException(
171                     "User is not authorized to perform this operation on container "
172                             + containerName);
173         }
174         IAffinityManager affinityManager = getIfAffinityManagerService(containerName);
175         if (affinityManager == null) {
176             throw new ServiceUnavailableException("Affinity "
177                                                   + RestMessages.SERVICEUNAVAILABLE.toString());
178         }
179
180         log.info("Get affinity group details" + affinityGroupName);
181         AffinityGroup ag = affinityManager.getAffinityGroup(affinityGroupName);
182         if (ag == null) {
183             throw new ResourceNotFoundException(RestMessages.SERVICEUNAVAILABLE.toString());
184         } else {
185             return ag;
186         }
187     }
188
189     /**
190      * Add an affinity link with one "from" and one "to" affinity group. 
191      *
192      * @param containerName
193      *            Name of the Container
194      * @param affinityLinkName
195      *            Name of the new affinity link being added
196      * @return Response as dictated by the HTTP Response Status code
197      */
198
199     @Path("/{containerName}/create/link/{affinityLinkName}/from/{fromAffinityGroup}/to/{toAffinityGroup}")
200     @PUT
201     @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
202     @TypeHint(Response.class)
203     @StatusCodes({
204             @ResponseCode(code = 200, condition = "Operation successful"),
205             @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
206             @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
207     public Response createAffinityLink(
208             @PathParam("containerName") String containerName,
209             @PathParam("affinityLinkName") String affinityLinkName,
210             @PathParam("fromAffinityGroup") String fromAffinityGroup,
211             @PathParam("toAffinityGroup") String toAffinityGroup) {
212
213         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
214             throw new UnauthorizedException("User is not authorized to perform this operation on container "
215                                             + containerName);
216         }
217
218         IAffinityManager affinityManager = getIfAffinityManagerService(containerName);
219         if (affinityManager == null) {
220             throw new ServiceUnavailableException("Affinity Manager "
221                                                   + RestMessages.SERVICEUNAVAILABLE.toString());
222         }
223
224         
225         log.info("Create affinity link" + affinityLinkName + "fromGroup" + fromAffinityGroup + "toGroup" + toAffinityGroup);
226         AffinityGroup from = affinityManager.getAffinityGroup(fromAffinityGroup);
227         AffinityGroup to = affinityManager.getAffinityGroup(toAffinityGroup);
228         AffinityLink al1 = new AffinityLink(affinityLinkName, from, to);
229
230         Status ret = affinityManager.addAffinityLink(al1);
231         if (!ret.isSuccess()) {
232             //            throw new InternalServerErrorException(ret.getDescription());
233             log.error("Create affinity link {}", ret);
234         }
235         return Response.status(Response.Status.CREATED).build();
236     }
237
238
239     /**
240      * Add path redirect details to an affinity link. 
241      *
242      * @param containerName
243      *            Name of the Container
244      * @param affinityLinkName
245      *            Name of the new affinity link being added
246      * @param wayPoint
247      *            IP address string of a waypoint server or VM
248      * @return Response as dictated by the HTTP Response Status code
249      */
250
251     @Path("/{containerName}/link/{affinityLinkName}/setwaypoint/{waypointIP}")
252     @PUT
253     @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
254     @TypeHint(Response.class)
255     @StatusCodes({
256             @ResponseCode(code = 200, condition = "Operation successful"),
257             @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
258             @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
259     public Response setLinkWaypoint(
260             @PathParam("containerName") String containerName,
261             @PathParam("affinityLinkName") String affinityLinkName,
262             @PathParam("waypointIP") String waypointIP) {
263
264         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
265             throw new UnauthorizedException("User is not authorized to perform this operation on container "
266                                             + containerName);
267         }
268
269         IAffinityManager affinityManager = getIfAffinityManagerService(containerName);
270         if (affinityManager == null) {
271             throw new ServiceUnavailableException("Affinity Manager "
272                                                   + RestMessages.SERVICEUNAVAILABLE.toString());
273         }
274         log.info("Set waypoint address (link)" + affinityLinkName + " (waypoint ip) " + waypointIP);
275
276         AffinityLink al1 = affinityManager.getAffinityLink(affinityLinkName);
277         al1.setWaypoint(waypointIP);        
278         return Response.status(Response.Status.CREATED).build();
279     }
280
281
282     /**
283      * Mark this affinity link with "deny". 
284      *
285      * @param containerName
286      *            Name of the Container
287      * @param affinityLinkName
288      *            Name of the new affinity link being marked. 
289      * @return Response as dictated by the HTTP Response Status code
290      */
291
292     @Path("/{containerName}/link/{affinityLinkName}/deny/")
293     @PUT
294     @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
295     @TypeHint(Response.class)
296     @StatusCodes({
297             @ResponseCode(code = 200, condition = "Operation successful"),
298             @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
299             @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
300     public Response setLinkDeny(
301             @PathParam("containerName") String containerName,
302             @PathParam("affinityLinkName") String affinityLinkName) {
303         
304         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
305             throw new UnauthorizedException("User is not authorized to perform this operation on container "
306                                             + containerName);
307         }
308
309         IAffinityManager affinityManager = getIfAffinityManagerService(containerName);
310         if (affinityManager == null) {
311             throw new ServiceUnavailableException("Affinity Manager "
312                                                   + RestMessages.SERVICEUNAVAILABLE.toString());
313         }
314         log.info("Set deny (link)" + affinityLinkName);
315
316         AffinityLink al1 = affinityManager.getAffinityLink(affinityLinkName);
317         al1.setDeny();        
318         return Response.status(Response.Status.CREATED).build();
319     }
320
321     /**
322      * Add IP addresses to a group. 
323      *
324      * @param containerName
325      *            Name of the Container
326      * @param affinityGroupName
327      *            Name of the affinity group to add to. 
328      * @param ipaddress
329      *            IP address of the new affinity member. 
330      * @return Response as dictated by the HTTP Response Status code
331      */
332     @Path("/{containerName}/group/{affinityGroupName}/add/ip/{ipaddress}")
333     @PUT
334     @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
335     @TypeHint(Response.class)
336     @StatusCodes({
337             @ResponseCode(code = 200, condition = "Operation successful"),
338             @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
339             @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
340     public Response addInetAddress(
341             @PathParam("containerName") String containerName,
342             @PathParam("affinityGroupName") String affinityGroupName,
343             @PathParam("ipaddress") String ipaddress) {
344         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
345             throw new UnauthorizedException("User is not authorized to perform this operation on container "
346                                             + containerName);
347         }
348         
349         IAffinityManager affinityManager = getIfAffinityManagerService(containerName);
350         if (affinityManager == null) {
351             throw new ServiceUnavailableException("Affinity Manager "
352                                                   + RestMessages.SERVICEUNAVAILABLE.toString());
353         }
354         
355         log.info("add Inet address " + affinityGroupName + " (ipaddress) " + ipaddress);
356         AffinityGroup ag1 = affinityManager.getAffinityGroup(affinityGroupName);
357         ag1.add(ipaddress);
358         
359         return Response.status(Response.Status.CREATED).build();
360     }
361     
362     /**
363      * Add prefix/mask subnet as a member of the affinity group.
364      *
365      * @param containerName
366      *            Name of the Container
367      * @param affinityGroupName
368      *            Name of the affinity group to add to. 
369      * @param ipmask
370      *            a.b.c.d/mm format of a set of IP addresses to add.
371      * @return Response as dictated by the HTTP Response Status code
372      */
373     @Path("/{containerName}/group/{affinityGroupName}/addsubnet/ipprefix/{ipprefix}/mask/{mask}")
374     @PUT
375     @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
376     @TypeHint(Response.class)
377     @StatusCodes({
378             @ResponseCode(code = 200, condition = "Operation successful"),
379             @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
380             @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
381     public Response addSubnet(
382             @PathParam("containerName") String containerName,
383             @PathParam("affinityGroupName") String affinityGroupName,
384             @PathParam("ipprefix") String ipprefix,
385             @PathParam("mask") String mask) {
386         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
387             throw new UnauthorizedException("User is not authorized to perform this operation on container "
388                                             + containerName);
389         }
390         
391         IAffinityManager affinityManager = getIfAffinityManagerService(containerName);
392         if (affinityManager == null) {
393             throw new ServiceUnavailableException("Affinity Manager "
394                                                   + RestMessages.SERVICEUNAVAILABLE.toString());
395         }
396         
397         log.info("addSubnet to affinitygroup" + affinityGroupName);
398         AffinityGroup ag1 = affinityManager.getAffinityGroup(affinityGroupName);
399         String ipmask = ipprefix + "/" + mask;
400         ag1.addInetMask(ipmask);
401         
402         return Response.status(Response.Status.CREATED).build();
403     }
404
405
406     @Path("/{containerName}/affinity-groups")
407     @GET
408     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
409     @TypeHint(AffinityGroupList.class)
410     @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"),
411         @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
412         @ResponseCode(code = 404, condition = "The containerName is not found"),
413         @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
414     public AffinityGroupList getAllAffinityGroups(@PathParam("containerName") String containerName) {
415
416         //        if (!isValidContainer(containerName)) {
417         //            throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
418         //}
419
420         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
421             throw new UnauthorizedException("User is not authorized to perform this operation on container "
422                     + containerName);
423         }
424
425         IAffinityManager affinityManager = getIfAffinityManagerService(containerName);
426         if (affinityManager == null) {
427             throw new ServiceUnavailableException("Affinity Manager "
428                                                   + RestMessages.SERVICEUNAVAILABLE.toString());
429         }
430         log.info("getallgroups");
431         return new AffinityGroupList(affinityManager.getAllAffinityGroups());
432     }
433
434
435
436     @Path("/{containerName}/affinity-links")
437     @GET
438     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
439     @TypeHint(AffinityLinkList.class)
440     @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"),
441     @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
442     @ResponseCode(code = 404, condition = "The containerName is not found"),
443     @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
444     public AffinityLinkList getAllAffinityLinks(@PathParam("containerName") String containerName) {
445
446         //        if (!isValidContainer(containerName)) {
447         //            throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
448         //}
449
450         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
451             throw new UnauthorizedException("User is not authorized to perform this operation on container "
452                     + containerName);
453         }
454
455         IAffinityManager affinityManager = getIfAffinityManagerService(containerName);
456         if (affinityManager == null) {
457             throw new ServiceUnavailableException("Affinity Manager "
458                                                   + RestMessages.SERVICEUNAVAILABLE.toString());
459         }
460         log.info("list all links");
461         return new AffinityLinkList(affinityManager.getAllAffinityLinks());
462     }
463
464     /**
465     @Path("/{containerName}/")
466     @GET
467     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
468     @TypeHint(AffinityGroupList.class)
469     @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"),
470         @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
471         @ResponseCode(code = 404, condition = "The containerName is not found"),
472         @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
473     public AffinityGroupList getAllAffinityGroups(@PathParam("containerName") String containerName) {
474
475         //        if (!isValidContainer(containerName)) {
476         //            throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
477         //}
478
479         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
480             throw new UnauthorizedException("User is not authorized to perform this operation on container "
481                     + containerName);
482         }
483
484         IAffinityManager affinityManager = getIfAffinityManagerService(containerName);
485         if (affinityManager == null) {
486             throw new ServiceUnavailableException("Affinity Manager "
487                                                   + RestMessages.SERVICEUNAVAILABLE.toString());
488         }
489         log.info("getallgroups");
490         return new AffinityGroupList(affinityManager.getAllAffinityGroups());
491     }
492     */
493
494 }