northbound: introduce a base class for nortubhound classes
[neutron.git] / northbound-api / src / main / java / org / opendaylight / neutron / northbound / api / NeutronNetworksNorthbound.java
1 /*
2  * Copyright (c) 2013, 2015 IBM Corporation 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.neutron.northbound.api;
10
11 import java.net.HttpURLConnection;
12
13 import java.util.ArrayList;
14 import java.util.Iterator;
15 import java.util.List;
16
17 import javax.ws.rs.Consumes;
18 import javax.ws.rs.DELETE;
19 import javax.ws.rs.DefaultValue;
20 import javax.ws.rs.GET;
21 import javax.ws.rs.POST;
22 import javax.ws.rs.PUT;
23 import javax.ws.rs.Path;
24 import javax.ws.rs.PathParam;
25 import javax.ws.rs.Produces;
26 import javax.ws.rs.QueryParam;
27 import javax.ws.rs.core.Context;
28 import javax.ws.rs.core.MediaType;
29 import javax.ws.rs.core.Response;
30 import javax.ws.rs.core.UriInfo;
31
32 import org.codehaus.enunciate.jaxrs.ResponseCode;
33 import org.codehaus.enunciate.jaxrs.StatusCodes;
34 import org.codehaus.enunciate.jaxrs.TypeHint;
35 import org.opendaylight.neutron.spi.INeutronNetworkAware;
36 import org.opendaylight.neutron.spi.INeutronNetworkCRUD;
37 import org.opendaylight.neutron.spi.NeutronCRUDInterfaces;
38 import org.opendaylight.neutron.spi.NeutronNetwork;
39
40 /**
41  * Neutron Northbound REST APIs for Network.<br>
42  * This class provides REST APIs for managing neutron Networks
43  *
44  * <br>
45  * <br>
46  * Authentication scheme : <b>HTTP Basic</b><br>
47  * Authentication realm : <b>opendaylight</b><br>
48  * Transport : <b>HTTP and HTTPS</b><br>
49  * <br>
50  * HTTPS Authentication is disabled by default. Administrator can enable it in
51  * tomcat-server.xml after adding a proper keystore / SSL certificate from a
52  * trusted authority.<br>
53  * More info :
54  * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
55  *
56  */
57
58 @Path("/networks")
59 public class NeutronNetworksNorthbound extends AbstractNeutronNorthbound {
60
61     @Context
62     UriInfo uriInfo;
63
64     private static final String RESOURCE_NAME = "Network";
65
66     private NeutronNetwork extractFields(NeutronNetwork o, List<String> fields) {
67         return o.extractFields(fields);
68     }
69
70     private NeutronCRUDInterfaces getNeutronInterfaces() {
71         NeutronCRUDInterfaces answer = new NeutronCRUDInterfaces().fetchINeutronNetworkCRUD(this);
72         if (answer.getNetworkInterface() == null) {
73             throw new ServiceUnavailableException(serviceUnavailable(RESOURCE_NAME));
74         }
75         return answer;
76     }
77
78     /**
79      * Returns a list of all Networks */
80
81     @GET
82     @Produces({ MediaType.APPLICATION_JSON })
83     //@TypeHint(OpenStackNetworks.class)
84     @StatusCodes({
85         @ResponseCode(code = HttpURLConnection.HTTP_OK, condition = "Operation successful"),
86         @ResponseCode(code = HttpURLConnection.HTTP_UNAUTHORIZED, condition = "Unauthorized"),
87         @ResponseCode(code = HttpURLConnection.HTTP_NOT_IMPLEMENTED, condition = "Not Implemented"),
88         @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
89     public Response listNetworks(
90             // return fields
91             @QueryParam("fields") List<String> fields,
92             // note: openstack isn't clear about filtering on lists, so we aren't handling them
93             @QueryParam("id") String queryID,
94             @QueryParam("name") String queryName,
95             @QueryParam("admin_state_up") String queryAdminStateUp,
96             @QueryParam("status") String queryStatus,
97             @QueryParam("shared") String queryShared,
98             @QueryParam("tenant_id") String queryTenantID,
99             @QueryParam("router_external") String queryRouterExternal,
100             @QueryParam("provider_network_type") String queryProviderNetworkType,
101             @QueryParam("provider_physical_network") String queryProviderPhysicalNetwork,
102             @QueryParam("provider_segmentation_id") String queryProviderSegmentationID,
103             // linkTitle
104             @QueryParam("limit") Integer limit,
105             @QueryParam("marker") String marker,
106             @DefaultValue("false") @QueryParam("page_reverse") Boolean pageReverse
107             // sorting not supported
108             ) {
109         INeutronNetworkCRUD networkInterface = getNeutronInterfaces().getNetworkInterface();
110         List<NeutronNetwork> allNetworks = networkInterface.getAllNetworks();
111         List<NeutronNetwork> ans = new ArrayList<NeutronNetwork>();
112         Iterator<NeutronNetwork> i = allNetworks.iterator();
113         while (i.hasNext()) {
114             NeutronNetwork oSN = i.next();
115             //match filters: TODO provider extension
116             Boolean bAdminStateUp = null;
117             Boolean bShared = null;
118             Boolean bRouterExternal = null;
119             if (queryAdminStateUp != null) {
120                 bAdminStateUp = Boolean.valueOf(queryAdminStateUp);
121             }
122             if (queryShared != null) {
123                 bShared = Boolean.valueOf(queryShared);
124             }
125             if (queryRouterExternal != null) {
126                 bRouterExternal = Boolean.valueOf(queryRouterExternal);
127             }
128             if ((queryID == null || queryID.equals(oSN.getID())) &&
129                     (queryName == null || queryName.equals(oSN.getNetworkName())) &&
130                     (bAdminStateUp == null || bAdminStateUp.booleanValue() == oSN.isAdminStateUp()) &&
131                     (queryStatus == null || queryStatus.equals(oSN.getStatus())) &&
132                     (bShared == null || bShared.booleanValue() == oSN.isShared()) &&
133                     (bRouterExternal == null || bRouterExternal.booleanValue() == oSN.isRouterExternal()) &&
134                     (queryTenantID == null || queryTenantID.equals(oSN.getTenantID()))) {
135                 if (fields.size() > 0) {
136                     ans.add(extractFields(oSN,fields));
137                 } else {
138                     ans.add(oSN);
139                 }
140             }
141         }
142
143         if (limit != null && ans.size() > 1) {
144             // Return a paginated request
145             NeutronNetworkRequest request = (NeutronNetworkRequest) PaginatedRequestFactory.createRequest(limit,
146                     marker, pageReverse, uriInfo, ans, NeutronNetwork.class);
147             return Response.status(HttpURLConnection.HTTP_OK).entity(request).build();
148         }
149
150     return Response.status(HttpURLConnection.HTTP_OK).entity(new NeutronNetworkRequest(ans)).build();
151
152     }
153
154     /**
155      * Returns a specific Network */
156
157     @Path("{netUUID}")
158     @GET
159     @Produces({ MediaType.APPLICATION_JSON })
160     //@TypeHint(OpenStackNetworks.class)
161     @StatusCodes({
162         @ResponseCode(code = HttpURLConnection.HTTP_OK, condition = "Operation successful"),
163         @ResponseCode(code = HttpURLConnection.HTTP_UNAUTHORIZED, condition = "Unauthorized"),
164         @ResponseCode(code = HttpURLConnection.HTTP_NOT_FOUND, condition = "Not Found"),
165         @ResponseCode(code = HttpURLConnection.HTTP_NOT_IMPLEMENTED, condition = "Not Implemented"),
166         @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
167     public Response showNetwork(
168             @PathParam("netUUID") String netUUID,
169             // return fields
170             @QueryParam("fields") List<String> fields
171             ) {
172         INeutronNetworkCRUD networkInterface = getNeutronInterfaces().getNetworkInterface();
173         if (!networkInterface.networkExists(netUUID)) {
174             throw new ResourceNotFoundException(uuidNoExist(RESOURCE_NAME));
175         }
176         if (fields.size() > 0) {
177             NeutronNetwork ans = networkInterface.getNetwork(netUUID);
178             return Response.status(HttpURLConnection.HTTP_OK).entity(
179                     new NeutronNetworkRequest(extractFields(ans, fields))).build();
180         } else {
181             return Response.status(HttpURLConnection.HTTP_OK).entity(
182                     new NeutronNetworkRequest(networkInterface.getNetwork(netUUID))).build();
183         }
184     }
185
186     /**
187      * Creates new Networks */
188     @POST
189     @Produces({ MediaType.APPLICATION_JSON })
190     @Consumes({ MediaType.APPLICATION_JSON })
191     @TypeHint(NeutronNetwork.class)
192     @StatusCodes({
193         @ResponseCode(code = HttpURLConnection.HTTP_CREATED, condition = "Created"),
194         @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
195     public Response createNetworks(final NeutronNetworkRequest input) {
196         INeutronNetworkCRUD networkInterface = getNeutronInterfaces().getNetworkInterface();
197         if (input.isSingleton()) {
198             NeutronNetwork singleton = input.getSingleton();
199
200             Object[] instances = NeutronUtil.getInstances(INeutronNetworkAware.class, this);
201             if (instances != null) {
202                 if (instances.length > 0) {
203                     for (Object instance : instances) {
204                         INeutronNetworkAware service = (INeutronNetworkAware) instance;
205                         int status = service.canCreateNetwork(singleton);
206                         if (status < HTTP_OK_BOTTOM || status > HTTP_OK_TOP) {
207                             return Response.status(status).build();
208                         }
209                     }
210                 } else {
211                     throw new ServiceUnavailableException(NO_PROVIDERS);
212                 }
213             } else {
214                 throw new ServiceUnavailableException(NO_PROVIDER_LIST);
215             }
216
217             // add network to cache
218             singleton.initDefaults();
219             networkInterface.addNetwork(singleton);
220             if (instances != null) {
221                 for (Object instance : instances) {
222                     INeutronNetworkAware service = (INeutronNetworkAware) instance;
223                     service.neutronNetworkCreated(singleton);
224                 }
225             }
226
227         } else {
228             Object[] instances = NeutronUtil.getInstances(INeutronNetworkAware.class, this);
229             for (NeutronNetwork test : input.getBulk()) {
230                 if (instances != null) {
231                     if (instances.length > 0) {
232                         for (Object instance: instances) {
233                             INeutronNetworkAware service = (INeutronNetworkAware) instance;
234                             int status = service.canCreateNetwork(test);
235                             if (status < HTTP_OK_BOTTOM || status > HTTP_OK_TOP) {
236                                 return Response.status(status).build();
237                             }
238                         }
239                     } else {
240                         throw new ServiceUnavailableException(NO_PROVIDERS);
241                     }
242                 } else {
243                     throw new ServiceUnavailableException(NO_PROVIDER_LIST);
244                 }
245             }
246
247             // now that everything passed, add items to the cache
248             for (NeutronNetwork test : input.getBulk()) {
249                 test.initDefaults();
250                 networkInterface.addNetwork(test);
251                 if (instances != null) {
252                     for (Object instance: instances) {
253                         INeutronNetworkAware service = (INeutronNetworkAware) instance;
254                         service.neutronNetworkCreated(test);
255                     }
256                 }
257             }
258         }
259         return Response.status(HttpURLConnection.HTTP_CREATED).entity(input).build();
260     }
261
262     /**
263      * Updates a Network */
264     @Path("{netUUID}")
265     @PUT
266     @Produces({ MediaType.APPLICATION_JSON })
267     @Consumes({ MediaType.APPLICATION_JSON })
268     //@TypeHint(OpenStackNetworks.class)
269     @StatusCodes({
270         @ResponseCode(code = HttpURLConnection.HTTP_OK, condition = "Operation successful"),
271         @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
272     public Response updateNetwork(
273             @PathParam("netUUID") String netUUID, final NeutronNetworkRequest input
274             ) {
275         INeutronNetworkCRUD networkInterface = getNeutronInterfaces().getNetworkInterface();
276
277         NeutronNetwork updatedObject = input.getSingleton();
278         NeutronNetwork original = networkInterface.getNetwork(netUUID);
279
280         /*
281          *  note: what we get appears to not be a delta but
282          * rather an incomplete updated object.  So we need to set
283          * the ID to complete the object and then send that down
284          * for folks to check
285          */
286
287         updatedObject.setID(netUUID);
288         updatedObject.setTenantID(original.getTenantID());
289         Object[] instances = NeutronUtil.getInstances(INeutronNetworkAware.class, this);
290         if (instances != null) {
291             if (instances.length > 0) {
292                 for (Object instance : instances) {
293                     INeutronNetworkAware service = (INeutronNetworkAware) instance;
294                     int status = service.canUpdateNetwork(updatedObject, original);
295                     if (status < HTTP_OK_BOTTOM || status > HTTP_OK_TOP) {
296                         return Response.status(status).build();
297                     }
298                 }
299             } else {
300                 throw new ServiceUnavailableException(NO_PROVIDERS);
301             }
302         } else {
303             throw new ServiceUnavailableException(NO_PROVIDER_LIST);
304         }
305
306         // update network object
307         networkInterface.updateNetwork(netUUID, updatedObject);
308         if (instances != null) {
309             for (Object instance : instances) {
310                 INeutronNetworkAware service = (INeutronNetworkAware) instance;
311                 service.neutronNetworkUpdated(updatedObject);
312             }
313         }
314         return Response.status(HttpURLConnection.HTTP_OK).entity(
315                 new NeutronNetworkRequest(networkInterface.getNetwork(netUUID))).build();
316     }
317
318     /**
319      * Deletes a Network */
320
321     @Path("{netUUID}")
322     @DELETE
323     @StatusCodes({
324         @ResponseCode(code = HttpURLConnection.HTTP_NO_CONTENT, condition = "No Content"),
325         @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") })
326     public Response deleteNetwork(
327             @PathParam("netUUID") String netUUID) {
328         INeutronNetworkCRUD networkInterface = getNeutronInterfaces().getNetworkInterface();
329
330         NeutronNetwork singleton = networkInterface.getNetwork(netUUID);
331         Object[] instances = NeutronUtil.getInstances(INeutronNetworkAware.class, this);
332         if (instances != null) {
333             if (instances.length > 0) {
334                 for (Object instance : instances) {
335                     INeutronNetworkAware service = (INeutronNetworkAware) instance;
336                     int status = service.canDeleteNetwork(singleton);
337                     if (status < HTTP_OK_BOTTOM || status > HTTP_OK_TOP) {
338                         return Response.status(status).build();
339                     }
340                 }
341             } else {
342                 throw new ServiceUnavailableException(NO_PROVIDERS);
343             }
344         } else {
345             throw new ServiceUnavailableException(NO_PROVIDER_LIST);
346         }
347
348         if (!networkInterface.removeNetwork(netUUID)) {
349             throw new InternalServerErrorException("Could not delete network");
350         }
351         if (instances != null) {
352             for (Object instance : instances) {
353                 INeutronNetworkAware service = (INeutronNetworkAware) instance;
354                 service.neutronNetworkDeleted(singleton);
355             }
356         }
357         return Response.status(HttpURLConnection.HTTP_NO_CONTENT).build();
358     }
359 }