Merge changes Ib795f077,I723e4262
authorGuillaume Lambert <guillaume.lambert@orange.com>
Thu, 29 Feb 2024 13:24:43 +0000 (13:24 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Thu, 29 Feb 2024 13:24:43 +0000 (13:24 +0000)
* changes:
  Refactoring rollback when service create fails
  New Package dealing with device rollback

1  2 
renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/DeviceRendererServiceImpl.java
renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/RendererServiceOperationsImpl.java

index 836282c44a8ae4fab4c9c9827c007c728b7b11e2,7c204f255903f961d56d100e31c743225e37454f..a38b848b414f1888ada468153a571145659cb762
@@@ -49,6 -49,15 +49,15 @@@ import org.opendaylight.transportpce.co
  import org.opendaylight.transportpce.renderer.openroadminterface.OpenRoadmInterfaceFactory;
  import org.opendaylight.transportpce.renderer.provisiondevice.servicepath.ServiceListTopology;
  import org.opendaylight.transportpce.renderer.provisiondevice.servicepath.ServicePathDirection;
+ import org.opendaylight.transportpce.renderer.provisiondevice.transaction.Connection;
+ import org.opendaylight.transportpce.renderer.provisiondevice.transaction.DeviceInterface;
+ import org.opendaylight.transportpce.renderer.provisiondevice.transaction.delete.DeleteService;
+ import org.opendaylight.transportpce.renderer.provisiondevice.transaction.delete.DeleteSubscriber;
+ import org.opendaylight.transportpce.renderer.provisiondevice.transaction.delete.FailedRollbackResult;
+ import org.opendaylight.transportpce.renderer.provisiondevice.transaction.delete.Result;
+ import org.opendaylight.transportpce.renderer.provisiondevice.transaction.delete.Subscriber;
+ import org.opendaylight.transportpce.renderer.provisiondevice.transaction.history.History;
+ import org.opendaylight.transportpce.renderer.provisiondevice.transaction.history.NonStickHistoryMemory;
  import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.alarmsuppression.rev171102.ServiceNodelist;
  import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.alarmsuppression.rev171102.service.nodelist.NodelistBuilder;
  import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.alarmsuppression.rev171102.service.nodelist.NodelistKey;
@@@ -66,8 -75,8 +75,8 @@@ import org.opendaylight.yang.gen.v1.htt
  import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.renderer.rollback.output.FailedToRollback;
  import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.renderer.rollback.output.FailedToRollbackBuilder;
  import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.renderer.rollback.output.FailedToRollbackKey;
 -import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220922.OpenroadmNodeVersion;
 -import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220922.mapping.Mapping;
 +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev231221.OpenroadmNodeVersion;
 +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev231221.mapping.Mapping;
  import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.Topology;
  import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.ServiceList;
  import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.service.list.Services;
@@@ -113,12 -122,21 +122,21 @@@ public class DeviceRendererServiceImpl 
          this.openRoadmInterfaceFactory = new OpenRoadmInterfaceFactory(mappingUtils, portMapping, openRoadmInterfaces);
      }
  
+     @Override
+     public ServicePathOutput setupServicePath(ServicePathInput input, ServicePathDirection direction) {
+         return setupServicePath(input, direction, new NonStickHistoryMemory());
+     }
      @SuppressWarnings("rawtypes")
      // FIXME check if the ForkJoinTask raw type can be avoided
      // Raw types use are discouraged since they lack type safety.
      // Resulting Problems are observed at run time and not at compile time
      @Override
-     public ServicePathOutput setupServicePath(ServicePathInput input, ServicePathDirection direction) {
+     public ServicePathOutput setupServicePath(
+             ServicePathInput input,
+             ServicePathDirection direction,
+             History transactionHistory
+     ) {
          LOG.info("setup service path for input {} and direction {}", input, direction);
          List<Nodes> nodes = new ArrayList<>();
          if (input.getNodes() != null) {
                          crossConnectFlag++;
                          String supportingOchInterface = this.openRoadmInterfaceFactory.createOpenRoadmOchInterface(
                                  nodeId, destTp, spectrumInformation);
+                         transactionHistory.add(new DeviceInterface(nodeId, supportingOchInterface));
                          // Split the string based on # pass the last element as the supported Interface
                          // This is needed for 7.1 device models with B100G, we have OTSI, OTSI-group combined as OCH
                          String[] listOfSuppOchInf = supportingOchInterface.split("#");
                          List<String> createdOchInf = Arrays.asList(listOfSuppOchInf);
+                         transactionHistory.addInterfaces(nodeId, listOfSuppOchInf);
                          createdOchInterfaces.addAll(createdOchInf);
                          LOG.info("DEST all otsi interfaces {}", createdOchInterfaces);
                          // Taking the last element
                                  .createOpenRoadmOtu4Interface(nodeId, destTp, supportingOchInterface, apiInfoA,
                                          apiInfoZ);
                          createdOtuInterfaces.add(supportingOtuInterface);
+                         transactionHistory.add(new DeviceInterface(nodeId, supportingOtuInterface));
                          LOG.info("all dest otu interfaces {}", createdOtuInterfaces);
                          if (srcTp == null) {
                              otnLinkTps.add(new LinkTpBuilder().setNodeId(nodeId).setTpId(destTp).build());
                              // If src and dest tp contains the network token, then it is regenerator
                              LOG.info("Create the ODUCn for regen on the dest-tp");
                              // Here we first create ODUCn interface for the Regen
-                             createdOduInterfaces.add(this.openRoadmInterfaceFactory
-                                     .createOpenRoadmOducn(nodeId, destTp));
+                             String openRoadmOducn = this.openRoadmInterfaceFactory
+                                     .createOpenRoadmOducn(nodeId, destTp);
+                             createdOduInterfaces.add(openRoadmOducn);
+                             transactionHistory.addInterfaces(nodeId, openRoadmOducn);
                              LOG.info("all dest odu interfaces {}", createdOduInterfaces);
                          } else {
                              // This is needed for 7.1 device models for 400GE, since we have ODUC4 and ODUflex
                              // are combined
-                             createdOduInterfaces = Set.of(this.openRoadmInterfaceFactory
-                                 .createOpenRoadmOdu4HOInterface(
-                                     nodeId, destTp, false, apiInfoA, apiInfoZ, PT_07).split("#"));
+                             String[] oduInterfaces = this.openRoadmInterfaceFactory
+                                     .createOpenRoadmOdu4HOInterface(
+                                             nodeId, destTp, false, apiInfoA, apiInfoZ, PT_07).split("#");
+                             createdOduInterfaces.addAll(Arrays.asList(oduInterfaces));
+                             transactionHistory.addInterfaces(nodeId, oduInterfaces);
                          }
                      }
                      if ((srcTp != null) && srcTp.contains(StringConstants.CLIENT_TOKEN)) {
                          LOG.info("Adding supporting EThernet interface for node {}, src tp {}", nodeId, srcTp);
                          crossConnectFlag++;
                          // create OpenRoadm Xponder Client Interfaces
-                         createdEthInterfaces.add(this.openRoadmInterfaceFactory.createOpenRoadmEthInterface(
-                                 nodeId, srcTp));
+                         String openRoadmEthInterface = this.openRoadmInterfaceFactory.createOpenRoadmEthInterface(
+                                 nodeId, srcTp);
+                         createdEthInterfaces.add(openRoadmEthInterface);
+                         transactionHistory.add(new DeviceInterface(nodeId, openRoadmEthInterface));
                      }
                      if ((srcTp != null) && srcTp.contains(StringConstants.NETWORK_TOKEN)) {
                          LOG.info("Adding supporting OCH interface for node {}, src tp {}, spectrumInformation {}",
                          // create OpenRoadm Xponder Line Interfaces
                          String supportingOchInterface = this.openRoadmInterfaceFactory.createOpenRoadmOchInterface(
                                  nodeId, srcTp, spectrumInformation);
+                         transactionHistory.add(new DeviceInterface(nodeId, supportingOchInterface));
                          // createdOchInterfaces.add(supportingOchInterface);
                          // Split the string based on # pass the last element as the supported Interface
                          // This is needed for 7.1 device models with B100G, we have OTSI, OTSI-group combined as OCH
                          String[] listOfSuppOchInf = supportingOchInterface.split("#");
+                         transactionHistory.addInterfaces(nodeId, listOfSuppOchInf);
                          List<String> tmpCreatedOchInterfaces = Arrays.asList(listOfSuppOchInf);
                          createdOchInterfaces.addAll(tmpCreatedOchInterfaces);
                          // Taking the last element
                          String supportingOtuInterface = this.openRoadmInterfaceFactory.createOpenRoadmOtu4Interface(
                                  nodeId, srcTp, supportingOchInterface, apiInfoA, apiInfoZ);
                          createdOtuInterfaces.add(supportingOtuInterface);
+                         transactionHistory.add(new DeviceInterface(nodeId, supportingOtuInterface));
                          if (destTp == null) {
                              otnLinkTps.add(new LinkTpBuilder().setNodeId(nodeId).setTpId(srcTp).build());
                          } else if (destTp.contains(StringConstants.NETWORK_TOKEN)) {
                              // If the src and dest tp have network-token, then it is a regen
                              LOG.info("Create the regen-interfaces on the src-tp");
                              // Here we first create ODUCn interface for the Regen
-                             createdOduInterfaces.add(this.openRoadmInterfaceFactory.createOpenRoadmOducn(nodeId,
-                                     srcTp));
+                             String openRoadmOducn = this.openRoadmInterfaceFactory.createOpenRoadmOducn(nodeId,
+                                     srcTp);
+                             createdOduInterfaces.add(openRoadmOducn);
+                             transactionHistory.add(new DeviceInterface(nodeId, openRoadmOducn));
                              LOG.info("all src odu interfaces {}", createdOduInterfaces);
                          } else {
-                             createdOduInterfaces.add(this.openRoadmInterfaceFactory.createOpenRoadmOdu4HOInterface(
-                                     nodeId, srcTp, false, apiInfoA, apiInfoZ, PT_07));
+                             String openRoadmOdu4HOInterface = this.openRoadmInterfaceFactory
+                                     .createOpenRoadmOdu4HOInterface(nodeId, srcTp, false, apiInfoA, apiInfoZ, PT_07);
+                             createdOduInterfaces.add(openRoadmOdu4HOInterface);
+                             transactionHistory.add(new DeviceInterface(nodeId, openRoadmOdu4HOInterface));
                          }
                      }
                      if ((destTp != null) && destTp.contains(StringConstants.CLIENT_TOKEN)) {
                          LOG.info("Adding supporting EThernet interface for node {}, dest tp {}", nodeId, destTp);
                          crossConnectFlag++;
                          // create OpenRoadm Xponder Client Interfaces
-                         createdEthInterfaces.add(this.openRoadmInterfaceFactory.createOpenRoadmEthInterface(
-                                 nodeId, destTp));
+                         String openRoadmEthInterface = this.openRoadmInterfaceFactory.createOpenRoadmEthInterface(
+                                 nodeId, destTp);
+                         createdEthInterfaces.add(openRoadmEthInterface);
+                         transactionHistory.add(new DeviceInterface(nodeId, openRoadmEthInterface));
                      }
                      if ((srcTp != null) && (srcTp.contains(StringConstants.TTP_TOKEN)
                              || srcTp.contains(StringConstants.PP_TOKEN))) {
                          LOG.info("Adding supporting OCH interface for node {}, src tp {}, spectrumInformation {}",
                                  nodeId, srcTp, spectrumInformation);
-                         createdOchInterfaces.addAll(this.openRoadmInterfaceFactory.createOpenRoadmOchInterfaces(
-                                 nodeId, srcTp, spectrumInformation));
+                         List<String> openRoadmOchInterfaces = this.openRoadmInterfaceFactory
+                                 .createOpenRoadmOchInterfaces(nodeId, srcTp, spectrumInformation);
+                         createdOchInterfaces.addAll(openRoadmOchInterfaces);
+                         transactionHistory.addInterfaces(nodeId, openRoadmOchInterfaces);
                      }
                      if ((destTp != null) && (destTp.contains(StringConstants.TTP_TOKEN)
                              || destTp.contains(StringConstants.PP_TOKEN))) {
                          LOG.info("Adding supporting OCH interface for node {}, dest tp {}, spectrumInformation {}",
                                  nodeId, destTp, spectrumInformation);
-                         createdOchInterfaces.addAll(this.openRoadmInterfaceFactory.createOpenRoadmOchInterfaces(
-                                 nodeId, destTp, spectrumInformation));
+                         List<String> openRoadmOchInterfaces = this.openRoadmInterfaceFactory
+                                 .createOpenRoadmOchInterfaces(nodeId, destTp, spectrumInformation);
+                         createdOchInterfaces.addAll(openRoadmOchInterfaces);
+                         transactionHistory.addInterfaces(nodeId, openRoadmOchInterfaces);
                      }
                      if (crossConnectFlag < 1) {
                          LOG.info("Creating cross connect between source {} and destination {} for node {}", srcTp,
                                  this.crossConnect.postCrossConnect(nodeId, srcTp, destTp, spectrumInformation);
                          if (connectionNameOpt.isPresent()) {
                              nodesProvisioned.add(nodeId);
-                             createdConnections.add(connectionNameOpt.orElseThrow());
+                             String connectionName = connectionNameOpt.orElseThrow();
+                             createdConnections.add(connectionName);
+                             transactionHistory.add(new Connection(nodeId, connectionName, false));
                          } else {
                              processErrorMessage("Unable to post Roadm-connection for node " + nodeId, forkJoinPool,
                                      results);
                  .build();
      }
  
+     @Override
+     public RendererRollbackOutput rendererRollback(History transactionHistory) {
+         LOG.info("Rolling back...");
+         Result rollbackResult = new FailedRollbackResult();
+         Subscriber deleteSubscriber = new DeleteSubscriber(rollbackResult);
+         transactionHistory.rollback(
+                 new DeleteService(
+                         crossConnect,
+                         openRoadmInterfaces,
+                         deleteSubscriber
+                 )
+         );
+         LOG.info("Rollback done!");
+         return rollbackResult.renderRollbackOutput();
+     }
      private boolean alarmSuppressionNodeRegistration(ServicePathInput input) {
          Map<org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.alarmsuppression.rev171102.service
                  .nodelist.nodelist.NodesKey,
index b051192ad21e54bcef1920f024a38ab371cdcda0,fb29f90c854a1fb6a538ade8f9dfc957cb4e70e2..cca076fa691a1650fea5b79820bfeba20706afea
@@@ -36,10 -36,14 +36,14 @@@ import org.opendaylight.transportpce.re
  import org.opendaylight.transportpce.renderer.provisiondevice.servicepath.ServicePathDirection;
  import org.opendaylight.transportpce.renderer.provisiondevice.tasks.DeviceRenderingRollbackTask;
  import org.opendaylight.transportpce.renderer.provisiondevice.tasks.DeviceRenderingTask;
+ import org.opendaylight.transportpce.renderer.provisiondevice.tasks.NetworkDeviceRenderingRollbackTask;
  import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OlmPowerSetupRollbackTask;
  import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OlmPowerSetupTask;
  import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OtnDeviceRenderingTask;
  import org.opendaylight.transportpce.renderer.provisiondevice.tasks.RollbackProcessor;
+ import org.opendaylight.transportpce.renderer.provisiondevice.tasks.RollbackResultMessage;
+ import org.opendaylight.transportpce.renderer.provisiondevice.transaction.history.History;
+ import org.opendaylight.transportpce.renderer.provisiondevice.transaction.history.TransactionHistory;
  import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.Action;
  import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.OtnServicePathInput;
  import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkutils.rev220630.OtnLinkType;
@@@ -141,7 -145,7 +145,7 @@@ public class RendererServiceOperationsI
                      "Service compliant, submitting service implementation Request ...");
                  Uint32 serviceRate = getServiceRate(input);
                  LOG.info("Using {}G rate", serviceRate);
 -                org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220922
 +                org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev231221
                          .network.Nodes mappingNode =
                      portMapping.isNodeExist(input.getServiceAEnd().getNodeId())
                          ? portMapping.getNode(input.getServiceAEnd().getNodeId())
              servicePathDataAtoZ.getServicePathInput().getServiceName(),
              RpcStatusEx.Pending,
              RENDERING_DEVICES_A_Z_MSG);
+         History transactionHistory = new TransactionHistory();
          ListenableFuture<DeviceRenderingResult> atozrenderingFuture =
              this.executor.submit(
-                 new DeviceRenderingTask(this.deviceRenderer, servicePathDataAtoZ, ServicePathDirection.A_TO_Z));
+                 new DeviceRenderingTask(this.deviceRenderer, servicePathDataAtoZ, ServicePathDirection.A_TO_Z,
+                         transactionHistory));
  
          LOG.info(RENDERING_DEVICES_Z_A_MSG);
          sendNotifications(
              RENDERING_DEVICES_Z_A_MSG);
          ListenableFuture<DeviceRenderingResult> ztoarenderingFuture =
              this.executor.submit(
-                 new DeviceRenderingTask(this.deviceRenderer, servicePathDataZtoA, ServicePathDirection.Z_TO_A));
+                 new DeviceRenderingTask(this.deviceRenderer, servicePathDataZtoA, ServicePathDirection.Z_TO_A,
+                         transactionHistory));
  
          ListenableFuture<List<DeviceRenderingResult>> renderingCombinedFuture =
              Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
          }
  
          rollbackProcessor.addTask(
-             new DeviceRenderingRollbackTask(
-                 "AtoZDeviceTask",
-                 ! renderingResults.get(0).isSuccess(),
-                 renderingResults.get(0).getRenderedNodeInterfaces(),
-                 this.deviceRenderer));
-         rollbackProcessor.addTask(
-                 new DeviceRenderingRollbackTask("ZtoADeviceTask",
-                 ! renderingResults.get(1).isSuccess(),
-                 renderingResults.get(1).getRenderedNodeInterfaces(),
-                 this.deviceRenderer));
+             new NetworkDeviceRenderingRollbackTask(
+                 "RollbackTransactionHistoryTask",
+                 transactionHistory,
+                 ! (renderingResults.get(0).isSuccess() && renderingResults.get(1).isSuccess()),
+                 deviceRenderer,
+                 new RollbackResultMessage()
+             )
+         );
          return renderingResults;
      }