Containerization feature of SO
[so.git] / adapters / mso-openstack-adapters / src / main / java / org / onap / so / adapters / network / NetworkAdapterRest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * Copyright (C) 2017 Huawei Technologies Co., Ltd. All rights reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  * 
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  * 
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.so.adapters.network;
23
24
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28
29 import javax.inject.Provider;
30 import javax.ws.rs.Consumes;
31 import javax.ws.rs.DELETE;
32 import javax.ws.rs.GET;
33 import javax.ws.rs.POST;
34 import javax.ws.rs.PUT;
35 import javax.ws.rs.Path;
36 import javax.ws.rs.PathParam;
37 import javax.ws.rs.Produces;
38 import javax.ws.rs.QueryParam;
39 import javax.ws.rs.core.GenericEntity;
40 import javax.ws.rs.core.MediaType;
41 import javax.ws.rs.core.Response;
42 import javax.xml.ws.Holder;
43
44 import org.apache.http.HttpStatus;
45 import org.onap.so.adapters.network.exceptions.NetworkException;
46 import org.onap.so.adapters.nwrest.ContrailNetwork;
47 import org.onap.so.adapters.nwrest.CreateNetworkError;
48 import org.onap.so.adapters.nwrest.CreateNetworkRequest;
49 import org.onap.so.adapters.nwrest.CreateNetworkResponse;
50 import org.onap.so.adapters.nwrest.DeleteNetworkError;
51 import org.onap.so.adapters.nwrest.DeleteNetworkRequest;
52 import org.onap.so.adapters.nwrest.DeleteNetworkResponse;
53 import org.onap.so.adapters.nwrest.ProviderVlanNetwork;
54 import org.onap.so.adapters.nwrest.QueryNetworkError;
55 import org.onap.so.adapters.nwrest.QueryNetworkResponse;
56 import org.onap.so.adapters.nwrest.RollbackNetworkError;
57 import org.onap.so.adapters.nwrest.RollbackNetworkRequest;
58 import org.onap.so.adapters.nwrest.RollbackNetworkResponse;
59 import org.onap.so.adapters.nwrest.UpdateNetworkError;
60 import org.onap.so.adapters.nwrest.UpdateNetworkRequest;
61 import org.onap.so.adapters.nwrest.UpdateNetworkResponse;
62 import org.onap.so.entity.MsoRequest;
63 import org.onap.so.logger.MessageEnum;
64 import org.onap.so.logger.MsoLogger;
65 import org.onap.so.openstack.beans.NetworkRollback;
66 import org.onap.so.openstack.beans.NetworkStatus;
67 import org.onap.so.openstack.beans.RouteTarget;
68 import org.onap.so.openstack.exceptions.MsoExceptionCategory;
69 import org.springframework.beans.factory.annotation.Autowired;
70 import org.springframework.beans.factory.annotation.Qualifier;
71 import org.springframework.stereotype.Component;
72 import org.springframework.transaction.annotation.Transactional;
73
74 import io.swagger.annotations.Api;
75 import io.swagger.annotations.ApiOperation;
76 import io.swagger.annotations.ApiParam;
77 import io.swagger.annotations.ApiResponse;
78 import io.swagger.annotations.ApiResponses;
79
80 @Path("/v1/networks")
81 @Api(value = "/v1/networks", description = "root of network adapters restful web service")
82 @Component
83 @Transactional
84 public class NetworkAdapterRest {
85         private static final MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA,NetworkAdapterRest.class);
86         private static final String TESTING_KEYWORD = "___TESTING___";
87
88    
89
90         @Autowired
91         private MsoNetworkAdapterImpl adapter;
92         @Autowired
93         @Qualifier("NetworkBpel")
94         private Provider<BpelRestClient> bpelRestClientProvider;
95         
96
97         @POST
98         @Path("")
99         @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
100         @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
101         @ApiOperation(value = "CreateNetwork", 
102                                         response = Response.class,
103                                         notes = "Creates a new network, CreateNetworkRquest JSON is required")
104         @ApiResponses({
105                 @ApiResponse(code = 200, message = "network has been successfully created"),
106                 @ApiResponse(code = 202, message = "create network request has been accepted (async only)"),
107                 @ApiResponse(code = 500, message = "create network failed, examine entity object for details") })
108         public Response createNetwork(
109                                 @ApiParam(value = "details of network being created", required = true) 
110                                 CreateNetworkRequest req) {
111                 LOGGER.debug("createNetwork enter: " + req.toJsonString());
112                 CreateNetworkTask task = new CreateNetworkTask(req);
113                 if (req.isSynchronous()) {
114                         // This is a synchronous request
115                         task.run();
116                         return Response
117                                 .status(task.getStatusCode())
118                                 .entity(task.getGenericEntityResponse())
119                                 .build();
120                 } else {
121                         // This is an asynchronous request
122                         try {
123                                 Thread t1 = new Thread(task);
124                                 t1.start();
125                         } catch (Exception e) {
126                                 // problem handling create, send generic failure as sync resp to caller
127                                 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, "", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception while create network", e);
128                                 return Response.serverError().build();
129                         }
130                         // send sync response (ACK) to caller
131                         LOGGER.debug ("createNetwork exit");
132                         return Response.status(HttpStatus.SC_ACCEPTED).build();
133                 }
134         }
135
136         public class CreateNetworkTask implements Runnable {
137                 private final CreateNetworkRequest req;
138                 private CreateNetworkResponse response = null;
139                 private CreateNetworkError eresp = null;
140                 private boolean sendxml;
141
142                 public CreateNetworkTask(CreateNetworkRequest req) {
143                         this.req = req;
144                         this.sendxml = true; // can be set with a field or header later
145                 }
146                 public int getStatusCode() {
147                         return (response != null) ? HttpStatus.SC_OK : HttpStatus.SC_BAD_REQUEST;
148                 }
149                 public Object getGenericEntityResponse() {
150                         return (response != null)
151                                 ? new GenericEntity<CreateNetworkResponse>(response) {}
152                                 : new GenericEntity<CreateNetworkError>(eresp) {};
153                 }
154                 private String getResponse() {
155                         if (response != null) {
156                                 return sendxml ? response.toXmlString() : response.toJsonString();
157                         } else {
158                                 return sendxml ? eresp.toXmlString() : eresp.toJsonString();
159                         }
160                 }
161                 @Override
162                 public void run() {
163                         LOGGER.debug ("CreateNetworkTask start");
164                         try {
165                                 // Synchronous Web Service Outputs
166                                 Holder<String> networkId = new Holder<>();
167                                 Holder<String> neutronNetworkId = new Holder<>();
168                                 Holder<String> networkFqdn = new Holder<>();
169                                 Holder<Map<String, String>> subnetIdMap = new Holder<>();
170                                 Holder<NetworkRollback> rollback = new Holder<>();
171
172                                 String cloudsite = req.getCloudSiteId();
173                                 if (cloudsite != null && cloudsite.equals(TESTING_KEYWORD)) {
174                                         String tenant = req.getTenantId();
175                                         if (tenant != null && tenant.equals(TESTING_KEYWORD)) {
176                                                 throw new NetworkException("testing.");
177                                         }
178                                         networkId.value = "479D3D8B-6360-47BC-AB75-21CC91981484";
179                                         neutronNetworkId.value = "55e55884-28fa-11e6-8971-0017f20fe1b8";
180                                         networkFqdn.value = "086f70b6-28fb-11e6-8260-0017f20fe1b8";
181                                         subnetIdMap.value = testMap();
182                                         rollback.value = new NetworkRollback();
183                                 } else if (req.isContrailRequest()) {
184                                         ContrailNetwork ctn = req.getContrailNetwork();
185                                         if (ctn == null) {
186                                                 ctn = new ContrailNetwork();
187                                                 req.setContrailNetwork(ctn);
188                                         }
189                                         adapter.createNetworkContrail(
190                                                 req.getCloudSiteId(),
191                                                 req.getTenantId(),
192                                                 req.getNetworkType(),
193                                                 req.getModelCustomizationUuid(),
194                                                 req.getNetworkName(),
195                         req.getContrailNetwork().getRouteTargets(),
196                         req.getContrailNetwork().getShared(),
197                         req.getContrailNetwork().getExternal(),
198                         req.getFailIfExists(),
199                         req.getBackout(),
200                         req.getSubnets(),
201                         req.getContrailNetwork().getPolicyFqdns(),
202                         req.getContrailNetwork().getRouteTableFqdns(),
203                                 req.getMsoRequest(),
204                                         networkId,
205                                                 neutronNetworkId,
206                                                 networkFqdn,
207                                                 subnetIdMap,
208                                                 rollback);
209                                 } else {
210                                         ProviderVlanNetwork pvn = req.getProviderVlanNetwork();
211                                         if (pvn == null) {
212                                                 pvn = new ProviderVlanNetwork();
213                                                 req.setProviderVlanNetwork(pvn);
214                                         }
215                                         adapter.createNetwork(
216                                                 req.getCloudSiteId(),
217                                                 req.getTenantId(),
218                                                 req.getNetworkType(),
219                                                 req.getModelCustomizationUuid(),
220                                                 req.getNetworkName(),
221                                                 req.getProviderVlanNetwork().getPhysicalNetworkName(),
222                                                 req.getProviderVlanNetwork().getVlans(),
223                         req.getFailIfExists(),
224                         req.getBackout(),
225                         req.getSubnets(),
226                         req.getMsoRequest(),
227                                         networkId,
228                                         neutronNetworkId,
229                                         subnetIdMap,
230                                         rollback);
231                                 }
232                                 response = new CreateNetworkResponse(
233                                                 req.getNetworkId(),
234                                                 neutronNetworkId.value,
235                                                 rollback.value.getNetworkStackId(),
236                                                 networkFqdn.value,
237                                                 rollback.value.getNetworkCreated(),
238                                                 subnetIdMap.value,
239                                                 rollback.value,
240                                                 req.getMessageId());
241                         } catch (NetworkException e) {
242                             LOGGER.debug ("Exception:", e);
243                                 eresp = new CreateNetworkError(
244                                         e.getMessage(), MsoExceptionCategory.INTERNAL, true, req.getMessageId());
245                         }
246                         if (!req.isSynchronous()) {
247                                 // This is asynch, so POST response back to caller
248                                 BpelRestClient bpelClient = bpelRestClientProvider.get();
249                                 bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
250                         }
251                         LOGGER.debug ("CreateNetworkTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
252                 }
253         }
254
255         @DELETE
256         @Path("{aaiNetworkId}")
257         @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
258         @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
259         @ApiOperation(value = "DeleteNetwork", 
260                                         response = Response.class,
261                                         notes = "Deletes an existing network, aaiNetworkId and DeleteNetworkRequest JSON are required")
262         @ApiResponses({
263                                 @ApiResponse(code = 200, message = "network has been successfully deleted"),
264                                 @ApiResponse(code = 202, message = "request to delete network has been accepted (async only)"),
265                                 @ApiResponse(code = 500, message = "delete network failed, examine entity object for details") })       
266         public Response deleteNetwork(
267                 @ApiParam(value = "aaiNetworkId to be deleted ", required = true) 
268                 @PathParam("aaiNetworkId") String aaiNetworkId,
269                 @ApiParam(value = "details of network being deleted", required = true) 
270                 DeleteNetworkRequest req)
271         {
272                 LOGGER.debug("deleteNetwork enter: " + req.toJsonString());
273                 if (aaiNetworkId == null || !aaiNetworkId.equals(req.getNetworkId())) {
274                         return Response
275                                 .status(HttpStatus.SC_BAD_REQUEST)
276                                 .type(MediaType.TEXT_PLAIN)
277                                 .entity("A&AI NetworkId in URL ("+aaiNetworkId+") does not match content ("+req.getNetworkId()+")")
278                                 .build();
279                 }
280                 DeleteNetworkTask task = new DeleteNetworkTask(req);
281                 if (req.isSynchronous()) {
282                         // This is a synchronous request
283                         task.run();
284                         return Response
285                                 .status(task.getStatusCode())
286                                 .entity(task.getGenericEntityResponse())
287                                 .build();
288                 } else {
289                         // This is an asynchronous request
290                         try {
291                                 Thread t1 = new Thread(task);
292                                 t1.start();
293                         } catch (Exception e) {
294                                 // problem handling create, send generic failure as sync resp to caller
295                                 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, "", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception while delete network", e);
296                                 return Response.serverError().build();
297                         }
298                         // send sync response (ACK) to caller
299                         LOGGER.debug ("deleteNetwork exit");
300                         return Response.status(HttpStatus.SC_ACCEPTED).build();
301                 }
302         }
303
304         public class DeleteNetworkTask implements Runnable {
305                 private final DeleteNetworkRequest req;
306                 private DeleteNetworkResponse response = null;
307                 private DeleteNetworkError eresp = null;
308                 private boolean sendxml;
309
310                 public DeleteNetworkTask(DeleteNetworkRequest req) {
311                         this.req = req;
312                         this.sendxml = true; // can be set with a field or header later
313                 }
314                 public int getStatusCode() {
315                         return (response != null) ? HttpStatus.SC_OK : HttpStatus.SC_BAD_REQUEST;
316                 }
317                 public Object getGenericEntityResponse() {
318                         return (response != null)
319                                 ? new GenericEntity<DeleteNetworkResponse>(response) {}
320                                 : new GenericEntity<DeleteNetworkError>(eresp) {};
321                 }
322                 private String getResponse() {
323                         if (response != null) {
324                                 return sendxml ? response.toXmlString() : response.toJsonString();
325                         } else {
326                                 return sendxml ? eresp.toXmlString() : eresp.toJsonString();
327                         }
328                 }
329                 @Override
330                 public void run() {
331                         LOGGER.debug("DeleteNetworkTask start");
332                         try {
333                                 Holder<Boolean> networkDeleted = new Holder<>();
334                                 if (req.getCloudSiteId().equals(TESTING_KEYWORD)) {
335                                         networkDeleted.value = true;
336                                 } else {
337                                         adapter.deleteNetwork(
338                                                 req.getCloudSiteId(),
339                                                 req.getTenantId(),
340                                                 req.getNetworkType(),
341                                                 req.getModelCustomizationUuid(),
342                                                 req.getNetworkStackId(),
343                                                 req.getMsoRequest(),
344                                                 networkDeleted);
345                                 }
346                                 response = new DeleteNetworkResponse(req.getNetworkId(), networkDeleted.value, req.getMessageId());
347                         } catch (NetworkException e) {
348                             LOGGER.debug ("Exception:", e);
349                                 eresp = new DeleteNetworkError(e.getMessage(), MsoExceptionCategory.INTERNAL, true, req.getMessageId());
350                         }
351                         if (!req.isSynchronous()) {
352                                 // This is asynch, so POST response back to caller
353                                 BpelRestClient bpelClient = bpelRestClientProvider.get();
354                                 bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
355                         }
356                         LOGGER.debug("DeleteNetworkTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
357                 }
358         }
359
360         @GET
361         @Path("{aaiNetworkId}")
362         @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
363         @ApiOperation(value = "QueryNetwork", 
364                         response = Response.class,
365                         notes = "Queries an existing network")
366         @ApiResponses({
367                         @ApiResponse(code = 200, message = "Query network successful"),
368                         @ApiResponse(code = 500, message = "Query network failed, examine entity object for details") })                
369         public Response queryNetwork(
370                 @ApiParam(value = "cloudSiteId", required = false)
371                 @QueryParam("cloudSiteId") String cloudSiteId,
372                 @ApiParam(value = "tenantId", required = false)
373                 @QueryParam("tenantId") String tenantId,
374                 @ApiParam(value = "networkStackId", required = false)
375                 @QueryParam("networkStackId") String networkStackId,
376                 @ApiParam(value = "skipAAI", required = false)
377                 @QueryParam("skipAAI") String skipAAI,
378                 @ApiParam(value = "msoRequest.requestId", required = false)
379                 @QueryParam("msoRequest.requestId") String requestId,
380                 @ApiParam(value = "msoRequest.serviceInstanceId", required = false)
381                 @QueryParam("msoRequest.serviceInstanceId") String serviceInstanceId,
382                 @ApiParam(value = "aaiNetworkId", required = false)
383                 @PathParam("aaiNetworkId") String aaiNetworkId)
384         {
385                 //This request responds synchronously only
386                 LOGGER.debug ("Query network enter:" + aaiNetworkId);
387                 MsoRequest msoRequest = new MsoRequest(requestId, serviceInstanceId);
388
389                 try {
390                         int respStatus = HttpStatus.SC_OK;
391                         QueryNetworkResponse resp = new QueryNetworkResponse(networkStackId, null, networkStackId, null, null);
392                         Holder<Boolean> networkExists = new Holder<>();
393             Holder<String> networkId = new Holder<>();
394             Holder<String> neutronNetworkId = new Holder<>();
395             Holder<NetworkStatus> status = new Holder<>();
396             Holder<List<RouteTarget>> routeTargets = new Holder<>();
397             Holder<Map<String, String>> subnetIdMap = new Holder<>();
398
399                         adapter.queryNetworkContrail(cloudSiteId,  tenantId, aaiNetworkId,  msoRequest,
400                                 networkExists, networkId, neutronNetworkId, status, routeTargets, subnetIdMap);
401
402                         if (!networkExists.value) {
403                                 LOGGER.debug ("network not found");
404                                 respStatus = HttpStatus.SC_NOT_FOUND;
405                         } else {
406                                 LOGGER.debug ("network found" + networkId.value + ", status=" + status.value);
407                                 resp.setNetworkExists(networkExists.value);
408                                 resp.setNetworkId(networkId.value);
409                                 resp.setNeutronNetworkId(neutronNetworkId.value);
410                                 resp.setNetworkStatus(status.value);
411                                 resp.setRouteTargets(routeTargets.value);
412                                 resp.setSubnetIdMap(subnetIdMap.value);
413                         }
414                         LOGGER.debug ("Query network exit");
415                         return Response
416                                 .status(respStatus)
417                                 .entity(new GenericEntity<QueryNetworkResponse>(resp) {})
418                                 .build();
419                 } catch (NetworkException e) {
420                         LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, aaiNetworkId, "", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception when query VNF", e);
421                         QueryNetworkError err = new QueryNetworkError();
422                         err.setMessage(e.getMessage());
423                         err.setCategory(MsoExceptionCategory.INTERNAL);
424                         return Response
425                                 .status(HttpStatus.SC_INTERNAL_SERVER_ERROR)
426                                 .entity(new GenericEntity<QueryNetworkError>(err) {})
427                                 .build();
428                 }
429         }
430
431         @DELETE
432         @Path("{aaiNetworkId}/rollback")
433         @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
434         @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
435         @ApiOperation(value = "RollbackNetwork", 
436                 response = Response.class,
437                 notes = "Rollback an existing network")
438         @ApiResponses({
439                         @ApiResponse(code = 200, message = "Rollback network successful"),
440                         @ApiResponse(code = 202, message = "Rollback network request has been accepted (async only)"),
441                         @ApiResponse(code = 500, message = "Rollback network failed, examine entity object for details") })
442         public Response rollbackNetwork(
443                 @ApiParam(value = "RollbackNetworkRequest in JSON format", required = true)
444                 RollbackNetworkRequest req)
445         {
446                 LOGGER.debug("rollbackNetwork enter: " + req.toJsonString());
447                 RollbackNetworkTask task = new RollbackNetworkTask(req);
448                 if (req.isSynchronous()) {
449                         // This is a synchronous request
450                         task.run();
451                         return Response
452                                 .status(task.getStatusCode())
453                                 .entity(task.getGenericEntityResponse())
454                                 .build();
455                 } else {
456                         // This is an asynchronous request
457                         try {
458                                 Thread t1 = new Thread(task);
459                                 t1.start();
460                         } catch (Exception e) {
461                                 // problem handling create, send generic failure as sync resp to caller
462                                 LOGGER.error (MessageEnum.RA_ROLLBACK_NULL, "", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception in rollbackNetwork", e);
463                                 return Response.serverError().build();
464                         }
465                         // send sync response (ACK) to caller
466                         LOGGER.debug("rollbackNetwork exit");
467                         return Response.status(HttpStatus.SC_ACCEPTED).build();
468                 }
469         }
470
471         public class RollbackNetworkTask implements Runnable {
472                 private final RollbackNetworkRequest req;
473                 private RollbackNetworkResponse response = null;
474                 private RollbackNetworkError eresp = null;
475                 private boolean sendxml;
476
477                 public RollbackNetworkTask(RollbackNetworkRequest req) {
478                         this.req = req;
479                         this.sendxml = true; // can be set with a field or header later
480                 }
481                 public int getStatusCode() {
482                         return (response != null) ? HttpStatus.SC_OK : HttpStatus.SC_BAD_REQUEST;
483                 }
484                 public Object getGenericEntityResponse() {
485                         return (response != null)
486                                 ? new GenericEntity<RollbackNetworkResponse>(response) {}
487                                 : new GenericEntity<RollbackNetworkError>(eresp) {};
488                 }
489                 private String getResponse() {
490                         if (response != null) {
491                                 return sendxml ? response.toXmlString() : response.toJsonString();
492                         } else {
493                                 return sendxml ? eresp.toXmlString() : eresp.toJsonString();
494                         }
495                 }
496                 @Override
497                 public void run() {
498                         LOGGER.debug("RollbackNetworkTask start");
499                         try {
500                                 NetworkRollback nwr = req.getNetworkRollback();
501                                 adapter.rollbackNetwork(nwr);
502                                 response = new RollbackNetworkResponse(true, req.getMessageId());
503                         } catch (NetworkException e) {
504                             LOGGER.debug ("Exception:", e);
505                                 eresp = new RollbackNetworkError(e.getMessage(), MsoExceptionCategory.INTERNAL, true, req.getMessageId());
506                         }
507                         if (!req.isSynchronous()) {
508                                 // This is asynch, so POST response back to caller
509                                 BpelRestClient bpelClient = bpelRestClientProvider.get();
510                                 bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
511                         }
512                         LOGGER.debug("RollbackNetworkTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
513                 }
514         }
515
516         @PUT
517         @Path("{aaiNetworkId}")
518         @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
519         @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
520         @ApiOperation(value = "UpdateNetwork", 
521                 response = Response.class,
522                 notes = "Update an existing network")
523         @ApiResponses({
524                 @ApiResponse(code = 200, message = "Update network successful"),
525                 @ApiResponse(code = 202, message = "Update network request has been accepted (async only)"),
526                 @ApiResponse(code = 500, message = "Update network failed, examine entity object for details") })       
527         public Response updateNetwork(
528                 @ApiParam(value = "aaiNetworkId", required = true)
529                 @PathParam("aaiNetworkId") String aaiNetworkId,
530                 @ApiParam(value = "UpdateNetworkRequest in JSON format", required = true)
531                 UpdateNetworkRequest req)
532         {
533                 LOGGER.debug("updateNetwork enter: " + req.toJsonString());
534                 if (aaiNetworkId == null || !aaiNetworkId.equals(req.getNetworkId())) {
535                         return Response
536                                 .status(HttpStatus.SC_BAD_REQUEST)
537                                 .type(MediaType.TEXT_PLAIN)
538                                 .entity("A&AI NetworkId in URL ("+aaiNetworkId+") does not match content ("+req.getNetworkId()+")")
539                                 .build();
540                 }
541                 UpdateNetworkTask task = new UpdateNetworkTask(req);
542                 if (req.isSynchronous()) {
543                         // This is a synchronous request
544                         task.run();
545                         return Response
546                                 .status(task.getStatusCode())
547                                 .entity(task.getGenericEntityResponse())
548                                 .build();
549                 } else {
550                         // This is an asynchronous request
551                 try {
552                         Thread t1 = new Thread(task);
553                         t1.start();
554                 } catch (Exception e) {
555                         // problem handling create, send generic failure as sync resp to caller
556                         LOGGER.error (MessageEnum.RA_UPDATE_NETWORK_ERR, "", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception in updateNetwork", e);
557                         return Response.serverError().build();
558                 }
559                 // send sync response (ACK) to caller
560                 LOGGER.debug ("updateNetwork exit");
561                 return Response.status(HttpStatus.SC_ACCEPTED).build();
562                 }
563         }
564
565         public class UpdateNetworkTask implements Runnable {
566                 private final UpdateNetworkRequest req;
567                 private UpdateNetworkResponse response = null;
568                 private UpdateNetworkError eresp = null;
569                 private boolean sendxml;
570
571                 public UpdateNetworkTask(UpdateNetworkRequest req) {
572                         this.req = req;
573                         this.sendxml = true; // can be set with a field or header later
574                 }
575                 public int getStatusCode() {
576                         return (response != null) ? HttpStatus.SC_OK : HttpStatus.SC_BAD_REQUEST;
577                 }
578                 public Object getGenericEntityResponse() {
579                         return (response != null)
580                                 ? new GenericEntity<UpdateNetworkResponse>(response) {}
581                                 : new GenericEntity<UpdateNetworkError>(eresp) {};
582                 }
583                 private String getResponse() {
584                         if (response != null) {
585                                 return sendxml ? response.toXmlString() : response.toJsonString();
586                         } else {
587                                 return sendxml ? eresp.toXmlString() : eresp.toJsonString();
588                         }
589                 }
590                 @Override
591                 public void run() {
592                         LOGGER.debug("UpdateNetworkTask start");
593                         try {
594                                 Holder<Map<String, String>> subnetIdMap = new Holder<>();
595                                 Holder<NetworkRollback> rollback = new Holder<> ();
596
597                                 if (req.getCloudSiteId().equals(TESTING_KEYWORD)) {
598                                         subnetIdMap.value = testMap();
599                                 NetworkRollback rb = new NetworkRollback ();
600                                 rb.setCloudId(req.getCloudSiteId());
601                                 rb.setTenantId(req.getTenantId());
602                                 rb.setMsoRequest(req.getMsoRequest());
603                                 rollback.value = rb;
604                                 } else if (req.isContrailRequest()) {
605                                         ContrailNetwork ctn = req.getContrailNetwork();
606                                         if (ctn == null) {
607                                                 ctn = new ContrailNetwork();
608                                                 req.setContrailNetwork(ctn);
609                                         }
610                                         adapter.updateNetworkContrail(
611                                                 req.getCloudSiteId(),
612                                                 req.getTenantId(),
613                                                 req.getNetworkType(),
614                                                 req.getModelCustomizationUuid(),
615                                                 req.getNetworkStackId(),
616                                                 req.getNetworkName(),
617                                                 req.getContrailNetwork().getRouteTargets(),
618                             req.getContrailNetwork().getShared(),
619                             req.getContrailNetwork().getExternal(),
620                             req.getSubnets(),
621                             req.getContrailNetwork().getPolicyFqdns(),
622                             req.getContrailNetwork().getRouteTableFqdns(),
623                             req.getMsoRequest(),
624                             subnetIdMap,
625                             rollback);
626                                 } else {
627                                         ProviderVlanNetwork pvn = req.getProviderVlanNetwork();
628                                         if (pvn == null) {
629                                                 pvn = new ProviderVlanNetwork();
630                                                 req.setProviderVlanNetwork(pvn);
631                                         }
632                                         adapter.updateNetwork(
633                                                 req.getCloudSiteId(),
634                                                 req.getTenantId(),
635                                                 req.getNetworkType(),
636                                                 req.getModelCustomizationUuid(),
637                                                 req.getNetworkStackId(),
638                                                 req.getNetworkName(),
639                                                 req.getProviderVlanNetwork().getPhysicalNetworkName(),
640                                                 req.getProviderVlanNetwork().getVlans(),
641                                                 req.getSubnets(),
642                                                 req.getMsoRequest(),
643                                                 subnetIdMap,
644                                                 rollback);
645                                 }
646                                 response = new UpdateNetworkResponse(
647                                         req.getNetworkId(),
648                                         null,   // NeutronNetworkId is not available from an update
649                                         subnetIdMap.value,
650                                         req.getMessageId());
651                         } catch (NetworkException e) {
652                             LOGGER.debug ("Exception:", e);
653                                 eresp = new UpdateNetworkError(e.getMessage(), MsoExceptionCategory.INTERNAL, true, req.getMessageId());
654                         }
655                         if (!req.isSynchronous()) {
656                                 // This is asynch, so POST response back to caller
657                                 BpelRestClient bpelClient = bpelRestClientProvider.get();
658                                 bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
659                         }
660                         LOGGER.debug("UpdateNetworkTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
661                 }
662         }
663
664         public static Map<String, String> testMap() {
665                 Map<String, String> m = new HashMap<>();
666                 m.put("mickey", "7");
667                 m.put("clyde", "10");
668                 m.put("wayne", "99");
669                 return m;
670     }
671 }