Neutron API v2.0 bindings and APIs for security groups/rules.
[controller.git] / opendaylight / northbound / networkconfiguration / neutron / src / main / java / org / opendaylight / controller / networkconfig / neutron / northbound / NeutronSecurityGroupsNorthbound.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
10 package org.opendaylight.controller.networkconfig.neutron.northbound;
11
12
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.Iterator;
16 import java.util.List;
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.QueryParam;
26 import javax.ws.rs.core.MediaType;
27 import javax.ws.rs.core.Response;
28
29 import org.codehaus.enunciate.jaxrs.ResponseCode;
30 import org.codehaus.enunciate.jaxrs.StatusCodes;
31 import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityGroupAware;
32 import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityGroupCRUD;
33 import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
34 import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityGroup;
35 import org.opendaylight.controller.northbound.commons.RestMessages;
36 import org.opendaylight.controller.northbound.commons.exception.BadRequestException;
37 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
38 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
39 import org.opendaylight.controller.sal.utils.ServiceHelper;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 /**
44  * Neutron Northbound REST APIs for Security Group.<br>
45  * This class provides REST APIs for managing neutron Security Group
46  * <p/>
47  * <br>
48  * <br>
49  * Authentication scheme : <b>HTTP Basic</b><br>
50  * Authentication realm : <b>opendaylight</b><br>
51  * Transport : <b>HTTP and HTTPS</b><br>
52  * <br>
53  * HTTPS Authentication is disabled by default. Administrator can enable it in
54  * tomcat-server.xml after adding a proper keystore / SSL certificate from a
55  * trusted authority.<br>
56  * More info :
57  * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
58  */
59 @Path ("/security-groups")
60 public class NeutronSecurityGroupsNorthbound {
61     static final Logger logger = LoggerFactory.getLogger(NeutronSecurityGroupsNorthbound.class);
62
63     private NeutronSecurityGroup extractFields(NeutronSecurityGroup o, List<String> fields) {
64         return o.extractFields(fields);
65     }
66
67     /**
68      * Returns a list of all Security Groups
69      */
70     @GET
71     @Produces ({MediaType.APPLICATION_JSON})
72     @StatusCodes ({
73             @ResponseCode (code = 200, condition = "Operation successful"),
74             @ResponseCode (code = 401, condition = "Unauthorized"),
75             @ResponseCode (code = 501, condition = "Not Implemented")})
76
77     public Response listGroups(
78             // return fields
79             @QueryParam ("fields") List<String> fields,
80             // OpenStack security group attributes
81             @QueryParam ("id") String querySecurityGroupUUID,
82             @QueryParam ("name") String querySecurityGroupName,
83             @QueryParam ("description") String querySecurityDescription,
84             @QueryParam ("tenant_id") String querySecurityTenantID,
85             @QueryParam ("limit") String limit,
86             @QueryParam ("marker") String marker,
87             @QueryParam ("page_reverse") String pageReverse
88     ) {
89         INeutronSecurityGroupCRUD securityGroupInterface = NeutronCRUDInterfaces.getINeutronSecurityGroupCRUD(this);
90
91         if (securityGroupInterface == null) {
92             throw new ServiceUnavailableException("Security Group CRUD Interface "
93                     + RestMessages.SERVICEUNAVAILABLE.toString());
94         }
95         List<NeutronSecurityGroup> allSecurityGroups = securityGroupInterface.getAllNeutronSecurityGroups();
96         List<NeutronSecurityGroup> ans = new ArrayList<NeutronSecurityGroup>();
97         Iterator<NeutronSecurityGroup> i = allSecurityGroups.iterator();
98         while (i.hasNext()) {
99             NeutronSecurityGroup nsg = i.next();
100             if ((querySecurityGroupUUID == null ||
101                     querySecurityGroupUUID.equals(nsg.getSecurityGroupUUID())) &&
102                     (querySecurityGroupName == null ||
103                             querySecurityGroupName.equals(nsg.getSecurityGroupName())) &&
104                     (querySecurityDescription == null ||
105                             querySecurityDescription.equals(nsg.getSecurityGroupDescription())) &&
106                     (querySecurityTenantID == null ||
107                             querySecurityTenantID.equals(nsg.getSecurityGroupTenantID()))) {
108                 if (fields.size() > 0) {
109                     ans.add(extractFields(nsg, fields));
110                 } else {
111                     ans.add(nsg);
112                 }
113             }
114         }
115         return Response.status(200).entity(
116                 new NeutronSecurityGroupRequest(ans)).build();
117     }
118
119     /**
120      * Returns a specific Security Group
121      */
122
123     @Path ("{securityGroupUUID}")
124     @GET
125     @Produces ({MediaType.APPLICATION_JSON})
126     @StatusCodes ({
127             @ResponseCode (code = 200, condition = "Operation successful"),
128             @ResponseCode (code = 401, condition = "Unauthorized"),
129             @ResponseCode (code = 404, condition = "Not Found"),
130             @ResponseCode (code = 501, condition = "Not Implemented")})
131     public Response showSecurityGroup(@PathParam ("securityGroupUUID") String securityGroupUUID,
132                                       // return fields
133                                       @QueryParam ("fields") List<String> fields) {
134         INeutronSecurityGroupCRUD securityGroupInterface = NeutronCRUDInterfaces.getINeutronSecurityGroupCRUD(this);
135         if (securityGroupInterface == null) {
136             throw new ServiceUnavailableException("Security Group CRUD Interface "
137                     + RestMessages.SERVICEUNAVAILABLE.toString());
138         }
139         if (!securityGroupInterface.neutronSecurityGroupExists(securityGroupUUID)) {
140             throw new ResourceNotFoundException("Security Group UUID does not exist.");
141         }
142         if (!fields.isEmpty()) {
143             NeutronSecurityGroup ans = securityGroupInterface.getNeutronSecurityGroup(securityGroupUUID);
144             return Response.status(200).entity(
145                     new NeutronSecurityGroupRequest(extractFields(ans, fields))).build();
146         } else {
147             return Response.status(200).entity(new NeutronSecurityGroupRequest(securityGroupInterface.getNeutronSecurityGroup(securityGroupUUID))).build();
148         }
149     }
150
151     /**
152      * Creates new Security Group
153      */
154
155     @POST
156     @Produces ({MediaType.APPLICATION_JSON})
157     @Consumes ({MediaType.APPLICATION_JSON})
158     @StatusCodes ({
159             @ResponseCode (code = 201, condition = "Created"),
160             @ResponseCode (code = 400, condition = "Bad Request"),
161             @ResponseCode (code = 401, condition = "Unauthorized"),
162             @ResponseCode (code = 403, condition = "Forbidden"),
163             @ResponseCode (code = 404, condition = "Not Found"),
164             @ResponseCode (code = 409, condition = "Conflict"),
165             @ResponseCode (code = 501, condition = "Not Implemented")})
166     public Response createSecurityGroups(final NeutronSecurityGroupRequest input) {
167         INeutronSecurityGroupCRUD securityGroupInterface = NeutronCRUDInterfaces.getINeutronSecurityGroupCRUD(this);
168         if (securityGroupInterface == null) {
169             throw new ServiceUnavailableException("Security Group CRUD Interface "
170                     + RestMessages.SERVICEUNAVAILABLE.toString());
171         }
172
173         if (input.isSingleton()) {
174             NeutronSecurityGroup singleton = input.getSingleton();
175
176             /*
177              *  Verify that the Security Group doesn't already exist.
178              */
179             if (securityGroupInterface.neutronSecurityGroupExists(singleton.getSecurityGroupUUID())) {
180                 throw new BadRequestException("Security Group UUID already exists");
181             }
182
183             Object[] instances = ServiceHelper.getGlobalInstances(INeutronSecurityGroupAware.class, this, null);
184             if (instances != null) {
185                 for (Object instance : instances) {
186                     INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance;
187                     int status = service.canCreateNeutronSecurityGroup(singleton);
188                     if (status < 200 || status > 299) {
189                         return Response.status(status).build();
190                     }
191                 }
192             }
193             // Add to Neutron cache
194             securityGroupInterface.addNeutronSecurityGroup(singleton);
195             if (instances != null) {
196                 for (Object instance : instances) {
197                     INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance;
198                     service.neutronSecurityGroupCreated(singleton);
199                 }
200             }
201         } else {
202             List<NeutronSecurityGroup> bulk = input.getBulk();
203             Iterator<NeutronSecurityGroup> i = bulk.iterator();
204             HashMap<String, NeutronSecurityGroup> testMap = new HashMap<String, NeutronSecurityGroup>();
205             Object[] instances = ServiceHelper.getGlobalInstances(INeutronSecurityGroupAware.class, this, null);
206             while (i.hasNext()) {
207                 NeutronSecurityGroup test = i.next();
208
209                 /*
210                  *  Verify that the security group doesn't already exist
211                  */
212
213                 if (securityGroupInterface.neutronSecurityGroupExists(test.getSecurityGroupUUID())) {
214                     throw new BadRequestException("Security Group UUID already is already created");
215                 }
216                 if (instances != null) for (Object instance : instances) {
217                     INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance;
218                     int status = service.canCreateNeutronSecurityGroup(test);
219                     if ((status < 200) || (status > 299)) return Response.status(status).build();
220                 }
221             }
222
223             /*
224              * now, each element of the bulk request can be added to the cache
225              */
226             i = bulk.iterator();
227             while (i.hasNext()) {
228                 NeutronSecurityGroup test = i.next();
229                 securityGroupInterface.addNeutronSecurityGroup(test);
230                 if (instances != null) {
231                     for (Object instance : instances) {
232                         INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance;
233                         service.neutronSecurityGroupCreated(test);
234                     }
235                 }
236             }
237         }
238         return Response.status(201).entity(input).build();
239     }
240
241     /**
242      * Updates a Security Group
243      */
244
245     @Path ("{securityGroupUUID}")
246     @PUT
247     @Produces ({MediaType.APPLICATION_JSON})
248     @Consumes ({MediaType.APPLICATION_JSON})
249     @StatusCodes ({
250             @ResponseCode (code = 200, condition = "Operation successful"),
251             @ResponseCode (code = 400, condition = "Bad Request"),
252             @ResponseCode (code = 401, condition = "Unauthorized"),
253             @ResponseCode (code = 403, condition = "Forbidden"),
254             @ResponseCode (code = 404, condition = "Not Found"),
255             @ResponseCode (code = 501, condition = "Not Implemented")})
256     public Response updateSecurityGroup(
257             @PathParam ("securityGroupUUID") String securityGroupUUID, final NeutronSecurityGroupRequest input) {
258         INeutronSecurityGroupCRUD securityGroupInterface = NeutronCRUDInterfaces.getINeutronSecurityGroupCRUD(this);
259         if (securityGroupInterface == null) {
260             throw new ServiceUnavailableException("Security Group CRUD Interface "
261                     + RestMessages.SERVICEUNAVAILABLE.toString());
262         }
263
264         /*
265          * verify the Security Group exists and there is only one delta provided
266          */
267         if (!securityGroupInterface.neutronSecurityGroupExists(securityGroupUUID)) {
268             throw new ResourceNotFoundException("Security Group UUID does not exist.");
269         }
270         if (!input.isSingleton()) {
271             throw new BadRequestException("Only singleton edit supported");
272         }
273         NeutronSecurityGroup delta = input.getSingleton();
274         NeutronSecurityGroup original = securityGroupInterface.getNeutronSecurityGroup(securityGroupUUID);
275
276         if (delta.getSecurityGroupUUID() != null ||
277                 delta.getSecurityGroupTenantID() != null ||
278                 delta.getSecurityGroupName() != null ||
279                 delta.getSecurityGroupDescription() != null) {
280             throw new BadRequestException("Attribute edit blocked by Neutron");
281         }
282
283         Object[] instances = ServiceHelper.getGlobalInstances(INeutronSecurityGroupAware.class, this, null);
284         if (instances != null) {
285             for (Object instance : instances) {
286                 INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance;
287                 int status = service.canUpdateNeutronSecurityGroup(delta, original);
288                 if (status < 200 || status > 299) {
289                     return Response.status(status).build();
290                 }
291             }
292         }
293
294         /*
295          * update the object and return it
296          */
297         securityGroupInterface.updateNeutronSecurityGroup(securityGroupUUID, delta);
298         NeutronSecurityGroup updatedSecurityGroup = securityGroupInterface.getNeutronSecurityGroup(securityGroupUUID);
299         if (instances != null) {
300             for (Object instance : instances) {
301                 INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance;
302                 service.neutronSecurityGroupUpdated(updatedSecurityGroup);
303             }
304         }
305         return Response.status(200).entity(new NeutronSecurityGroupRequest(securityGroupInterface.getNeutronSecurityGroup(securityGroupUUID))).build();
306     }
307
308     /**
309      * Deletes a Security Group
310      */
311
312     @Path ("{securityGroupUUID}")
313     @DELETE
314     @StatusCodes ({
315             @ResponseCode (code = 204, condition = "No Content"),
316             @ResponseCode (code = 401, condition = "Unauthorized"),
317             @ResponseCode (code = 404, condition = "Not Found"),
318             @ResponseCode (code = 409, condition = "Conflict"),
319             @ResponseCode (code = 501, condition = "Not Implemented")})
320     public Response deleteSecurityGroup(
321             @PathParam ("securityGroupUUID") String securityGroupUUID) {
322         INeutronSecurityGroupCRUD securityGroupInterface = NeutronCRUDInterfaces.getINeutronSecurityGroupCRUD(this);
323         if (securityGroupInterface == null) {
324             throw new ServiceUnavailableException("Security Group CRUD Interface "
325                     + RestMessages.SERVICEUNAVAILABLE.toString());
326         }
327
328         /*
329          * verify the Security Group exists and it isn't currently in use
330          */
331         if (!securityGroupInterface.neutronSecurityGroupExists(securityGroupUUID)) {
332             throw new ResourceNotFoundException("Security Group UUID does not exist.");
333         }
334         if (securityGroupInterface.neutronSecurityGroupInUse(securityGroupUUID)) {
335             return Response.status(409).build();
336         }
337         NeutronSecurityGroup singleton = securityGroupInterface.getNeutronSecurityGroup(securityGroupUUID);
338         Object[] instances = ServiceHelper.getGlobalInstances(INeutronSecurityGroupAware.class, this, null);
339         if (instances != null) {
340             for (Object instance : instances) {
341                 INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance;
342                 int status = service.canDeleteNeutronSecurityGroup(singleton);
343                 if ((status < 200) || (status > 299)) {
344                     return Response.status(status).build();
345                 }
346             }
347         }
348
349         /*
350          * remove it and return 204 status
351          */
352         securityGroupInterface.removeNeutronSecurityGroup(securityGroupUUID);
353         if (instances != null) {
354             for (Object instance : instances) {
355                 INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance;
356                 service.neutronSecurityGroupDeleted(singleton);
357             }
358         }
359         return Response.status(204).build();
360     }
361 }