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