73bca80f1de0b747a0724c926b6ff8fb1b0541c3
[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         }
234         return Response.status(Response.Status.CREATED).build();
235     }
236
237
238     /**
239      * Add path redirect details to an affinity link. 
240      *
241      * @param containerName
242      *            Name of the Container
243      * @param affinityLinkName
244      *            Name of the new affinity link being added
245      * @param wayPoint
246      *            IP address string of a waypoint server or VM
247      * @return Response as dictated by the HTTP Response Status code
248      */
249
250     @Path("/{containerName}/link/{affinityLinkName}/setwaypoint/{waypointIP}")
251     @PUT
252     @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
253     @TypeHint(Response.class)
254     @StatusCodes({
255             @ResponseCode(code = 200, condition = "Operation successful"),
256             @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
257             @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
258     public Response setLinkWaypoint(
259             @PathParam("containerName") String containerName,
260             @PathParam("affinityLinkName") String affinityLinkName,
261             @PathParam("waypointIP") String waypointIP) {
262
263         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
264             throw new UnauthorizedException("User is not authorized to perform this operation on container "
265                                             + containerName);
266         }
267
268         IAffinityManager affinityManager = getIfAffinityManagerService(containerName);
269         if (affinityManager == null) {
270             throw new ServiceUnavailableException("Affinity Manager "
271                                                   + RestMessages.SERVICEUNAVAILABLE.toString());
272         }
273         log.info("Set waypoint address (link)" + affinityLinkName + " (waypoint ip) " + waypointIP);
274
275         AffinityLink al1 = affinityManager.getAffinityLink(affinityLinkName);
276         al1.setWaypoint(waypointIP);
277         try {
278             affinityManager.addNfchain(al1);
279         } catch (Exception e) {
280             String message = "An error occurred during flow programming.";
281             log.error(message, e);
282         }
283         return Response.status(Response.Status.CREATED).build();
284     }
285
286
287     @Path("/{containerName}/link/{affinityLinkName}/enable")
288     @PUT
289     @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
290     @TypeHint(Response.class)
291     @StatusCodes({
292             @ResponseCode(code = 200, condition = "Operation successful"),
293             @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
294             @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
295     public Response enableLink(
296             @PathParam("containerName") String containerName,
297             @PathParam("affinityLinkName") String affinityLinkName) {
298
299         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
300             throw new UnauthorizedException("User is not authorized to perform this operation on container "
301                                             + containerName);
302         }
303
304         IAffinityManager affinityManager = getIfAffinityManagerService(containerName);
305         if (affinityManager == null) {
306             throw new ServiceUnavailableException("Affinity Manager "
307                                                   + RestMessages.SERVICEUNAVAILABLE.toString());
308         }
309         log.info("Enable (link) " + affinityLinkName);
310
311         AffinityLink al1 = affinityManager.getAffinityLink(affinityLinkName);
312         try {
313             affinityManager.enableRedirect(al1);
314         } catch (Exception e) {
315             String message = "An error occurred during flow programming.";
316             log.error(message, e);
317         }
318         return Response.status(Response.Status.CREATED).build();
319     }
320
321     @Path("/{containerName}/link/{affinityLinkName}/disable")
322     @PUT
323     @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
324     @TypeHint(Response.class)
325     @StatusCodes({
326             @ResponseCode(code = 200, condition = "Operation successful"),
327             @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
328             @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
329     public Response disableLink(
330             @PathParam("containerName") String containerName,
331             @PathParam("affinityLinkName") String affinityLinkName) {
332
333         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
334             throw new UnauthorizedException("User is not authorized to perform this operation on container "
335                                             + containerName);
336         }
337
338         IAffinityManager affinityManager = getIfAffinityManagerService(containerName);
339         if (affinityManager == null) {
340             throw new ServiceUnavailableException("Affinity Manager "
341                                                   + RestMessages.SERVICEUNAVAILABLE.toString());
342         }
343         log.info("Disable (link) " + affinityLinkName);
344
345         AffinityLink al1 = affinityManager.getAffinityLink(affinityLinkName);
346         try {
347             affinityManager.disableRedirect(al1);
348         } catch (Exception e) {
349             String message = "An error occurred during flow programming.";
350             log.error(message, e);
351         }
352         return Response.status(Response.Status.CREATED).build();
353     }
354
355     /**
356      * Add IP addresses to a group. 
357      *
358      * @param containerName
359      *            Name of the Container
360      * @param affinityGroupName
361      *            Name of the affinity group to add to. 
362      * @param ipaddress
363      *            IP address of the new affinity member. 
364      * @return Response as dictated by the HTTP Response Status code
365      */
366     @Path("/{containerName}/group/{affinityGroupName}/add/ip/{ipaddress}")
367     @PUT
368     @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
369     @TypeHint(Response.class)
370     @StatusCodes({
371             @ResponseCode(code = 200, condition = "Operation successful"),
372             @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
373             @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
374     public Response addInetAddress(
375             @PathParam("containerName") String containerName,
376             @PathParam("affinityGroupName") String affinityGroupName,
377             @PathParam("ipaddress") String ipaddress) {
378         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
379             throw new UnauthorizedException("User is not authorized to perform this operation on container "
380                                             + containerName);
381         }
382         
383         IAffinityManager affinityManager = getIfAffinityManagerService(containerName);
384         if (affinityManager == null) {
385             throw new ServiceUnavailableException("Affinity Manager "
386                                                   + RestMessages.SERVICEUNAVAILABLE.toString());
387         }
388         
389         log.info("add Inet address " + affinityGroupName + " (ipaddress) " + ipaddress);
390         AffinityGroup ag1 = affinityManager.getAffinityGroup(affinityGroupName);
391         ag1.add(ipaddress);
392         
393         return Response.status(Response.Status.CREATED).build();
394     }
395     
396     /**
397      * Add prefix/mask subnet as a member of the affinity group.
398      *
399      * @param containerName
400      *            Name of the Container
401      * @param affinityGroupName
402      *            Name of the affinity group to add to. 
403      * @param ipmask
404      *            a.b.c.d/mm format of a set of IP addresses to add.
405      * @return Response as dictated by the HTTP Response Status code
406      */
407     @Path("/{containerName}/group/{affinityGroupName}/addsubnet/ipprefix/{ipprefix}/mask/{mask}")
408     @PUT
409     @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
410     @TypeHint(Response.class)
411     @StatusCodes({
412             @ResponseCode(code = 200, condition = "Operation successful"),
413             @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
414             @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
415     public Response addSubnet(
416             @PathParam("containerName") String containerName,
417             @PathParam("affinityGroupName") String affinityGroupName,
418             @PathParam("ipprefix") String ipprefix,
419             @PathParam("mask") String mask) {
420         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, 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         
431         log.info("addSubnet to affinitygroup" + affinityGroupName);
432         AffinityGroup ag1 = affinityManager.getAffinityGroup(affinityGroupName);
433         String ipmask = ipprefix + "/" + mask;
434         ag1.addInetMask(ipmask);
435         
436         return Response.status(Response.Status.CREATED).build();
437     }
438
439
440     @Path("/{containerName}/affinity-groups")
441     @GET
442     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
443     @TypeHint(AffinityGroupList.class)
444     @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"),
445         @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
446         @ResponseCode(code = 404, condition = "The containerName is not found"),
447         @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
448     public AffinityGroupList getAllAffinityGroups(@PathParam("containerName") String containerName) {
449
450         //        if (!isValidContainer(containerName)) {
451         //            throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
452         //}
453
454         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
455             throw new UnauthorizedException("User is not authorized to perform this operation on container "
456                     + containerName);
457         }
458
459         IAffinityManager affinityManager = getIfAffinityManagerService(containerName);
460         if (affinityManager == null) {
461             throw new ServiceUnavailableException("Affinity Manager "
462                                                   + RestMessages.SERVICEUNAVAILABLE.toString());
463         }
464         log.info("getallgroups");
465         return new AffinityGroupList(affinityManager.getAllAffinityGroups());
466     }
467
468     /**
469     @Path("/{containerName}/")
470     @GET
471     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
472     @TypeHint(AffinityGroupList.class)
473     @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"),
474         @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
475         @ResponseCode(code = 404, condition = "The containerName is not found"),
476         @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
477     public AffinityGroupList getAllAffinityGroups(@PathParam("containerName") String containerName) {
478
479         //        if (!isValidContainer(containerName)) {
480         //            throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
481         //}
482
483         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
484             throw new UnauthorizedException("User is not authorized to perform this operation on container "
485                     + containerName);
486         }
487
488         IAffinityManager affinityManager = getIfAffinityManagerService(containerName);
489         if (affinityManager == null) {
490             throw new ServiceUnavailableException("Affinity Manager "
491                                                   + RestMessages.SERVICEUNAVAILABLE.toString());
492         }
493         log.info("getallgroups");
494         return new AffinityGroupList(affinityManager.getAllAffinityGroups());
495     }
496     */
497
498 }