2  * ============LICENSE_START=======================================================
 
   4  * ================================================================================
 
   5  * Copyright (C) 2017 AT&T Intellectual Property. All rights
 
   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
 
  12  *      http://www.apache.org/licenses/LICENSE-2.0
 
  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=========================================================
 
  22 package org.onap.ccsdk.sli.northbound.asdcapi;
 
  24 import com.google.common.base.Optional;
 
  25 import com.google.common.util.concurrent.FluentFuture;
 
  26 import com.google.common.util.concurrent.Futures;
 
  27 import com.google.common.util.concurrent.ListenableFuture;
 
  28 import java.util.Properties;
 
  29 import java.util.concurrent.ExecutionException;
 
  30 import java.util.concurrent.ExecutorService;
 
  31 import java.util.concurrent.Executors;
 
  32 import org.eclipse.jdt.annotation.NonNull;
 
  33 import org.opendaylight.mdsal.binding.api.DataBroker;
 
  34 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
 
  35 import org.opendaylight.mdsal.binding.api.ReadTransaction;
 
  36 import org.opendaylight.mdsal.binding.api.RpcProviderService;
 
  37 import org.opendaylight.mdsal.binding.api.WriteTransaction;
 
  38 import org.opendaylight.mdsal.common.api.CommitInfo;
 
  39 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 
  40 import org.opendaylight.yang.gen.v1.http.xmlns.onap.org.asdc.license.model._1._0.rev160427.vf.license.model.grouping.VfLicenseModel;
 
  41 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev170201.ASDCAPIService;
 
  42 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev170201.Artifacts;
 
  43 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev170201.ArtifactsBuilder;
 
  44 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev170201.VfLicenseModelUpdateInput;
 
  45 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev170201.VfLicenseModelUpdateInputBuilder;
 
  46 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev170201.VfLicenseModelUpdateOutput;
 
  47 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev170201.VfLicenseModelUpdateOutputBuilder;
 
  48 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev170201.VfLicenseModelVersions;
 
  49 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev170201.VfLicenseModelVersionsBuilder;
 
  50 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev170201.artifacts.Artifact;
 
  51 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev170201.artifacts.ArtifactBuilder;
 
  52 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev170201.artifacts.ArtifactKey;
 
  53 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev170201.vf.license.model.versions.VfLicenseModelVersion;
 
  54 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev170201.vf.license.model.versions.VfLicenseModelVersionBuilder;
 
  55 import org.opendaylight.yangtools.concepts.ObjectRegistration;
 
  56 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
  57 import org.opendaylight.yangtools.yang.common.RpcResult;
 
  58 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 
  59 import org.slf4j.Logger;
 
  60 import org.slf4j.LoggerFactory;
 
  63  * Defines a base implementation for your provider. This class extends from a helper class
 
  64  * which provides storage for the most commonly used components of the MD-SAL. Additionally the
 
  65  * base class provides some basic logging and initialization / clean up methods.
 
  67  * To use this, copy and paste (overwrite) the following method into the TestApplicationProviderModule
 
  68  * class which is auto generated under src/main/java in this project
 
  69  * (created only once during first compilation):
 
  74     public java.lang.AutoCloseable createInstance() {
 
  76          final asdcApiProvider provider = new asdcApiProvider();
 
  77          provider.setDataBroker( getDataBrokerDependency() );
 
  78          provider.setNotificationService( getNotificationServiceDependency() );
 
  79          provider.setRpcRegistry( getRpcRegistryDependency() );
 
  80          provider.initialize();
 
  81          return new AutoCloseable() {
 
  84             public void close() throws Exception {
 
  85                 //TODO: CLOSE ANY REGISTRATION OBJECTS CREATED USING ABOVE BROKER/NOTIFICATION
 
  95 public class AsdcApiProvider implements AutoCloseable, ASDCAPIService {
 
  97     private static final Logger LOG = LoggerFactory.getLogger(AsdcApiProvider.class);
 
  99     private static final String ACTIVE_VERSION = "active";
 
 101     private static final String APPLICATION_NAME = "asdcApi";
 
 103     private final ExecutorService executor;
 
 104     protected DataBroker dataBroker;
 
 105     protected NotificationPublishService notificationService;
 
 106     protected RpcProviderService rpcRegistry;
 
 107     private final AsdcApiSliClient asdcApiSliClient;
 
 109     protected ObjectRegistration<ASDCAPIService> rpcRegistration;
 
 111     public AsdcApiProvider(final DataBroker dataBroker,
 
 112                            final NotificationPublishService notificationPublishService,
 
 113                            final RpcProviderService rpcProviderRegistry,
 
 114                            final AsdcApiSliClient asdcApiSliClient) {
 
 116         LOG.info("Creating provider for {}", APPLICATION_NAME);
 
 117         executor = Executors.newFixedThreadPool(1);
 
 118         this.dataBroker = dataBroker;
 
 119         notificationService = notificationPublishService;
 
 120         rpcRegistry = rpcProviderRegistry;
 
 121         this.asdcApiSliClient= asdcApiSliClient;
 
 125     public void initialize(){
 
 126         LOG.info("Initializing {} for {}", this.getClass().getName(), APPLICATION_NAME);
 
 130         if (rpcRegistration == null) {
 
 131             if (rpcRegistry != null) {
 
 132                 rpcRegistration = rpcRegistry.registerRpcImplementation(
 
 133                         ASDCAPIService.class, this);
 
 134                 LOG.info("Initialization complete for {}", APPLICATION_NAME);
 
 136                 LOG.warn("Error initializing {} : rpcRegistry unset", APPLICATION_NAME);
 
 141     private void createContainers() {
 
 143         if (dataBroker != null) {
 
 144         final WriteTransaction t = dataBroker.newReadWriteTransaction();
 
 146         // Create the vf-model-license-versions and artifacts containers
 
 147         t.merge(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(VfLicenseModelVersions.class),
 
 148         new VfLicenseModelVersionsBuilder().build());
 
 150         t.merge(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(Artifacts.class), new ArtifactsBuilder().build());
 
 154             FluentFuture<? extends @NonNull CommitInfo> checkedFuture = t.commit();
 
 156             LOG.info("Create Containers succeeded!: ");
 
 158         } catch (InterruptedException | ExecutionException e) {
 
 159             LOG.error("Create Containers Failed: ", e);
 
 162             LOG.warn("createContainers : cannot find dataBroker to create containers");
 
 165     protected void initializeChild() {
 
 166         //Override if you have custom initialization intelligence
 
 170     public void close() throws Exception {
 
 171         LOG.info( "Closing provider for " + APPLICATION_NAME);
 
 173         rpcRegistration.close();
 
 174         LOG.info( "Successfully closed provider for " + APPLICATION_NAME);
 
 177     protected boolean artifactVersionExists(String aName, String aVersion) {
 
 178         InstanceIdentifier artifactInstanceId =
 
 179                 InstanceIdentifier.<Artifacts>builder(Artifacts.class)
 
 180                 .child(Artifact.class, new ArtifactKey(aName, aVersion)).build();
 
 181         Optional<Artifact> data = null;
 
 182         try(ReadTransaction readTx = dataBroker.newReadOnlyTransaction()) {
 
 183             data = (Optional<Artifact>) readTx.read(LogicalDatastoreType.CONFIGURATION, artifactInstanceId).get();
 
 184         } catch (InterruptedException | ExecutionException e) {
 
 185             LOG.error("Caught Exception reading MD-SAL for ["+aName+","+ aVersion+"] " ,e);
 
 189         return data.isPresent();
 
 192     protected void addArtifactVersion(String aName, String aVersion) {
 
 196             ArtifactBuilder aBuilder = new ArtifactBuilder();
 
 198             aBuilder.setArtifactName(aName);
 
 199             aBuilder.setArtifactVersion(aVersion);
 
 201             Artifact artifact = aBuilder.build();
 
 203             InstanceIdentifier.InstanceIdentifierBuilder<Artifact> aIdBuilder = InstanceIdentifier
 
 204                     .<Artifacts> builder(Artifacts.class)
 
 205                     .child(Artifact.class, artifact.key());
 
 207             InstanceIdentifier<Artifact> path = aIdBuilder.build();
 
 209             WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
 
 211             tx.merge(LogicalDatastoreType.CONFIGURATION, path,
 
 214         } catch (Exception e) {
 
 215             LOG.error("Caught exception trying to add artifact entry", e);
 
 221     private void applyVfLicenseModelUpdate(VfLicenseModelUpdateInput input) {
 
 223     String aName = input.getArtifactName();
 
 224     String aVersion = input.getArtifactVersion();
 
 225     VfLicenseModel vfLicenseModel = input.getVfLicenseModel();
 
 228     // Add new version (version = artifact-version)
 
 231         VfLicenseModelVersionBuilder vBuilder = new VfLicenseModelVersionBuilder();
 
 232         vBuilder.setArtifactName(aName);
 
 233         vBuilder.setArtifactVersion(aVersion);
 
 234         vBuilder.setVfLicenseModel(vfLicenseModel);
 
 236         VfLicenseModelVersion version = vBuilder.build();
 
 238         InstanceIdentifier.InstanceIdentifierBuilder<VfLicenseModelVersion> versionIdBuilder = InstanceIdentifier
 
 239                 .<VfLicenseModelVersions> builder(VfLicenseModelVersions.class)
 
 240                 .child(VfLicenseModelVersion.class, version.key());
 
 242         InstanceIdentifier<VfLicenseModelVersion> path = versionIdBuilder.build();
 
 244         WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
 
 245   tx.merge(LogicalDatastoreType.CONFIGURATION, path,
 
 248     } catch (Exception e) {
 
 250                 "Caught exception trying to save entry to MD-SAL",
 
 255     // Add "active" version (version = "active")
 
 258         VfLicenseModelVersionBuilder vBuilder = new VfLicenseModelVersionBuilder();
 
 259         vBuilder.setArtifactName(aName);
 
 260         vBuilder.setArtifactVersion(ACTIVE_VERSION);
 
 261         vBuilder.setVfLicenseModel(vfLicenseModel);
 
 263         VfLicenseModelVersion version = vBuilder.build();
 
 264         InstanceIdentifier.InstanceIdentifierBuilder<VfLicenseModelVersion> versionIdBuilder = InstanceIdentifier
 
 265                 .<VfLicenseModelVersions> builder(VfLicenseModelVersions.class)
 
 266                 .child(VfLicenseModelVersion.class, version.key());
 
 268         InstanceIdentifier<VfLicenseModelVersion> path = versionIdBuilder.build();
 
 270         WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
 
 272         tx.merge(LogicalDatastoreType.CONFIGURATION, path,
 
 275     } catch (Exception e) {
 
 277                 "Caught exception trying to save entry to MD-SAL",
 
 284 public ListenableFuture<RpcResult<VfLicenseModelUpdateOutput>> vfLicenseModelUpdate(VfLicenseModelUpdateInput input) {
 
 285     final String svcOperation = "vf-license-model-update";
 
 287     Properties parms = new Properties();
 
 289     LOG.info( svcOperation +" called." );
 
 292         LOG.debug("exiting " +svcOperation+ " because of invalid input");
 
 296     VfLicenseModelUpdateInputBuilder inputBuilder = new VfLicenseModelUpdateInputBuilder(input);
 
 298     VfLicenseModelUpdateInput inputVfLic = inputBuilder.build();
 
 300     String errorMessage = "Success";
 
 301     String errorCode = "200";
 
 303     // If this artifact already exists, reject this update
 
 304     if (artifactVersionExists(inputVfLic.getArtifactName(), inputVfLic.getArtifactVersion())) {
 
 306         errorMessage = "Artifact version already exists";
 
 308         // Translate input object into SLI-consumable properties
 
 309         LOG.info("Adding INPUT data for "+svcOperation+" input: " + inputVfLic);
 
 310         AsdcApiUtil.toProperties(parms, inputVfLic);
 
 313         // Call directed graph
 
 314         Properties respProps = null;
 
 317             if (asdcApiSliClient.hasGraph("ASDC-API", svcOperation , null, "sync"))
 
 322                     respProps = asdcApiSliClient.execute("ASDC-API", svcOperation, null, "sync", parms);
 
 326                     LOG.error("Caught exception executing service logic for "+ svcOperation, e);
 
 329                 errorMessage = "No service logic active for ASDC-API: '" + svcOperation + "'";
 
 336             errorMessage = e.getMessage();
 
 337             LOG.error("Caught exception looking for service logic", e);
 
 341         if (respProps != null)
 
 343             errorCode = respProps.getProperty("error-code");
 
 344             errorMessage = respProps.getProperty("error-message", "");
 
 349     if ("200".equals(errorCode)) {
 
 350         LOG.info("ASDC update succeeded");
 
 352         // Update config tree
 
 353         applyVfLicenseModelUpdate(inputVfLic);
 
 354         addArtifactVersion(inputVfLic.getArtifactName(), inputVfLic.getArtifactVersion());
 
 357         LOG.info("ASDC update failed ("+errorCode+" : "+errorMessage);
 
 361     VfLicenseModelUpdateOutputBuilder respBuilder = new VfLicenseModelUpdateOutputBuilder();
 
 362     respBuilder.setAsdcApiResponseCode(errorCode);
 
 363     if (errorMessage != null && errorMessage.length() > 0) {
 
 364         respBuilder.setAsdcApiResponseText(errorMessage);
 
 367     RpcResult<VfLicenseModelUpdateOutput> rpcResult;
 
 370     rpcResult = RpcResultBuilder.<VfLicenseModelUpdateOutput> status(true).withResult(respBuilder.build()).build();
 
 374     return Futures.immediateFuture(rpcResult);