26145c8cf7259ccd2d24adb051f38548829f06bc
[neutron.git] / northbound-api / src / main / java / org / opendaylight / neutron / northbound / api / NeutronSecurityRulesNorthbound.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.neutron.northbound.api;
11
12 import java.net.HttpURLConnection;
13
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.Iterator;
17 import java.util.List;
18
19 import javax.ws.rs.Consumes;
20 import javax.ws.rs.DELETE;
21 import javax.ws.rs.GET;
22 import javax.ws.rs.POST;
23 import javax.ws.rs.PUT;
24 import javax.ws.rs.Path;
25 import javax.ws.rs.PathParam;
26 import javax.ws.rs.Produces;
27 import javax.ws.rs.QueryParam;
28 import javax.ws.rs.core.MediaType;
29 import javax.ws.rs.core.Response;
30
31 import org.codehaus.enunciate.jaxrs.ResponseCode;
32 import org.codehaus.enunciate.jaxrs.StatusCodes;
33 import org.opendaylight.neutron.spi.INeutronSecurityRuleAware;
34 import org.opendaylight.neutron.spi.INeutronSecurityRuleCRUD;
35 import org.opendaylight.neutron.spi.NeutronCRUDInterfaces;
36 import org.opendaylight.neutron.spi.NeutronSecurityRule;
37
38 /**
39  * Neutron Northbound REST APIs for Security Rule.<br>
40  * This class provides REST APIs for managing neutron Security Rule
41  * <p>
42  * <br>
43  * <br>
44  * Authentication scheme : <b>HTTP Basic</b><br>
45  * Authentication realm : <b>opendaylight</b><br>
46  * Transport : <b>HTTP and HTTPS</b><br>
47  * <br>
48  * HTTPS Authentication is disabled by default. Administrator can enable it in
49  * tomcat-server.xml after adding a proper keystore / SSL certificate from a
50  * trusted authority.<br>
51  * More info :
52  * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
53  */
54
55 @Path ("/security-group-rules")
56 public class NeutronSecurityRulesNorthbound {
57     private static final int HTTP_OK_BOTTOM = 200;
58     private static final int HTTP_OK_TOP = 299;
59     private static final String INTERFACE_NAME = "Security Rule CRUD Interface";
60     private static final String UUID_NO_EXIST = "Security Rule UUID does not exist.";
61     private static final String UUID_EXISTS = "Security Rule UUID already exists.";
62     private static final String NO_PROVIDERS = "No providers registered.  Please try again later";
63     private static final String NO_PROVIDER_LIST = "Couldn't get providers list.  Please try again later";
64
65     private NeutronSecurityRule extractFields(NeutronSecurityRule o, List<String> fields) {
66         return o.extractFields(fields);
67     }
68
69     private NeutronCRUDInterfaces getNeutronInterfaces() {
70         NeutronCRUDInterfaces answer = new NeutronCRUDInterfaces().fetchINeutronSecurityRuleCRUD(this);
71         if (answer.getSecurityRuleInterface() == null) {
72             throw new ServiceUnavailableException(INTERFACE_NAME
73                 + RestMessages.SERVICEUNAVAILABLE.toString());
74         }
75         return answer;
76     }
77
78     /**
79      * Returns a list of all Security Rules
80      */
81     @GET
82     @Produces ({MediaType.APPLICATION_JSON})
83     @StatusCodes ({
84             @ResponseCode (code = HttpURLConnection.HTTP_OK, condition = "Operation successful"),
85             @ResponseCode (code = HttpURLConnection.HTTP_UNAUTHORIZED, condition = "Unauthorized"),
86             @ResponseCode(code = HttpURLConnection.HTTP_NOT_IMPLEMENTED, condition = "Not Implemented"),
87             @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
88     public Response listRules(
89             // return fields
90             @QueryParam ("fields") List<String> fields,
91             // OpenStack security rule attributes
92             @QueryParam ("id") String querySecurityRuleUUID,
93             @QueryParam ("direction") String querySecurityRuleDirection,
94             @QueryParam ("protocol") String querySecurityRuleProtocol,
95             @QueryParam ("port_range_min") Integer querySecurityRulePortMin,
96             @QueryParam ("port_range_max") Integer querySecurityRulePortMax,
97             @QueryParam ("ethertype") String querySecurityRuleEthertype,
98             @QueryParam ("remote_ip_prefix") String querySecurityRuleIpPrefix,
99             @QueryParam ("remote_group_id") String querySecurityRemoteGroupID,
100             @QueryParam ("security_group_id") String querySecurityRuleGroupID,
101             @QueryParam ("tenant_id") String querySecurityRuleTenantID,
102             @QueryParam ("limit") String limit,
103             @QueryParam ("marker") String marker,
104             @QueryParam ("page_reverse") String pageReverse
105     ) {
106         INeutronSecurityRuleCRUD securityRuleInterface = getNeutronInterfaces().getSecurityRuleInterface();
107         List<NeutronSecurityRule> allSecurityRules = securityRuleInterface.getAllNeutronSecurityRules();
108         List<NeutronSecurityRule> ans = new ArrayList<NeutronSecurityRule>();
109         Iterator<NeutronSecurityRule> i = allSecurityRules.iterator();
110         while (i.hasNext()) {
111             NeutronSecurityRule nsr = i.next();
112             if ((querySecurityRuleUUID == null ||
113                     querySecurityRuleUUID.equals(nsr.getSecurityRuleUUID())) &&
114                     (querySecurityRuleDirection == null ||
115                             querySecurityRuleDirection.equals(nsr.getSecurityRuleDirection())) &&
116                     (querySecurityRuleProtocol == null ||
117                             querySecurityRuleProtocol.equals(nsr.getSecurityRuleProtocol())) &&
118                     (querySecurityRulePortMin == null ||
119                             querySecurityRulePortMin.equals(nsr.getSecurityRulePortMin())) &&
120                     (querySecurityRulePortMax == null ||
121                             querySecurityRulePortMax.equals(nsr.getSecurityRulePortMax())) &&
122                     (querySecurityRuleEthertype == null ||
123                             querySecurityRuleEthertype.equals(nsr.getSecurityRuleEthertype())) &&
124                     (querySecurityRuleIpPrefix == null ||
125                             querySecurityRuleIpPrefix.equals(nsr.getSecurityRuleRemoteIpPrefix())) &&
126                     (querySecurityRuleGroupID == null ||
127                             querySecurityRuleGroupID.equals(nsr.getSecurityRuleGroupID())) &&
128                     (querySecurityRemoteGroupID == null ||
129                             querySecurityRemoteGroupID.equals(nsr.getSecurityRemoteGroupID())) &&
130                     (querySecurityRuleTenantID == null ||
131                             querySecurityRuleTenantID.equals(nsr.getSecurityRuleTenantID()))) {
132                 if (fields.size() > 0) {
133                     ans.add(extractFields(nsr, fields));
134                 } else {
135                     ans.add(nsr);
136                 }
137             }
138         }
139         return Response.status(HttpURLConnection.HTTP_OK).entity(
140                 new NeutronSecurityRuleRequest(ans)).build();
141     }
142
143     /**
144      * Returns a specific Security Rule
145      */
146
147     @Path ("{securityRuleUUID}")
148     @GET
149     @Produces ({MediaType.APPLICATION_JSON})
150     @StatusCodes ({
151             @ResponseCode (code = HttpURLConnection.HTTP_OK, condition = "Operation successful"),
152             @ResponseCode (code = HttpURLConnection.HTTP_UNAUTHORIZED, condition = "Unauthorized"),
153             @ResponseCode (code = HttpURLConnection.HTTP_NOT_FOUND, condition = "Not Found"),
154             @ResponseCode(code = HttpURLConnection.HTTP_NOT_IMPLEMENTED, condition = "Not Implemented"),
155             @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
156     public Response showSecurityRule(@PathParam ("securityRuleUUID") String securityRuleUUID,
157                                      // return fields
158                                      @QueryParam ("fields") List<String> fields) {
159         INeutronSecurityRuleCRUD securityRuleInterface = getNeutronInterfaces().getSecurityRuleInterface();
160         if (!securityRuleInterface.neutronSecurityRuleExists(securityRuleUUID)) {
161             throw new ResourceNotFoundException(UUID_NO_EXIST);
162         }
163         if (!fields.isEmpty()) {
164             NeutronSecurityRule ans = securityRuleInterface.getNeutronSecurityRule(securityRuleUUID);
165             return Response.status(HttpURLConnection.HTTP_OK).entity(
166                     new NeutronSecurityRuleRequest(extractFields(ans, fields))).build();
167         } else {
168             return Response.status(HttpURLConnection.HTTP_OK).entity(new NeutronSecurityRuleRequest(securityRuleInterface.getNeutronSecurityRule(securityRuleUUID))).build();
169         }
170     }
171
172     /**
173      * Creates new Security Rule
174      */
175
176     @POST
177     @Produces ({MediaType.APPLICATION_JSON})
178     @Consumes ({MediaType.APPLICATION_JSON})
179     @StatusCodes ({
180             @ResponseCode (code = HttpURLConnection.HTTP_CREATED, condition = "Created"),
181             @ResponseCode (code = HttpURLConnection.HTTP_BAD_REQUEST, condition = "Bad Request"),
182             @ResponseCode (code = HttpURLConnection.HTTP_UNAUTHORIZED, condition = "Unauthorized"),
183             @ResponseCode (code = HttpURLConnection.HTTP_FORBIDDEN, condition = "Forbidden"),
184             @ResponseCode (code = HttpURLConnection.HTTP_NOT_FOUND, condition = "Not Found"),
185             @ResponseCode (code = HttpURLConnection.HTTP_CONFLICT, condition = "Conflict"),
186             @ResponseCode(code = HttpURLConnection.HTTP_NOT_IMPLEMENTED, condition = "Not Implemented"),
187             @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
188     public Response createSecurityRules(final NeutronSecurityRuleRequest input) {
189         INeutronSecurityRuleCRUD securityRuleInterface = getNeutronInterfaces().getSecurityRuleInterface();
190
191         /*
192          * Existing entry checks
193         */
194
195         if (input.isSingleton()) {
196             NeutronSecurityRule singleton = input.getSingleton();
197
198             if (securityRuleInterface.neutronSecurityRuleExists(singleton.getSecurityRuleUUID())) {
199                 throw new BadRequestException(UUID_EXISTS);
200             }
201             Object[] instances = NeutronUtil.getInstances(INeutronSecurityRuleAware.class, this);
202             if (instances != null) {
203                 if (instances.length > 0) {
204                     for (Object instance : instances) {
205                         INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance;
206                         int status = service.canCreateNeutronSecurityRule(singleton);
207                         if ((status < HTTP_OK_BOTTOM) || (status > HTTP_OK_TOP)) {
208                             return Response.status(status).build();
209                         }
210                     }
211                 } else {
212                     throw new ServiceUnavailableException(NO_PROVIDERS);
213                 }
214             } else {
215                 throw new ServiceUnavailableException(NO_PROVIDER_LIST);
216             }
217
218             // add rule to cache
219             singleton.initDefaults();
220             securityRuleInterface.addNeutronSecurityRule(singleton);
221             if (instances != null) {
222                 for (Object instance : instances) {
223                     INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance;
224                     service.neutronSecurityRuleCreated(singleton);
225                 }
226             }
227         } else {
228             List<NeutronSecurityRule> bulk = input.getBulk();
229             Iterator<NeutronSecurityRule> i = bulk.iterator();
230             HashMap<String, NeutronSecurityRule> testMap = new HashMap<String, NeutronSecurityRule>();
231             Object[] instances = NeutronUtil.getInstances(INeutronSecurityRuleAware.class, this);
232             while (i.hasNext()) {
233                 NeutronSecurityRule test = i.next();
234
235                 /*
236                  *  Verify that the security rule doesn't already exist
237                  */
238
239                 if (securityRuleInterface.neutronSecurityRuleExists(test.getSecurityRuleUUID())) {
240                     throw new BadRequestException(UUID_EXISTS);
241                 }
242                 if (testMap.containsKey(test.getSecurityRuleUUID())) {
243                     throw new BadRequestException(UUID_EXISTS);
244                 }
245                 if (instances != null) {
246                     if (instances.length > 0) {
247                         for (Object instance : instances) {
248                             INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance;
249                             int status = service.canCreateNeutronSecurityRule(test);
250                             if ((status < HTTP_OK_BOTTOM) || (status > HTTP_OK_TOP)) {
251                                 return Response.status(status).build();
252                             }
253                         }
254                     } else {
255                         throw new ServiceUnavailableException(NO_PROVIDERS);
256                     }
257                 } else {
258                     throw new ServiceUnavailableException(NO_PROVIDER_LIST);
259                 }
260             }
261
262             /*
263              * now, each element of the bulk request can be added to the cache
264              */
265             i = bulk.iterator();
266             while (i.hasNext()) {
267                 NeutronSecurityRule test = i.next();
268                 securityRuleInterface.addNeutronSecurityRule(test);
269                 if (instances != null) {
270                     for (Object instance : instances) {
271                         INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance;
272                         service.neutronSecurityRuleCreated(test);
273                     }
274                 }
275             }
276         }
277         return Response.status(HttpURLConnection.HTTP_CREATED).entity(input).build();
278     }
279
280     /**
281      * Updates a Security Rule
282      */
283
284     @Path ("{securityRuleUUID}")
285     @PUT
286     @Produces ({MediaType.APPLICATION_JSON})
287     @Consumes ({MediaType.APPLICATION_JSON})
288     @StatusCodes ({
289             @ResponseCode (code = HttpURLConnection.HTTP_OK, condition = "Operation successful"),
290             @ResponseCode (code = HttpURLConnection.HTTP_BAD_REQUEST, condition = "Bad Request"),
291             @ResponseCode (code = HttpURLConnection.HTTP_UNAUTHORIZED, condition = "Unauthorized"),
292             @ResponseCode (code = HttpURLConnection.HTTP_FORBIDDEN, condition = "Forbidden"),
293             @ResponseCode (code = HttpURLConnection.HTTP_NOT_FOUND, condition = "Not Found"),
294             @ResponseCode(code = HttpURLConnection.HTTP_NOT_IMPLEMENTED, condition = "Not Implemented"),
295             @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
296     public Response updateSecurityRule(
297             @PathParam ("securityRuleUUID") String securityRuleUUID, final NeutronSecurityRuleRequest input) {
298         INeutronSecurityRuleCRUD securityRuleInterface = getNeutronInterfaces().getSecurityRuleInterface();
299
300         /*
301          * verify the Security Rule exists and there is only one delta provided
302          */
303         if (!securityRuleInterface.neutronSecurityRuleExists(securityRuleUUID)) {
304             throw new ResourceNotFoundException(UUID_NO_EXIST);
305         }
306         if (!input.isSingleton()) {
307             throw new BadRequestException("Only singleton edit supported");
308         }
309         NeutronSecurityRule delta = input.getSingleton();
310         NeutronSecurityRule original = securityRuleInterface.getNeutronSecurityRule(securityRuleUUID);
311
312         /*
313          * updates restricted by Neutron
314          *
315          */
316         if (delta.getSecurityRuleUUID() != null ||
317                 delta.getSecurityRuleDirection() != null ||
318                 delta.getSecurityRuleProtocol() != null ||
319                 delta.getSecurityRulePortMin() != null ||
320                 delta.getSecurityRulePortMax() != null ||
321                 delta.getSecurityRuleEthertype() != null ||
322                 delta.getSecurityRuleRemoteIpPrefix() != null ||
323                 delta.getSecurityRuleGroupID() != null ||
324                 delta.getSecurityRemoteGroupID() != null ||
325                 delta.getSecurityRuleTenantID() != null) {
326             throw new BadRequestException("Attribute edit blocked by Neutron");
327         }
328
329         Object[] instances = NeutronUtil.getInstances(INeutronSecurityRuleAware.class, this);
330         if (instances != null) {
331             if (instances.length > 0) {
332                 for (Object instance : instances) {
333                     INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance;
334                     int status = service.canUpdateNeutronSecurityRule(delta, original);
335                     if (status < HTTP_OK_BOTTOM || status > HTTP_OK_TOP) {
336                         return Response.status(status).build();
337                     }
338                 }
339             } else {
340                 throw new ServiceUnavailableException(NO_PROVIDERS);
341             }
342         } else {
343             throw new ServiceUnavailableException(NO_PROVIDER_LIST);
344         }
345
346         /*
347          * update the object and return it
348          */
349         securityRuleInterface.updateNeutronSecurityRule(securityRuleUUID, delta);
350         NeutronSecurityRule updatedSecurityRule = securityRuleInterface.getNeutronSecurityRule(securityRuleUUID);
351         if (instances != null) {
352             for (Object instance : instances) {
353                 INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance;
354                 service.neutronSecurityRuleUpdated(updatedSecurityRule);
355             }
356         }
357         return Response.status(HttpURLConnection.HTTP_OK).entity(new NeutronSecurityRuleRequest(securityRuleInterface.getNeutronSecurityRule(securityRuleUUID))).build();
358     }
359
360     /**
361      * Deletes a Security Rule
362      */
363
364     @Path ("{securityRuleUUID}")
365     @DELETE
366     @StatusCodes ({
367             @ResponseCode (code = HttpURLConnection.HTTP_NO_CONTENT, condition = "No Content"),
368             @ResponseCode (code = HttpURLConnection.HTTP_UNAUTHORIZED, condition = "Unauthorized"),
369             @ResponseCode (code = HttpURLConnection.HTTP_NOT_FOUND, condition = "Not Found"),
370             @ResponseCode (code = HttpURLConnection.HTTP_CONFLICT, condition = "Conflict"),
371             @ResponseCode(code = HttpURLConnection.HTTP_NOT_IMPLEMENTED, condition = "Not Implemented"),
372             @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
373     public Response deleteSecurityRule(
374             @PathParam ("securityRuleUUID") String securityRuleUUID) {
375         INeutronSecurityRuleCRUD securityRuleInterface = getNeutronInterfaces().getSecurityRuleInterface();
376
377         /*
378          * verify the Security Rule exists and it isn't currently in use
379          */
380         if (!securityRuleInterface.neutronSecurityRuleExists(securityRuleUUID)) {
381             throw new ResourceNotFoundException(UUID_NO_EXIST);
382         }
383         if (securityRuleInterface.neutronSecurityRuleInUse(securityRuleUUID)) {
384             return Response.status(HttpURLConnection.HTTP_CONFLICT).build();
385         }
386         NeutronSecurityRule singleton = securityRuleInterface.getNeutronSecurityRule(securityRuleUUID);
387         Object[] instances = NeutronUtil.getInstances(INeutronSecurityRuleAware.class, this);
388         if (instances != null) {
389             if (instances.length > 0) {
390                 for (Object instance : instances) {
391                     INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance;
392                     int status = service.canDeleteNeutronSecurityRule(singleton);
393                     if (status < HTTP_OK_BOTTOM || status > HTTP_OK_TOP) {
394                         return Response.status(status).build();
395                     }
396                 }
397             } else {
398                 throw new ServiceUnavailableException(NO_PROVIDERS);
399             }
400         } else {
401             throw new ServiceUnavailableException(NO_PROVIDER_LIST);
402         }
403
404
405         /*
406          * remove it and return 204 status
407          */
408         securityRuleInterface.removeNeutronSecurityRule(securityRuleUUID);
409         if (instances != null) {
410             for (Object instance : instances) {
411                 INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance;
412                 service.neutronSecurityRuleDeleted(singleton);
413             }
414         }
415         return Response.status(HttpURLConnection.HTTP_NO_CONTENT).build();
416     }
417 }