/*- * ============LICENSE_START======================================================= * openECOMP : SDN-C * ================================================================================ * Copyright (C) 2017 AT&T Intellectual Property. All rights * reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============LICENSE_END========================================================= */ package org.openecomp.sdnc.asdcapi; import com.google.common.base.Optional; import com.google.common.util.concurrent.CheckedFuture; import com.google.common.util.concurrent.Futures; import java.util.Properties; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker; import org.opendaylight.controller.sal.binding.api.NotificationProviderService; import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; import org.opendaylight.yang.gen.v1.http.xmlns.openecomp.org.asdc.license.model._1._0.rev160427.vf.license.model.grouping.VfLicenseModel; import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.rev170201.ASDCAPIService; import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.rev170201.Artifacts; import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.rev170201.ArtifactsBuilder; import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.rev170201.VfLicenseModelUpdateInput; import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.rev170201.VfLicenseModelUpdateInputBuilder; import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.rev170201.VfLicenseModelUpdateOutput; import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.rev170201.VfLicenseModelUpdateOutputBuilder; import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.rev170201.VfLicenseModelVersions; import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.rev170201.VfLicenseModelVersionsBuilder; import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.rev170201.artifacts.Artifact; import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.rev170201.artifacts.ArtifactBuilder; import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.rev170201.artifacts.ArtifactKey; import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.rev170201.vf.license.model.versions.VfLicenseModelVersion; import org.opendaylight.yang.gen.v1.org.openecomp.sdnc.rev170201.vf.license.model.versions.VfLicenseModelVersionBuilder; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.common.RpcResultBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Defines a base implementation for your provider. This class extends from a helper class * which provides storage for the most commonly used components of the MD-SAL. Additionally the * base class provides some basic logging and initialization / clean up methods. * * To use this, copy and paste (overwrite) the following method into the TestApplicationProviderModule * class which is auto generated under src/main/java in this project * (created only once during first compilation): * *

    @Override
    public java.lang.AutoCloseable createInstance() {

         final asdcApiProvider provider = new asdcApiProvider();
         provider.setDataBroker( getDataBrokerDependency() );
         provider.setNotificationService( getNotificationServiceDependency() );
         provider.setRpcRegistry( getRpcRegistryDependency() );
         provider.initialize();
         return new AutoCloseable() {

            @Override
            public void close() throws Exception {
                //TODO: CLOSE ANY REGISTRATION OBJECTS CREATED USING ABOVE BROKER/NOTIFICATION
                //SERVIE/RPC REGISTRY
                provider.close();
            }
        };
    }


    
*/ public class AsdcApiProvider implements AutoCloseable, ASDCAPIService { private static final String ACTIVE_VERSION = "active"; private final Logger log = LoggerFactory.getLogger( AsdcApiProvider.class ); private final String appName = "asdcApi"; private final ExecutorService executor; protected DataBroker dataBroker; protected NotificationProviderService notificationService; protected RpcProviderRegistry rpcRegistry; protected BindingAwareBroker.RpcRegistration rpcRegistration; public AsdcApiProvider(DataBroker dataBroker2, NotificationProviderService notificationProviderService, RpcProviderRegistry rpcProviderRegistry) { this.log.info( "Creating provider for " + appName ); executor = Executors.newFixedThreadPool(1); dataBroker = dataBroker2; notificationService = notificationProviderService; rpcRegistry = rpcProviderRegistry; initialize(); } public void initialize(){ log.info( "Initializing provider for " + appName ); createContainers(); if (rpcRegistration == null) { if (rpcRegistry != null) { rpcRegistration = rpcRegistry.addRpcImplementation( ASDCAPIService.class, this); log.info("Initialization complete for " + appName); } else { log.warn("Error initializing " + appName + " : rpcRegistry unset"); } } } private void createContainers() { if (dataBroker != null) { final WriteTransaction t = dataBroker.newReadWriteTransaction(); // Create the vf-model-license-versions and artifacts containers t.merge(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(VfLicenseModelVersions.class), new VfLicenseModelVersionsBuilder().build()); t.merge(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(Artifacts.class), new ArtifactsBuilder().build()); try { CheckedFuture checkedFuture = t.submit(); checkedFuture.get(); log.info("Create Containers succeeded!: "); } catch (InterruptedException | ExecutionException e) { log.error("Create Containers Failed: " + e); e.printStackTrace(); } } else { log.warn("createContainers : cannot find dataBroker to create containers"); } } protected void initializeChild() { //Override if you have custom initialization intelligence } @Override public void close() throws Exception { log.info( "Closing provider for " + appName ); executor.shutdown(); rpcRegistration.close(); log.info( "Successfully closed provider for " + appName ); } public void setDataBroker(DataBroker dataBroker) { this.dataBroker = dataBroker; if( log.isDebugEnabled() ){ log.debug( "DataBroker set to " + (dataBroker==null?"null":"non-null") + "." ); } } public void setNotificationService( NotificationProviderService notificationService) { this.notificationService = notificationService; if( log.isDebugEnabled() ){ log.debug( "Notification Service set to " + (notificationService==null?"null":"non-null") + "." ); } } public void setRpcRegistry(RpcProviderRegistry rpcRegistry) { this.rpcRegistry = rpcRegistry; rpcRegistration = rpcRegistry.addRpcImplementation(ASDCAPIService.class, this); if( log.isDebugEnabled() ){ log.debug( "RpcRegistry set to " + (rpcRegistry==null?"null":"non-null") + "." ); } } protected boolean artifactVersionExists(String aName, String aVersion) { InstanceIdentifier artifactInstanceId = InstanceIdentifier.builder(Artifacts.class) .child(Artifact.class, new ArtifactKey(aName, aVersion)).toInstance(); ReadOnlyTransaction readTx = dataBroker.newReadOnlyTransaction(); Optional data = null; try { data = (Optional) readTx.read(LogicalDatastoreType.CONFIGURATION, artifactInstanceId).get(); } catch (InterruptedException | ExecutionException e) { log.error("Caught Exception reading MD-SAL for ["+aName+","+ aVersion+"] " ,e); return false; } if (data.isPresent()) { return true; } else { return false; } } protected void addArtifactVersion(String aName, String aVersion) { try { ArtifactBuilder aBuilder = new ArtifactBuilder(); aBuilder.setArtifactName(aName); aBuilder.setArtifactVersion(aVersion); Artifact artifact = aBuilder.build(); InstanceIdentifier.InstanceIdentifierBuilder aIdBuilder = InstanceIdentifier . builder(Artifacts.class) .child(Artifact.class, artifact.getKey()); InstanceIdentifier path = aIdBuilder .toInstance(); WriteTransaction tx = dataBroker.newWriteOnlyTransaction(); tx.merge(LogicalDatastoreType.CONFIGURATION, path, artifact); tx.submit().checkedGet(); } catch (Exception e) { log.error("Caught exception trying to add artifact entry", e); } } private void applyVfLicenseModelUpdate(VfLicenseModelUpdateInput input) { String aName = input.getArtifactName(); String aVersion = input.getArtifactVersion(); VfLicenseModel vfLicenseModel = input.getVfLicenseModel(); // Add new version (version = artifact-version) try { VfLicenseModelVersionBuilder vBuilder = new VfLicenseModelVersionBuilder(); vBuilder.setArtifactName(aName); vBuilder.setArtifactVersion(aVersion); vBuilder.setVfLicenseModel(vfLicenseModel); VfLicenseModelVersion version = vBuilder.build(); InstanceIdentifier.InstanceIdentifierBuilder versionIdBuilder = InstanceIdentifier . builder(VfLicenseModelVersions.class) .child(VfLicenseModelVersion.class, version.getKey()); InstanceIdentifier path = versionIdBuilder .toInstance(); WriteTransaction tx = dataBroker.newWriteOnlyTransaction(); tx.merge(LogicalDatastoreType.CONFIGURATION, path, version); tx.submit().checkedGet(); } catch (Exception e) { log.error( "Caught exception trying to save entry to MD-SAL", e); } // Add "active" version (version = "active") try { VfLicenseModelVersionBuilder vBuilder = new VfLicenseModelVersionBuilder(); vBuilder.setArtifactName(aName); vBuilder.setArtifactVersion(ACTIVE_VERSION); vBuilder.setVfLicenseModel(vfLicenseModel); VfLicenseModelVersion version = vBuilder.build(); InstanceIdentifier.InstanceIdentifierBuilder versionIdBuilder = InstanceIdentifier . builder(VfLicenseModelVersions.class) .child(VfLicenseModelVersion.class, version.getKey()); InstanceIdentifier path = versionIdBuilder .toInstance(); WriteTransaction tx = dataBroker.newWriteOnlyTransaction(); tx.merge(LogicalDatastoreType.CONFIGURATION, path, version); tx.submit().checkedGet(); } catch (Exception e) { log.error( "Caught exception trying to save entry to MD-SAL", e); } } @Override public Future> vfLicenseModelUpdate(VfLicenseModelUpdateInput input) { final String SVC_OPERATION = "vf-license-model-update"; Properties parms = new Properties(); log.info( SVC_OPERATION +" called." ); if(input == null ) { log.debug("exiting " +SVC_OPERATION+ " because of invalid input"); return null; } VfLicenseModelUpdateInputBuilder inputBuilder = new VfLicenseModelUpdateInputBuilder(input); input = inputBuilder.build(); String errorMessage = "Success"; String errorCode = "200"; // If this artifact already exists, reject this update if (artifactVersionExists(input.getArtifactName(), input.getArtifactVersion())) { errorCode = "409"; errorMessage = "Artifact version already exists"; } else { // Translate input object into SLI-consumable properties log.info("Adding INPUT data for "+SVC_OPERATION+" input: " + input); AsdcApiUtil.toProperties(parms, input); // Call directed graph Properties respProps = null; AsdcApiSliClient sliClient = new AsdcApiSliClient(); try { if (sliClient.hasGraph("ASDC-API", SVC_OPERATION , null, "sync")) { try { respProps = sliClient.execute("ASDC-API", SVC_OPERATION, null, "sync", parms); } catch (Exception e) { log.error("Caught exception executing service logic for "+ SVC_OPERATION, e); } } else { errorMessage = "No service logic active for ASDC-API: '" + SVC_OPERATION + "'"; errorCode = "503"; } } catch (Exception e) { errorCode = "500"; errorMessage = e.getMessage(); log.error("Caught exception looking for service logic", e); } if (respProps != null) { errorCode = respProps.getProperty("error-code"); errorMessage = respProps.getProperty("error-message", ""); } } if ("200".equals(errorCode)) { log.info("ASDC update succeeded"); // Update config tree applyVfLicenseModelUpdate(input); addArtifactVersion(input.getArtifactName(), input.getArtifactVersion()); } else { log.info("ASDC update failed ("+errorCode+" : "+errorMessage); } // Send response VfLicenseModelUpdateOutputBuilder respBuilder = new VfLicenseModelUpdateOutputBuilder(); respBuilder.setAsdcApiResponseCode(errorCode); if (errorMessage != null && errorMessage.length() > 0) { respBuilder.setAsdcApiResponseText(errorMessage); } RpcResult rpcResult; rpcResult = RpcResultBuilder. status(true).withResult(respBuilder.build()).build(); return Futures.immediateFuture(rpcResult); } }