Merge "Replace deprecated APIs with newer one"
[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 AT&T 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.NotificationPublishService;
32 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
33 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
34 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
35 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
36 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
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 Logger LOG = LoggerFactory.getLogger(AsdcApiProvider.class);
99
100     private static final String ACTIVE_VERSION = "active";
101
102     private static final String APPLICATION_NAME = "asdcApi";
103
104     private final ExecutorService executor;
105     protected DataBroker dataBroker;
106     protected NotificationPublishService notificationService;
107     protected RpcProviderRegistry rpcRegistry;
108     private final AsdcApiSliClient asdcApiSliClient;
109
110     protected BindingAwareBroker.RpcRegistration<ASDCAPIService> rpcRegistration;
111
112     public AsdcApiProvider(final DataBroker dataBroker,
113                            final NotificationPublishService notificationPublishService,
114                            final RpcProviderRegistry rpcProviderRegistry,
115                            final AsdcApiSliClient asdcApiSliClient) {
116
117         LOG.info("Creating provider for {}", APPLICATION_NAME);
118         executor = Executors.newFixedThreadPool(1);
119         this.dataBroker = dataBroker;
120         notificationService = notificationPublishService;
121         rpcRegistry = rpcProviderRegistry;
122         this.asdcApiSliClient= asdcApiSliClient;
123         initialize();
124     }
125
126     public void initialize(){
127         LOG.info("Initializing {} for {}", this.getClass().getName(), APPLICATION_NAME);
128
129         createContainers();
130
131         if (rpcRegistration == null) {
132             if (rpcRegistry != null) {
133                 rpcRegistration = rpcRegistry.addRpcImplementation(
134                         ASDCAPIService.class, this);
135                 LOG.info("Initialization complete for {}", APPLICATION_NAME);
136             } else {
137                 LOG.warn("Error initializing {} : rpcRegistry unset", APPLICATION_NAME);
138             }
139         }
140     }
141
142     private void createContainers() {
143
144         if (dataBroker != null) {
145         final WriteTransaction t = dataBroker.newReadWriteTransaction();
146
147         // Create the vf-model-license-versions and artifacts containers
148         t.merge(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(VfLicenseModelVersions.class),
149         new VfLicenseModelVersionsBuilder().build());
150
151         t.merge(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(Artifacts.class), new ArtifactsBuilder().build());
152
153
154         try {
155             CheckedFuture<Void, TransactionCommitFailedException> checkedFuture = t.submit();
156             checkedFuture.get();
157             LOG.info("Create Containers succeeded!: ");
158
159         } catch (InterruptedException | ExecutionException e) {
160             LOG.error("Create Containers Failed: " + e);
161             e.printStackTrace();
162         }
163         } else {
164             LOG.warn("createContainers : cannot find dataBroker to create containers");
165         }
166     }
167     protected void initializeChild() {
168         //Override if you have custom initialization intelligence
169     }
170
171     @Override
172     public void close() throws Exception {
173         LOG.info( "Closing provider for " + APPLICATION_NAME);
174         executor.shutdown();
175         rpcRegistration.close();
176         LOG.info( "Successfully closed provider for " + APPLICATION_NAME);
177     }
178
179     protected boolean artifactVersionExists(String aName, String aVersion) {
180         InstanceIdentifier artifactInstanceId =
181                 InstanceIdentifier.<Artifacts>builder(Artifacts.class)
182                 .child(Artifact.class, new ArtifactKey(aName, aVersion)).build();
183         ReadOnlyTransaction readTx = dataBroker.newReadOnlyTransaction();
184         Optional<Artifact> data = null;
185         try {
186             data = (Optional<Artifact>) readTx.read(LogicalDatastoreType.CONFIGURATION, artifactInstanceId).get();
187         } catch (InterruptedException | ExecutionException e) {
188             LOG.error("Caught Exception reading MD-SAL for ["+aName+","+ aVersion+"] " ,e);
189             return false;
190
191         }
192
193         if (data.isPresent()) {
194             return true;
195         } else {
196             return false;
197         }
198     }
199
200     protected void addArtifactVersion(String aName, String aVersion) {
201
202
203         try {
204             ArtifactBuilder aBuilder = new ArtifactBuilder();
205
206             aBuilder.setArtifactName(aName);
207             aBuilder.setArtifactVersion(aVersion);
208
209             Artifact artifact = aBuilder.build();
210
211             InstanceIdentifier.InstanceIdentifierBuilder<Artifact> aIdBuilder = InstanceIdentifier
212                     .<Artifacts> builder(Artifacts.class)
213                     .child(Artifact.class, artifact.getKey());
214
215             InstanceIdentifier<Artifact> path = aIdBuilder.build();
216
217             WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
218
219             tx.merge(LogicalDatastoreType.CONFIGURATION, path,
220                     artifact);
221             tx.submit().checkedGet();
222         } catch (Exception e) {
223             LOG.error("Caught exception trying to add artifact entry", e);
224         }
225
226     }
227
228
229     private void applyVfLicenseModelUpdate(VfLicenseModelUpdateInput input) {
230
231     String aName = input.getArtifactName();
232     String aVersion = input.getArtifactVersion();
233     VfLicenseModel vfLicenseModel = input.getVfLicenseModel();
234
235
236     // Add new version (version = artifact-version)
237     try {
238
239         VfLicenseModelVersionBuilder vBuilder = new VfLicenseModelVersionBuilder();
240         vBuilder.setArtifactName(aName);
241         vBuilder.setArtifactVersion(aVersion);
242         vBuilder.setVfLicenseModel(vfLicenseModel);
243
244         VfLicenseModelVersion version = vBuilder.build();
245
246         InstanceIdentifier.InstanceIdentifierBuilder<VfLicenseModelVersion> versionIdBuilder = InstanceIdentifier
247                 .<VfLicenseModelVersions> builder(VfLicenseModelVersions.class)
248                 .child(VfLicenseModelVersion.class, version.getKey());
249
250         InstanceIdentifier<VfLicenseModelVersion> path = versionIdBuilder.build();
251
252         WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
253   tx.merge(LogicalDatastoreType.CONFIGURATION, path,
254                 version);
255         tx.submit().checkedGet();
256     } catch (Exception e) {
257         LOG.error(
258                 "Caught exception trying to save entry to MD-SAL",
259                 e);
260     }
261
262
263     // Add "active" version (version = "active")
264     try {
265
266         VfLicenseModelVersionBuilder vBuilder = new VfLicenseModelVersionBuilder();
267         vBuilder.setArtifactName(aName);
268         vBuilder.setArtifactVersion(ACTIVE_VERSION);
269         vBuilder.setVfLicenseModel(vfLicenseModel);
270
271         VfLicenseModelVersion version = vBuilder.build();
272         InstanceIdentifier.InstanceIdentifierBuilder<VfLicenseModelVersion> versionIdBuilder = InstanceIdentifier
273                 .<VfLicenseModelVersions> builder(VfLicenseModelVersions.class)
274                 .child(VfLicenseModelVersion.class, version.getKey());
275
276         InstanceIdentifier<VfLicenseModelVersion> path = versionIdBuilder.build();
277
278         WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
279
280         tx.merge(LogicalDatastoreType.CONFIGURATION, path,
281                 version);
282         tx.submit().checkedGet();
283     } catch (Exception e) {
284         LOG.error(
285                 "Caught exception trying to save entry to MD-SAL",
286                 e);
287     }
288
289 }
290
291 @Override
292 public Future<RpcResult<VfLicenseModelUpdateOutput>> vfLicenseModelUpdate(VfLicenseModelUpdateInput input) {
293     final String SVC_OPERATION = "vf-license-model-update";
294
295     Properties parms = new Properties();
296
297     LOG.info( SVC_OPERATION +" called." );
298
299     if(input == null ) {
300         LOG.debug("exiting " +SVC_OPERATION+ " because of invalid input");
301         return null;
302     }
303
304     VfLicenseModelUpdateInputBuilder inputBuilder = new VfLicenseModelUpdateInputBuilder(input);
305     input = inputBuilder.build();
306
307     String errorMessage = "Success";
308     String errorCode = "200";
309
310     // If this artifact already exists, reject this update
311     if (artifactVersionExists(input.getArtifactName(), input.getArtifactVersion())) {
312         errorCode = "409";
313         errorMessage = "Artifact version already exists";
314     } else {
315         // Translate input object into SLI-consumable properties
316         LOG.info("Adding INPUT data for "+SVC_OPERATION+" input: " + input);
317         AsdcApiUtil.toProperties(parms, input);
318
319
320         // Call directed graph
321         Properties respProps = null;
322         try
323         {
324             if (asdcApiSliClient.hasGraph("ASDC-API", SVC_OPERATION , null, "sync"))
325             {
326
327                 try
328                 {
329                     respProps = asdcApiSliClient.execute("ASDC-API", SVC_OPERATION, null, "sync", parms);
330                 }
331                 catch (Exception e)
332                 {
333                     LOG.error("Caught exception executing service logic for "+ SVC_OPERATION, e);
334                 }
335             } else {
336                 errorMessage = "No service logic active for ASDC-API: '" + SVC_OPERATION + "'";
337                 errorCode = "503";
338             }
339         }
340         catch (Exception e)
341         {
342             errorCode = "500";
343             errorMessage = e.getMessage();
344             LOG.error("Caught exception looking for service logic", e);
345         }
346
347
348         if (respProps != null)
349         {
350             errorCode = respProps.getProperty("error-code");
351             errorMessage = respProps.getProperty("error-message", "");
352         }
353     }
354
355
356     if ("200".equals(errorCode)) {
357         LOG.info("ASDC update succeeded");
358
359         // Update config tree
360         applyVfLicenseModelUpdate(input);
361         addArtifactVersion(input.getArtifactName(), input.getArtifactVersion());
362
363     } else {
364         LOG.info("ASDC update failed ("+errorCode+" : "+errorMessage);
365     }
366
367     // Send response
368     VfLicenseModelUpdateOutputBuilder respBuilder = new VfLicenseModelUpdateOutputBuilder();
369     respBuilder.setAsdcApiResponseCode(errorCode);
370     if (errorMessage != null && errorMessage.length() > 0) {
371         respBuilder.setAsdcApiResponseText(errorMessage);
372     }
373
374     RpcResult<VfLicenseModelUpdateOutput> rpcResult;
375
376
377     rpcResult = RpcResultBuilder.<VfLicenseModelUpdateOutput> status(true).withResult(respBuilder.build()).build();
378
379
380
381     return Futures.immediateFuture(rpcResult);
382 }
383
384
385 }