2 * ============LICENSE_START=======================================================
3 * ONAP : ccsdk features
4 * ================================================================================
5 * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property.
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.features.sdnr.wt.dataprovider.setup;
25 import java.io.FileNotFoundException;
26 import java.io.IOException;
27 import java.nio.charset.StandardCharsets;
28 import java.nio.file.Files;
29 import java.text.ParseException;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.List;
35 import org.json.JSONObject;
36 import org.onap.ccsdk.features.sdnr.wt.common.database.HtDatabaseClient;
37 import org.onap.ccsdk.features.sdnr.wt.common.database.SearchHit;
38 import org.onap.ccsdk.features.sdnr.wt.common.database.SearchResult;
39 import org.onap.ccsdk.features.sdnr.wt.common.database.config.HostInfo;
40 import org.onap.ccsdk.features.sdnr.wt.common.database.data.AliasesEntry;
41 import org.onap.ccsdk.features.sdnr.wt.common.database.data.AliasesEntryList;
42 import org.onap.ccsdk.features.sdnr.wt.common.database.data.EsVersion;
43 import org.onap.ccsdk.features.sdnr.wt.common.database.data.IndicesEntry;
44 import org.onap.ccsdk.features.sdnr.wt.common.database.data.IndicesEntryList;
45 import org.onap.ccsdk.features.sdnr.wt.common.database.requests.CreateAliasRequest;
46 import org.onap.ccsdk.features.sdnr.wt.common.database.requests.CreateIndexRequest;
47 import org.onap.ccsdk.features.sdnr.wt.common.database.requests.DeleteAliasRequest;
48 import org.onap.ccsdk.features.sdnr.wt.common.database.requests.DeleteIndexRequest;
49 import org.onap.ccsdk.features.sdnr.wt.common.database.responses.AcknowledgedResponse;
50 import org.onap.ccsdk.features.sdnr.wt.common.database.responses.GetInfoResponse;
51 import org.onap.ccsdk.features.sdnr.wt.common.database.responses.ListAliasesResponse;
52 import org.onap.ccsdk.features.sdnr.wt.common.database.responses.ListIndicesResponse;
53 import org.onap.ccsdk.features.sdnr.wt.dataprovider.setup.data.ComponentData;
54 import org.onap.ccsdk.features.sdnr.wt.dataprovider.setup.data.ComponentName;
55 import org.onap.ccsdk.features.sdnr.wt.dataprovider.setup.data.DataMigrationReport;
56 import org.onap.ccsdk.features.sdnr.wt.dataprovider.setup.data.DataContainer;
57 import org.onap.ccsdk.features.sdnr.wt.dataprovider.setup.data.Release;
58 import org.onap.ccsdk.features.sdnr.wt.dataprovider.setup.data.SearchHitConverter;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
62 public class DataMigrationProviderImpl implements DataMigrationProviderService {
64 private final Logger LOG = LoggerFactory.getLogger(DataMigrationProviderImpl.class);
66 private final HtDatabaseClient dbClient;
68 public DataMigrationProviderImpl(HostInfo[] hosts, String username, String password, boolean trustAll) {
69 this.dbClient = new HtDatabaseClient(hosts, username, password, trustAll);
73 public DataMigrationReport importData(String filename, boolean dryrun) throws Exception {
74 return this.importData(filename, dryrun, Release.CURRENT_RELEASE);
77 public DataMigrationReport importData(String filename, boolean dryrun, Release forRelease) throws Exception {
78 DataMigrationReport report = new DataMigrationReport();
79 File file = new File(filename);
82 report.error("file %s not found", filename);
85 throw new FileNotFoundException(filename);
87 DataContainer container = null;
89 container = DataContainer.load(file);
90 } catch (Exception e) {
92 report.error("problem loading file %s: %s", filename, e.getMessage());
95 throw new Exception("problem loading file " + filename, e);
97 ReleaseInformation ri = ReleaseInformation.getInstance(forRelease);
98 SearchHitConverter converter;
99 Set<ComponentName> components = ri.getComponents();
100 //for all db components of dest architecture
101 for (ComponentName component : components) {
102 //convert to ComponentData for current release with existing ComponentData of the container
103 converter = SearchHitConverter.Factory.getInstance(container.getRelease(), forRelease, component);
104 if (converter == null) {
107 ComponentData data = converter.convert(container);
109 String indexName = ri.getAlias(component);
110 String dataTypeName = ri.getDataType(component);
112 report.log("write %d entries into %s/%s", data.size(), indexName, dataTypeName);
114 LOG.debug("write {} entries into {}/{}", data.size(), indexName, dataTypeName);
116 for (SearchHit item : data) {
118 String id = this.dbClient.doWriteRaw(indexName, dataTypeName, item.getId(),
119 item.getSourceAsString());
120 if (!item.getId().equals(id)) {
121 LOG.warn("entry for {} with original id {} was written with another id {}",
122 component.getValue(), item.getId(), id);
128 report.error("unable to convert data for " + component.getValue() + " from version "
129 + container.getRelease().getValue() + " to " + forRelease.getValue() + "\n");
131 LOG.warn("unable to convert data for {} from version {} to {}", component.getValue(),
132 container.getRelease().getValue(), forRelease.getValue());
136 LOG.info("import of {} completed", filename);
138 report.log("import of %s completed", filename);
140 report.setCompleted(true);
147 * if file exists .1 (.n) will be created
151 public DataMigrationReport exportData(String filename) {
152 DataMigrationReport report = new DataMigrationReport();
154 DataContainer container = new DataContainer();
156 filename = this.checkFilenameForWrite(filename);
157 LOG.info("output will be written to {}", filename);
159 Release dbRelease = this.autoDetectRelease();
160 if(dbRelease==null) {
161 report.error("unbable to detect db release. is database initialized?");
164 ReleaseInformation ri = ReleaseInformation.getInstance(dbRelease);
165 boolean componentsSucceeded = true;
166 for(ComponentName c: ri.getComponents()) {
167 ComponentData data = new ComponentData(c);
168 SearchResult<SearchHit> result = this.dbClient.doReadAllJsonData(ri.getAlias(c),ri.getDataType(c),false);
169 data.addAll(result.getHits());
170 container.addComponent(c, data );
173 Files.write(new File(filename).toPath(), Arrays.asList(container.toJSON()), StandardCharsets.UTF_8);
174 report.setCompleted(componentsSucceeded);
175 } catch (IOException e) {
176 LOG.warn("problem writing data to {}: {}", filename, e);
181 private String checkFilenameForWrite(String filename) {
182 File f = new File(filename);
186 return this.checkFilenameForWrite(filename, 0);
189 private String checkFilenameForWrite(String filename, int apdx) {
190 File f = new File(String.format("$s.$d",filename,apdx));
194 return this.checkFilenameForWrite(filename, apdx + 1);
198 public Release getCurrentVersion() {
199 return Release.CURRENT_RELEASE;
203 public Release autoDetectRelease() {
204 EsVersion dbVersion = this.readActualVersion();
205 AliasesEntryList aliases = this.readAliases();
206 IndicesEntryList indices = this.readIndices();
210 List<Release> foundReleases = new ArrayList<Release>();
211 //if there are active aliases reduce indices to the active ones
212 if(aliases!=null && aliases.size()>0) {
213 indices = indices.subList(aliases.getLinkedIndices());
215 for(Release r:Release.values()) {
216 if(r.isDbInRange(dbVersion)) {
217 ReleaseInformation ri = ReleaseInformation.getInstance(r);
218 if(ri!=null && ri.containsIndices(indices)) {
219 foundReleases.add(r);
223 if (foundReleases.size() == 1) {
224 return foundReleases.get(0);
226 LOG.error("detect {} releases: {}. unable to detect for which one to do sth.",foundReleases.size(), foundReleases);
229 private EsVersion readActualVersion() {
231 GetInfoResponse response = this.dbClient.getInfo();
232 return response.getVersion();
233 } catch (Exception e) {
234 LOG.warn(e.getMessage());
239 private AliasesEntryList readAliases() {
240 AliasesEntryList entries = null;
242 ListAliasesResponse response = this.dbClient.getAliases();
243 entries = response.getEntries();
244 } catch (ParseException | IOException e) {
245 LOG.error(e.getMessage());
250 private IndicesEntryList readIndices() {
251 IndicesEntryList entries = null;
253 ListIndicesResponse response = this.dbClient.getIndices();
254 entries = response.getEntries();
255 } catch (ParseException | IOException e) {
256 LOG.error(e.getMessage());
262 public boolean initDatabase(Release release, int numShards, int numReplicas, String dbPrefix,
263 boolean forceRecreate,long timeoutms) {
265 this.dbClient.waitForYellowStatus(timeoutms);
267 EsVersion dbVersion = this.readActualVersion();
268 if (dbVersion == null) {
271 if (!release.isDbInRange(dbVersion)) {
272 LOG.warn("db version {} maybe not compatible with release {}", dbVersion, release);
276 this.clearDatabase(release, dbPrefix,0);
278 ReleaseInformation ri = ReleaseInformation.getInstance(release);
279 AliasesEntryList aliases = this.readAliases();
280 IndicesEntryList indices = this.readIndices();
281 if (aliases == null || indices == null) {
284 AcknowledgedResponse response = null;
285 if(!ri.runPreInitCommands(this.dbClient)) {
288 for (ComponentName component : ri.getComponents()) {
290 if (ri.hasOwnDbIndex(component)) {
291 //check if index already exists
292 String indexName = ri.getIndex(component, dbPrefix);
293 String aliasName = ri.getAlias(component, dbPrefix);
294 if (indices.findByIndex(indexName) == null) {
295 LOG.info("creating index for {}", component);
296 CreateIndexRequest request = new CreateIndexRequest(ri.getIndex(component, dbPrefix));
297 request.mappings(new JSONObject(ri.getDatabaseMapping(component)));
298 request.settings(new JSONObject(ri.getDatabaseSettings(component, numShards, numReplicas)));
299 response = this.dbClient.createIndex(request);
300 LOG.info(response.isAcknowledged() ? "succeeded" : "failed");
302 LOG.info("index {} for {} already exists", indexName, component);
304 //check if alias already exists
305 if (aliases.findByAlias(aliasName) == null) {
306 LOG.info("creating alias for {}", component);
307 response = this.dbClient.createAlias(new CreateAliasRequest(indexName, aliasName));
308 LOG.info(response.isAcknowledged() ? "succeeded" : "failed");
310 LOG.info("alias {} for index {} for {} already exists", aliasName, indexName, component);
313 } catch (IOException e) {
314 LOG.error(e.getMessage());
318 if(!ri.runPostInitCommands(this.dbClient)) {
325 public boolean clearDatabase(Release release, String dbPrefix, long timeoutms) {
328 this.dbClient.waitForYellowStatus(timeoutms);
331 AliasesEntryList entries = this.readAliases();
332 if (entries == null) {
335 ReleaseInformation ri = ReleaseInformation.getInstance(release);
336 AcknowledgedResponse response;
337 if (entries.size() <= 0) {
338 LOG.info("no aliases to clear");
340 //check for every component of release if alias exists
341 for (ComponentName component : ri.getComponents()) {
342 String aliasToDelete = ri.getAlias(component, dbPrefix);
343 AliasesEntry entryToDelete = entries.findByAlias(aliasToDelete);
344 if (entryToDelete != null) {
346 LOG.info("deleting alias {} for index {}", entryToDelete.getAlias(), entryToDelete.getIndex());
347 response=this.dbClient.deleteAlias(
348 new DeleteAliasRequest(entryToDelete.getIndex(), entryToDelete.getAlias()));
349 LOG.info(response.isResponseSucceeded()?"succeeded":"failed");
350 } catch (IOException e) {
351 LOG.error(e.getMessage());
357 IndicesEntryList entries2 = this.readIndices();
358 if (entries2 == null) {
361 if (entries2.size() <= 0) {
362 LOG.info("no indices to clear");
364 //check for every component of release if index exists
365 for (ComponentName component : ri.getComponents()) {
366 String indexToDelete = ri.getIndex(component, dbPrefix);
367 IndicesEntry entryToDelete = entries2.findByIndex(indexToDelete);
368 if (entryToDelete != null) {
370 LOG.info("deleting index {}", entryToDelete.getName());
371 response=this.dbClient.deleteIndex(new DeleteIndexRequest(entryToDelete.getName()));
372 LOG.info(response.isResponseSucceeded()?"succeeded":"failed");
373 } catch (IOException e) {
374 LOG.error(e.getMessage());