[CCSDK-6] Populate seed code
[ccsdk/sli/northbound.git] / asdcApi / provider / src / main / java / org / onap / ccsdk / sli / northbound / asdcapi / AsdcApiProvider.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * openECOMP : SDN-C
4  * ================================================================================
5  * Copyright (C) 2017 ONAP Intellectual Property. All rights
6  *                                              reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  * 
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  * 
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.ccsdk.sli.northbound.asdcapi;
23
24 import java.util.Properties;
25 import java.util.concurrent.ExecutionException;
26 import java.util.concurrent.ExecutorService;
27 import java.util.concurrent.Executors;
28 import java.util.concurrent.Future;
29
30 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
31 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
32 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
33 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
34 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
35 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
36 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
37 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
38 import org.opendaylight.yang.gen.v1.http.xmlns.onap.org.asdc.license.model._1._0.rev160427.vf.license.model.grouping.VfLicenseModel;
39 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev170201.ASDCAPIService;
40 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev170201.Artifacts;
41 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev170201.ArtifactsBuilder;
42 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev170201.VfLicenseModelUpdateInput;
43 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev170201.VfLicenseModelUpdateInputBuilder;
44 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev170201.VfLicenseModelUpdateOutput;
45 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev170201.VfLicenseModelUpdateOutputBuilder;
46 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev170201.VfLicenseModelVersions;
47 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev170201.VfLicenseModelVersionsBuilder;
48 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev170201.artifacts.Artifact;
49 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev170201.artifacts.ArtifactBuilder;
50 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev170201.artifacts.ArtifactKey;
51 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev170201.vf.license.model.versions.VfLicenseModelVersion;
52 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev170201.vf.license.model.versions.VfLicenseModelVersionBuilder;
53 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
54 import org.opendaylight.yangtools.yang.common.RpcResult;
55 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
58
59 import com.google.common.base.Optional;
60 import com.google.common.util.concurrent.CheckedFuture;
61 import com.google.common.util.concurrent.Futures;
62
63 /**
64  * Defines a base implementation for your provider. This class extends from a helper class
65  * which provides storage for the most commonly used components of the MD-SAL. Additionally the
66  * base class provides some basic logging and initialization / clean up methods.
67  *
68  * To use this, copy and paste (overwrite) the following method into the TestApplicationProviderModule
69  * class which is auto generated under src/main/java in this project
70  * (created only once during first compilation):
71  *
72  * <pre>
73
74     @Override
75     public java.lang.AutoCloseable createInstance() {
76
77          final asdcApiProvider provider = new asdcApiProvider();
78          provider.setDataBroker( getDataBrokerDependency() );
79          provider.setNotificationService( getNotificationServiceDependency() );
80          provider.setRpcRegistry( getRpcRegistryDependency() );
81          provider.initialize();
82          return new AutoCloseable() {
83
84             @Override
85             public void close() throws Exception {
86                 //TODO: CLOSE ANY REGISTRATION OBJECTS CREATED USING ABOVE BROKER/NOTIFICATION
87                 //SERVIE/RPC REGISTRY
88                 provider.close();
89             }
90         };
91     }
92
93
94     </pre>
95  */
96 public class AsdcApiProvider implements AutoCloseable, ASDCAPIService {
97
98     private static final String ACTIVE_VERSION = "active";
99
100     private final Logger log = LoggerFactory.getLogger( AsdcApiProvider.class );
101     private final String appName = "asdcApi";
102
103     private final ExecutorService executor;
104     protected DataBroker dataBroker;
105     protected NotificationProviderService notificationService;
106     protected RpcProviderRegistry rpcRegistry;
107
108     protected BindingAwareBroker.RpcRegistration<ASDCAPIService> rpcRegistration;
109
110     public AsdcApiProvider(DataBroker dataBroker2,
111             NotificationProviderService notificationProviderService,
112             RpcProviderRegistry rpcProviderRegistry) {
113         this.log.info( "Creating provider for " + appName );
114         executor = Executors.newFixedThreadPool(1);
115         dataBroker = dataBroker2;
116         notificationService = notificationProviderService;
117         rpcRegistry = rpcProviderRegistry;
118         initialize();
119     }
120
121     public void initialize(){
122         log.info( "Initializing provider for " + appName );
123
124
125         createContainers();
126
127         if (rpcRegistration == null) {
128             if (rpcRegistry != null) {
129                 rpcRegistration = rpcRegistry.addRpcImplementation(
130                         ASDCAPIService.class, this);
131                 log.info("Initialization complete for " + appName);
132             } else {
133                 log.warn("Error initializing " + appName
134                         + " : rpcRegistry unset");
135             }
136         }
137     }
138
139     private void createContainers() {
140
141         if (dataBroker != null) {
142         final WriteTransaction t = dataBroker.newReadWriteTransaction();
143
144         // Create the vf-model-license-versions and artifacts containers
145         t.merge(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(VfLicenseModelVersions.class),
146         new VfLicenseModelVersionsBuilder().build());
147
148         t.merge(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(Artifacts.class), new ArtifactsBuilder().build());
149
150
151         try {
152             CheckedFuture<Void, TransactionCommitFailedException> checkedFuture = t.submit();
153             checkedFuture.get();
154             log.info("Create Containers succeeded!: ");
155
156         } catch (InterruptedException | ExecutionException e) {
157             log.error("Create Containers Failed: " + e);
158             e.printStackTrace();
159         }
160         } else {
161             log.warn("createContainers : cannot find dataBroker to create containers");
162         }
163     }
164     protected void initializeChild() {
165         //Override if you have custom initialization intelligence
166     }
167
168     @Override
169     public void close() throws Exception {
170         log.info( "Closing provider for " + appName );
171         executor.shutdown();
172         rpcRegistration.close();
173         log.info( "Successfully closed provider for " + appName );
174     }
175
176     public void setDataBroker(DataBroker dataBroker) {
177         this.dataBroker = dataBroker;
178         if( log.isDebugEnabled() ){
179             log.debug( "DataBroker set to " + (dataBroker==null?"null":"non-null") + "." );
180         }
181     }
182
183     public void setNotificationService(
184             NotificationProviderService notificationService) {
185         this.notificationService = notificationService;
186         if( log.isDebugEnabled() ){
187             log.debug( "Notification Service set to " + (notificationService==null?"null":"non-null") + "." );
188         }
189     }
190
191     public void setRpcRegistry(RpcProviderRegistry rpcRegistry) {
192         this.rpcRegistry = rpcRegistry;
193
194         rpcRegistration = rpcRegistry.addRpcImplementation(ASDCAPIService.class, this);
195
196         if( log.isDebugEnabled() ){
197             log.debug( "RpcRegistry set to " + (rpcRegistry==null?"null":"non-null") + "." );
198         }
199     }
200
201
202     protected boolean artifactVersionExists(String aName, String aVersion) {
203         InstanceIdentifier artifactInstanceId =
204                 InstanceIdentifier.<Artifacts>builder(Artifacts.class)
205                 .child(Artifact.class, new ArtifactKey(aName, aVersion)).toInstance();
206         ReadOnlyTransaction readTx = dataBroker.newReadOnlyTransaction();
207         Optional<Artifact> data = null;
208         try {
209             data = (Optional<Artifact>) readTx.read(LogicalDatastoreType.CONFIGURATION, artifactInstanceId).get();
210         } catch (InterruptedException | ExecutionException e) {
211             log.error("Caught Exception reading MD-SAL for ["+aName+","+ aVersion+"] " ,e);
212             return false;
213
214         }
215
216         if (data.isPresent()) {
217             return true;
218         } else {
219             return false;
220         }
221     }
222
223     protected void addArtifactVersion(String aName, String aVersion) {
224
225
226         try {
227             ArtifactBuilder aBuilder = new ArtifactBuilder();
228
229             aBuilder.setArtifactName(aName);
230             aBuilder.setArtifactVersion(aVersion);
231
232             Artifact artifact = aBuilder.build();
233
234             InstanceIdentifier.InstanceIdentifierBuilder<Artifact> aIdBuilder = InstanceIdentifier
235                     .<Artifacts> builder(Artifacts.class)
236                     .child(Artifact.class, artifact.getKey());
237
238             InstanceIdentifier<Artifact> path = aIdBuilder
239                     .toInstance();
240
241             WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
242
243             tx.merge(LogicalDatastoreType.CONFIGURATION, path,
244                     artifact);
245             tx.submit().checkedGet();
246         } catch (Exception e) {
247             log.error("Caught exception trying to add artifact entry", e);
248         }
249
250     }
251
252
253     private void applyVfLicenseModelUpdate(VfLicenseModelUpdateInput input) {
254
255     String aName = input.getArtifactName();
256     String aVersion = input.getArtifactVersion();
257     VfLicenseModel vfLicenseModel = input.getVfLicenseModel();
258
259
260     // Add new version (version = artifact-version)
261     try {
262
263         VfLicenseModelVersionBuilder vBuilder = new VfLicenseModelVersionBuilder();
264         vBuilder.setArtifactName(aName);
265         vBuilder.setArtifactVersion(aVersion);
266         vBuilder.setVfLicenseModel(vfLicenseModel);
267
268         VfLicenseModelVersion version = vBuilder.build();
269
270         InstanceIdentifier.InstanceIdentifierBuilder<VfLicenseModelVersion> versionIdBuilder = InstanceIdentifier
271                 .<VfLicenseModelVersions> builder(VfLicenseModelVersions.class)
272                 .child(VfLicenseModelVersion.class, version.getKey());
273
274         InstanceIdentifier<VfLicenseModelVersion> path = versionIdBuilder
275                 .toInstance();
276
277         WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
278   tx.merge(LogicalDatastoreType.CONFIGURATION, path,
279                 version);
280         tx.submit().checkedGet();
281     } catch (Exception e) {
282         log.error(
283                 "Caught exception trying to save entry to MD-SAL",
284                 e);
285     }
286
287
288     // Add "active" version (version = "active")
289     try {
290
291         VfLicenseModelVersionBuilder vBuilder = new VfLicenseModelVersionBuilder();
292         vBuilder.setArtifactName(aName);
293         vBuilder.setArtifactVersion(ACTIVE_VERSION);
294         vBuilder.setVfLicenseModel(vfLicenseModel);
295
296         VfLicenseModelVersion version = vBuilder.build();
297         InstanceIdentifier.InstanceIdentifierBuilder<VfLicenseModelVersion> versionIdBuilder = InstanceIdentifier
298                 .<VfLicenseModelVersions> builder(VfLicenseModelVersions.class)
299                 .child(VfLicenseModelVersion.class, version.getKey());
300
301         InstanceIdentifier<VfLicenseModelVersion> path = versionIdBuilder
302                 .toInstance();
303
304         WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
305
306         tx.merge(LogicalDatastoreType.CONFIGURATION, path,
307                 version);
308         tx.submit().checkedGet();
309     } catch (Exception e) {
310         log.error(
311                 "Caught exception trying to save entry to MD-SAL",
312                 e);
313     }
314
315 }
316
317 @Override
318 public Future<RpcResult<VfLicenseModelUpdateOutput>> vfLicenseModelUpdate(VfLicenseModelUpdateInput input) {
319     final String SVC_OPERATION = "vf-license-model-update";
320
321     Properties parms = new Properties();
322
323     log.info( SVC_OPERATION +" called." );
324
325     if(input == null ) {
326         log.debug("exiting " +SVC_OPERATION+ " because of invalid input");
327         return null;
328     }
329
330     VfLicenseModelUpdateInputBuilder inputBuilder = new VfLicenseModelUpdateInputBuilder(input);
331     input = inputBuilder.build();
332
333     String errorMessage = "Success";
334     String errorCode = "200";
335
336     // If this artifact already exists, reject this update
337     if (artifactVersionExists(input.getArtifactName(), input.getArtifactVersion())) {
338         errorCode = "409";
339         errorMessage = "Artifact version already exists";
340     } else {
341         // Translate input object into SLI-consumable properties
342         log.info("Adding INPUT data for "+SVC_OPERATION+" input: " + input);
343         AsdcApiUtil.toProperties(parms, input);
344
345
346         // Call directed graph
347
348         Properties respProps = null;
349
350
351         AsdcApiSliClient sliClient = new AsdcApiSliClient();
352         try
353         {
354             if (sliClient.hasGraph("ASDC-API", SVC_OPERATION , null, "sync"))
355             {
356
357                 try
358                 {
359                     respProps = sliClient.execute("ASDC-API", SVC_OPERATION, null, "sync", parms);
360                 }
361                 catch (Exception e)
362                 {
363                     log.error("Caught exception executing service logic for "+ SVC_OPERATION, e);
364                 }
365             } else {
366                 errorMessage = "No service logic active for ASDC-API: '" + SVC_OPERATION + "'";
367                 errorCode = "503";
368             }
369         }
370         catch (Exception e)
371         {
372             errorCode = "500";
373             errorMessage = e.getMessage();
374             log.error("Caught exception looking for service logic", e);
375         }
376
377
378         if (respProps != null)
379         {
380             errorCode = respProps.getProperty("error-code");
381             errorMessage = respProps.getProperty("error-message", "");
382         }
383     }
384
385
386     if ("200".equals(errorCode)) {
387         log.info("ASDC update succeeded");
388
389         // Update config tree
390         applyVfLicenseModelUpdate(input);
391         addArtifactVersion(input.getArtifactName(), input.getArtifactVersion());
392
393     } else {
394         log.info("ASDC update failed ("+errorCode+" : "+errorMessage);
395     }
396
397     // Send response
398     VfLicenseModelUpdateOutputBuilder respBuilder = new VfLicenseModelUpdateOutputBuilder();
399     respBuilder.setAsdcApiResponseCode(errorCode);
400     if (errorMessage != null && errorMessage.length() > 0) {
401         respBuilder.setAsdcApiResponseText(errorMessage);
402     }
403
404     RpcResult<VfLicenseModelUpdateOutput> rpcResult;
405
406
407     rpcResult = RpcResultBuilder.<VfLicenseModelUpdateOutput> status(true).withResult(respBuilder.build()).build();
408
409
410
411     return Futures.immediateFuture(rpcResult);
412 }
413
414
415 }