2 * Copyright IBM Corporation, 2013. All rights reserved.
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
9 package org.opendaylight.controller.networkconfig.neutron.northbound;
11 import java.util.ArrayList;
12 import java.util.HashMap;
13 import java.util.Iterator;
14 import java.util.List;
16 import javax.ws.rs.Consumes;
17 import javax.ws.rs.DELETE;
18 import javax.ws.rs.DefaultValue;
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.Context;
27 import javax.ws.rs.core.MediaType;
28 import javax.ws.rs.core.UriInfo;
29 import javax.ws.rs.core.Response;
31 import org.codehaus.enunciate.jaxrs.ResponseCode;
32 import org.codehaus.enunciate.jaxrs.StatusCodes;
33 import org.codehaus.enunciate.jaxrs.TypeHint;
35 import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkAware;
36 import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
37 import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
38 import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
39 import org.opendaylight.controller.northbound.commons.RestMessages;
40 import org.opendaylight.controller.northbound.commons.exception.BadRequestException;
41 import org.opendaylight.controller.northbound.commons.exception.ResourceConflictException;
42 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
43 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
44 import org.opendaylight.controller.sal.utils.ServiceHelper;
47 * Neutron Northbound REST APIs for Network.<br>
48 * This class provides REST APIs for managing neutron Networks
52 * Authentication scheme : <b>HTTP Basic</b><br>
53 * Authentication realm : <b>opendaylight</b><br>
54 * Transport : <b>HTTP and HTTPS</b><br>
56 * HTTPS Authentication is disabled by default. Administrator can enable it in
57 * tomcat-server.xml after adding a proper keystore / SSL certificate from a
58 * trusted authority.<br>
60 * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
65 public class NeutronNetworksNorthbound {
70 private NeutronNetwork extractFields(NeutronNetwork o, List<String> fields) {
71 return o.extractFields(fields);
75 * Returns a list of all Networks */
78 @Produces({ MediaType.APPLICATION_JSON })
79 //@TypeHint(OpenStackNetworks.class)
81 @ResponseCode(code = 200, condition = "Operation successful"),
82 @ResponseCode(code = 401, condition = "Unauthorized")})
83 public Response listNetworks(
85 @QueryParam("fields") List<String> fields,
86 // note: openstack isn't clear about filtering on lists, so we aren't handling them
87 @QueryParam("id") String queryID,
88 @QueryParam("name") String queryName,
89 @QueryParam("admin_state_up") String queryAdminStateUp,
90 @QueryParam("status") String queryStatus,
91 @QueryParam("shared") String queryShared,
92 @QueryParam("tenant_id") String queryTenantID,
93 @QueryParam("router_external") String queryRouterExternal,
94 @QueryParam("provider_network_type") String queryProviderNetworkType,
95 @QueryParam("provider_physical_network") String queryProviderPhysicalNetwork,
96 @QueryParam("provider_segmentation_id") String queryProviderSegmentationID,
98 @QueryParam("limit") Integer limit,
99 @QueryParam("marker") String marker,
100 @DefaultValue("false") @QueryParam("page_reverse") Boolean pageReverse
101 // sorting not supported
103 INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);
104 if (networkInterface == null) {
105 throw new ServiceUnavailableException("Network CRUD Interface "
106 + RestMessages.SERVICEUNAVAILABLE.toString());
108 List<NeutronNetwork> allNetworks = networkInterface.getAllNetworks();
109 List<NeutronNetwork> ans = new ArrayList<NeutronNetwork>();
110 Iterator<NeutronNetwork> i = allNetworks.iterator();
111 while (i.hasNext()) {
112 NeutronNetwork oSN = i.next();
113 //match filters: TODO provider extension
114 Boolean bAdminStateUp = null;
115 Boolean bShared = null;
116 Boolean bRouterExternal = null;
117 if (queryAdminStateUp != null) {
118 bAdminStateUp = Boolean.valueOf(queryAdminStateUp);
120 if (queryShared != null) {
121 bShared = Boolean.valueOf(queryShared);
123 if (queryRouterExternal != null) {
124 bRouterExternal = Boolean.valueOf(queryRouterExternal);
126 if ((queryID == null || queryID.equals(oSN.getID())) &&
127 (queryName == null || queryName.equals(oSN.getNetworkName())) &&
128 (bAdminStateUp == null || bAdminStateUp.booleanValue() == oSN.isAdminStateUp()) &&
129 (queryStatus == null || queryStatus.equals(oSN.getStatus())) &&
130 (bShared == null || bShared.booleanValue() == oSN.isShared()) &&
131 (bRouterExternal == null || bRouterExternal.booleanValue() == oSN.isRouterExternal()) &&
132 (queryTenantID == null || queryTenantID.equals(oSN.getTenantID()))) {
133 if (fields.size() > 0) {
134 ans.add(extractFields(oSN,fields));
141 if (limit != null && ans.size() > 1) {
142 // Return a paginated request
143 NeutronNetworkRequest request = (NeutronNetworkRequest) PaginatedRequestFactory.createRequest(limit,
144 marker, pageReverse, uriInfo, ans, NeutronNetwork.class);
145 return Response.status(200).entity(request).build();
148 return Response.status(200).entity(new NeutronNetworkRequest(ans)).build();
153 * Returns a specific Network */
157 @Produces({ MediaType.APPLICATION_JSON })
158 //@TypeHint(OpenStackNetworks.class)
160 @ResponseCode(code = 200, condition = "Operation successful"),
161 @ResponseCode(code = 401, condition = "Unauthorized"),
162 @ResponseCode(code = 404, condition = "Not Found") })
163 public Response showNetwork(
164 @PathParam("netUUID") String netUUID,
166 @QueryParam("fields") List<String> fields
168 INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
169 if (networkInterface == null) {
170 throw new ServiceUnavailableException("Network CRUD Interface "
171 + RestMessages.SERVICEUNAVAILABLE.toString());
173 if (!networkInterface.networkExists(netUUID)) {
174 throw new ResourceNotFoundException("network UUID does not exist.");
176 if (fields.size() > 0) {
177 NeutronNetwork ans = networkInterface.getNetwork(netUUID);
178 return Response.status(200).entity(
179 new NeutronNetworkRequest(extractFields(ans, fields))).build();
181 return Response.status(200).entity(
182 new NeutronNetworkRequest(networkInterface.getNetwork(netUUID))).build();
187 * Creates new Networks */
189 @Produces({ MediaType.APPLICATION_JSON })
190 @Consumes({ MediaType.APPLICATION_JSON })
191 @TypeHint(NeutronNetwork.class)
193 @ResponseCode(code = 201, condition = "Created"),
194 @ResponseCode(code = 400, condition = "Bad Request"),
195 @ResponseCode(code = 401, condition = "Unauthorized") })
196 public Response createNetworks(final NeutronNetworkRequest input) {
197 INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
198 if (networkInterface == null) {
199 throw new ServiceUnavailableException("Network CRUD Interface "
200 + RestMessages.SERVICEUNAVAILABLE.toString());
202 if (input.isSingleton()) {
203 NeutronNetwork singleton = input.getSingleton();
206 * network ID can't already exist
208 if (networkInterface.networkExists(singleton.getID())) {
209 throw new BadRequestException("network UUID already exists");
212 Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);
213 if (instances != null) {
214 for (Object instance : instances) {
215 INeutronNetworkAware service = (INeutronNetworkAware) instance;
216 int status = service.canCreateNetwork(singleton);
217 if (status < 200 || status > 299) {
218 return Response.status(status).build();
223 // add network to cache
224 singleton.initDefaults();
225 networkInterface.addNetwork(singleton);
226 if (instances != null) {
227 for (Object instance : instances) {
228 INeutronNetworkAware service = (INeutronNetworkAware) instance;
229 service.neutronNetworkCreated(singleton);
234 List<NeutronNetwork> bulk = input.getBulk();
235 Iterator<NeutronNetwork> i = bulk.iterator();
236 HashMap<String, NeutronNetwork> testMap = new HashMap<String, NeutronNetwork>();
237 Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);
238 while (i.hasNext()) {
239 NeutronNetwork test = i.next();
242 * network ID can't already exist, nor can there be an entry for this UUID
243 * already in this bulk request
245 if (networkInterface.networkExists(test.getID())) {
246 throw new BadRequestException("network UUID already exists");
248 if (testMap.containsKey(test.getID())) {
249 throw new BadRequestException("network UUID already exists");
251 if (instances != null) {
252 for (Object instance: instances) {
253 INeutronNetworkAware service = (INeutronNetworkAware) instance;
254 int status = service.canCreateNetwork(test);
255 if (status < 200 || status > 299) {
256 return Response.status(status).build();
260 testMap.put(test.getID(),test);
263 // now that everything passed, add items to the cache
265 while (i.hasNext()) {
266 NeutronNetwork test = i.next();
268 networkInterface.addNetwork(test);
269 if (instances != null) {
270 for (Object instance: instances) {
271 INeutronNetworkAware service = (INeutronNetworkAware) instance;
272 service.neutronNetworkCreated(test);
277 return Response.status(201).entity(input).build();
281 * Updates a Network */
284 @Produces({ MediaType.APPLICATION_JSON })
285 @Consumes({ MediaType.APPLICATION_JSON })
286 //@TypeHint(OpenStackNetworks.class)
288 @ResponseCode(code = 200, condition = "Operation successful"),
289 @ResponseCode(code = 400, condition = "Bad Request"),
290 @ResponseCode(code = 403, condition = "Forbidden"),
291 @ResponseCode(code = 404, condition = "Not Found"), })
292 public Response updateNetwork(
293 @PathParam("netUUID") String netUUID, final NeutronNetworkRequest input
295 INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
296 if (networkInterface == null) {
297 throw new ServiceUnavailableException("Network CRUD Interface "
298 + RestMessages.SERVICEUNAVAILABLE.toString());
302 * network has to exist and only a single delta is supported
304 if (!networkInterface.networkExists(netUUID)) {
305 throw new ResourceNotFoundException("network UUID does not exist.");
307 if (!input.isSingleton()) {
308 throw new BadRequestException("only singleton edits supported");
310 NeutronNetwork delta = input.getSingleton();
313 * transitions forbidden by Neutron
315 if (delta.getID() != null || delta.getTenantID() != null ||
316 delta.getStatus() != null) {
317 throw new BadRequestException("attribute edit blocked by Neutron");
320 Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);
321 if (instances != null) {
322 for (Object instance : instances) {
323 INeutronNetworkAware service = (INeutronNetworkAware) instance;
324 NeutronNetwork original = networkInterface.getNetwork(netUUID);
325 int status = service.canUpdateNetwork(delta, original);
326 if (status < 200 || status > 299) {
327 return Response.status(status).build();
332 // update network object and return the modified object
333 networkInterface.updateNetwork(netUUID, delta);
334 NeutronNetwork updatedSingleton = networkInterface.getNetwork(netUUID);
335 if (instances != null) {
336 for (Object instance : instances) {
337 INeutronNetworkAware service = (INeutronNetworkAware) instance;
338 service.neutronNetworkUpdated(updatedSingleton);
341 return Response.status(200).entity(
342 new NeutronNetworkRequest(networkInterface.getNetwork(netUUID))).build();
346 * Deletes a Network */
351 @ResponseCode(code = 204, condition = "No Content"),
352 @ResponseCode(code = 401, condition = "Unauthorized"),
353 @ResponseCode(code = 404, condition = "Not Found"),
354 @ResponseCode(code = 409, condition = "Network In Use") })
355 public Response deleteNetwork(
356 @PathParam("netUUID") String netUUID) {
357 INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
358 if (networkInterface == null) {
359 throw new ServiceUnavailableException("Network CRUD Interface "
360 + RestMessages.SERVICEUNAVAILABLE.toString());
364 * network has to exist and not be in use before it can be removed
366 if (!networkInterface.networkExists(netUUID)) {
367 throw new ResourceNotFoundException("network UUID does not exist.");
369 if (networkInterface.networkInUse(netUUID)) {
370 throw new ResourceConflictException("Network ID in use");
373 NeutronNetwork singleton = networkInterface.getNetwork(netUUID);
374 Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);
375 if (instances != null) {
376 for (Object instance : instances) {
377 INeutronNetworkAware service = (INeutronNetworkAware) instance;
378 int status = service.canDeleteNetwork(singleton);
379 if (status < 200 || status > 299) {
380 return Response.status(status).build();
384 networkInterface.removeNetwork(netUUID);
385 if (instances != null) {
386 for (Object instance : instances) {
387 INeutronNetworkAware service = (INeutronNetworkAware) instance;
388 service.neutronNetworkDeleted(singleton);
391 return Response.status(204).build();