summaryrefslogtreecommitdiffstats
path: root/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/CompositionBusinessLogic.java
blob: 27910282e0795e139e85d40b7da3aceaf4d3c2fc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
package org.onap.sdc.dcae.composition.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import org.onap.sdc.common.onaplog.Enums.LogLevel;
import org.onap.sdc.dcae.composition.restmodels.CreateMcResponse;
import org.onap.sdc.dcae.composition.restmodels.VfcmtData;
import org.onap.sdc.dcae.composition.restmodels.sdc.Artifact;
import org.onap.sdc.dcae.composition.restmodels.sdc.ResourceDetailed;
import org.onap.sdc.dcae.composition.restmodels.sdc.ResourceInstance;
import org.onap.sdc.dcae.composition.restmodels.sdc.ServiceDetailed;
import org.onap.sdc.dcae.composition.util.DcaeBeConstants;
import org.onap.sdc.dcae.enums.ArtifactType;
import org.onap.sdc.dcae.enums.LifecycleOperationType;
import org.onap.sdc.dcae.errormng.ActionStatus;
import org.onap.sdc.dcae.errormng.ErrConfMgr;
import org.onap.sdc.dcae.utils.Normalizers;
import org.onap.sdc.dcae.utils.SdcRestClientUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.Base64Utils;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@Component
public class CompositionBusinessLogic extends BaseBusinessLogic {

    private static final String CREATE_DESC = "creating new artifact blueprint on the service vfi";
    private static final String UPDATE_DESC = "updating artifact blueprint on the service vfi";

	//canvas cdump as simple string
    public Artifact getComposition(String vfcmtUuid, String requestId) {
		ResourceDetailed vfcmt = sdcRestClient.getResource(vfcmtUuid, requestId);
		return fetchCdump(vfcmt, requestId);
	}

	//cdump and vfcmt for monitoring configuration
    public CreateMcResponse getDataAndComposition(String vfcmtUuid, String requestId) throws IOException {
        ResourceDetailed vfcmt = sdcRestClient.getResource(vfcmtUuid, requestId);
        Artifact composition = fetchCdump(vfcmt, requestId);
        return buildVfcmtAndCdumpResponse(new VfcmtData(vfcmt), composition.getPayloadData());
    }

    // 1806 US399018 update composition - assumes an artifact already exists (create mode flag for backward compatibility)
    public ResponseEntity saveComposition(String userId, String vfcmtUuid, String updatedPayload, String requestId, boolean allowCreateNew) {

        boolean undoCheckoutOnFailure = false;
        ResourceDetailed vfcmt = null;
        try {
            vfcmt = sdcRestClient.getResource(vfcmtUuid, requestId);
            Artifact artifactData = findCdumpArtifactData(vfcmt);
            if (null == artifactData && !allowCreateNew) {
                debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Composition not found on vfcmt {}", vfcmt.getUuid());
                return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.MISSING_TOSCA_FILE, "", vfcmt.getName());
            }
            if (DcaeBeConstants.LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT != DcaeBeConstants.LifecycleStateEnum.findState(vfcmt.getLifecycleState())) {
                vfcmt = sdcRestClient.changeResourceLifecycleState(userId, vfcmt.getUuid(), LifecycleOperationType.CHECKOUT.name(), null, requestId);
                undoCheckoutOnFailure = true;
            }
            if (null == artifactData) {
                artifactData = SdcRestClientUtils.generateDeploymentArtifact("creating composition file", DcaeBeConstants.Composition.fileNames.COMPOSITION_YML, ArtifactType.DCAE_TOSCA.name(), "composition", updatedPayload.getBytes());
                debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "creating new composition artifact for MC: {}", vfcmt.getUuid());
                sdcRestClient.createResourceArtifact(userId, vfcmt.getUuid(), artifactData, requestId);
            } else {
                debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "updating composition artifact for MC: {}", vfcmt.getUuid());
                artifactData.setDescription("updating composition");
                artifactData.setPayloadData(Base64Utils.encodeToString(updatedPayload.getBytes()));
                sdcRestClient.updateResourceArtifact(userId, vfcmt.getUuid(), artifactData, requestId);
            }
            return new ResponseEntity<>(sdcRestClient.changeResourceLifecycleState(userId, vfcmt.getUuid(), LifecycleOperationType.CHECKIN.name(), "auto checkin after save composition", requestId), HttpStatus.OK);
        } catch (Exception e) {
            errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Save composition failed: {}", e);
            if(undoCheckoutOnFailure) {
                rollBack(userId, vfcmt, requestId);
            }
            return ErrConfMgr.INSTANCE.handleException(e, ErrConfMgr.ApiType.SAVE_CDUMP);
        }
    }

    // 1810 US436244 Update MC table version representations and actions
    public ResponseEntity overwriteRevertedMC(String userId, String vfcmtUuid, String revertedUuid, String updatedPayload, String requestId) {
    	try {
    		cloneArtifactsToRevertedMC(userId, vfcmtUuid, revertedUuid, requestId, false);
		}  catch (Exception e) {
		    errLogger.log(LogLevel.ERROR, this.getClass().getName(), "clone action failed: {}", e);
			return ErrConfMgr.INSTANCE.handleException(e, ErrConfMgr.ApiType.SAVE_CDUMP);
		}
    	return saveComposition(userId, revertedUuid, updatedPayload, requestId, false);
	}

    Artifact submitComposition(String userId, String context, VfcmtData vfcmtData, String resultBlueprintCreation, String requestId) throws JsonProcessingException {

        // get service / find vfi
        ServiceDetailed service = sdcRestClient.getAssetMetadata(context, vfcmtData.getServiceUuid(), requestId);
        ResourceInstance vfi = findVfiOnService(service, vfcmtData.getVfiName());
        if(null == vfi){
            errLogger.log(LogLevel.ERROR, this.getClass().getName(), "VF instance {} not found on service {}", vfcmtData.getVfiName(), vfcmtData.getServiceUuid());
            return null;
        }
        // look for existing blueprint details
		//1802,1806 US412711 - Allow multiple BP from the same flow type on a single VFi - identify existing blueprint by name - for backward compatibility
		String artifactName = generateBlueprintFileName(vfcmtData.getFlowType(), vfcmtData.getName());
        Artifact blueprintArtifact = findExistingBlueprint(vfi, artifactName);

        // save blueprint as instance artifact
        // create mode
        if(null == blueprintArtifact) {
			String artifactLabel = "blueprint-".concat(vfcmtData.getFlowType()).concat("-").concat(Normalizers.normalizeComponentName(vfcmtData.getName()));
            debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Service {} does not consist {} ----> createMode", vfcmtData.getServiceUuid(), artifactLabel);
            blueprintArtifact = SdcRestClientUtils.generateDeploymentArtifact(CREATE_DESC, artifactName , ArtifactType.DCAE_INVENTORY_BLUEPRINT.name(), artifactLabel, resultBlueprintCreation.getBytes());
            blueprintArtifact = sdcRestClient.createInstanceArtifact(userId, context, vfcmtData.getServiceUuid(), Normalizers.normalizeComponentInstanceName(vfcmtData.getVfiName()), blueprintArtifact, requestId);
            // update mode
        } else {
            blueprintArtifact = updateBlueprint(userId, context, vfcmtData.getServiceUuid(), vfcmtData.getVfiName(), blueprintArtifact, resultBlueprintCreation, requestId);
            // TODO should this be safe?
            //1806 US390018 - remove reference to previous version
            deletePreviousReference(userId, context, service, vfcmtData, requestId);
        }
        //1806 US374593 - certify VFCMT after BP generation
        certifyVfcmt(userId, vfcmtData, requestId);
        return blueprintArtifact;
    }


    private Artifact updateBlueprint(String userId, String context, String serviceUuid, String vfiName, Artifact blueprintArtifact, String payload, String requestId) throws JsonProcessingException {
        debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Found that service {} already consist of {} ----> updateMode", serviceUuid, blueprintArtifact.getArtifactLabel());
        blueprintArtifact.setDescription(UPDATE_DESC);
        blueprintArtifact.setPayloadData(Base64Utils.encodeToString(payload.getBytes()));
        return sdcRestClient.updateInstanceArtifact(userId, context, serviceUuid, Normalizers.normalizeComponentInstanceName(vfiName), blueprintArtifact, requestId);
    }

	private Artifact findExistingBlueprint(ResourceInstance vfi, String artifactName) {
		return CollectionUtils.isEmpty(vfi.getArtifacts()) ? null : vfi.getArtifacts().stream()
				.filter(p -> Normalizers.normalizeArtifactLabel(artifactName).equals(Normalizers.normalizeArtifactLabel(p.getArtifactName())))
				.findAny()
				.orElse(null);
	}

    //TODO should this be safe or throw?
    private void deletePreviousReference(String userId, String context, ServiceDetailed service, VfcmtData newReferencedMc, String requestId) {
    	String normalizedInstanceName = Normalizers.normalizeComponentInstanceName(newReferencedMc.getVfiName());
        List<String> vfiRefs = sdcRestClient.getMonitoringReferences(context, service.getUuid(), service.getVersion(), requestId).get(normalizedInstanceName);
        if (null != vfiRefs && 1 < vfiRefs.size()) {
            debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Found {} external monitoring references for vfi {} on service {}:{}", vfiRefs.size(), newReferencedMc.getVfiName(), service.getUuid(), vfiRefs);
            Collections.synchronizedList(vfiRefs).parallelStream()
                    .filter(p -> !newReferencedMc.getUuid().equals(p) && !p.endsWith(REVERTED_REF))
                    .filter(p -> newReferencedMc.getInvariantUUID().equals(sdcRestClient.getResource(p, requestId).getInvariantUUID()))
                    .forEach(id -> sdcRestClient.deleteExternalMonitoringReference(userId, context, service.getUuid(), normalizedInstanceName, id, requestId));
        } else {
			// this shouldn't happen - there should be at least two references registered to the vfi
            debugLogger.log(LogLevel.WARN, this.getClass().getName(), "Sum Ting Wong. References found: {}", vfiRefs);
        }
    }

    private void certifyVfcmt(String userId, VfcmtData vfcmt, String requestId) {
        String state = vfcmt.getLifecycleState();
        if(null == state) {
            debugLogger.log(LogLevel.ERROR, this.getClass().getName(), "Couldn't read Vfcmt lifecycle state");
            return;
        }
        DcaeBeConstants.LifecycleStateEnum lifeCycleState = DcaeBeConstants.LifecycleStateEnum.findState(state);
        if(null == lifeCycleState) {
            debugLogger.log(LogLevel.ERROR, this.getClass().getName(), "Undefined lifecycle state: {}", state);
            return;
        }
        try{
            switch (lifeCycleState){
            case NOT_CERTIFIED_CHECKOUT:
                sdcRestClient.changeResourceLifecycleState(userId, vfcmt.getUuid(), LifecycleOperationType.CHECKIN.name(), "check in VFCMT after blueprint successful submission", requestId);
                sdcRestClient.changeResourceLifecycleState(userId, vfcmt.getUuid(), LifecycleOperationType.CERTIFY.name(), "certify VFCMT after blueprint successful submission", requestId);
                break;
            case NOT_CERTIFIED_CHECKIN:
                sdcRestClient.changeResourceLifecycleState(userId, vfcmt.getUuid(), LifecycleOperationType.CERTIFY.name(), "certify VFCMT after blueprint successful submission", requestId);
                break;
            default:
            }
        }
        catch (Exception e){
            //informative only. no message to user (TBA)
            debugLogger.log(LogLevel.ERROR, this.getClass().getName(), "Error occurred during vfcmt lifecycle operation: {}", e);
        }
    }

}