1 import {DynamicInputsService} from "../../dynamicInputs.service";
2 import {ILevelNodeInfo} from "../basic.model.info";
3 import * as _ from "lodash";
4 import {VNFModel} from "../../../../../shared/models/vnfModel";
5 import {SharedTreeService} from "../../shared.tree.service";
6 import {VfModuleTreeNode} from "../../../../../shared/models/vfModuleTreeNode";
7 import {VfModuleInstance} from "../../../../../shared/models/vfModuleInstance";
8 import {VfModule} from "../../../../../shared/models/vfModule";
9 import {NgRedux} from "@angular-redux/store";
10 import {ITreeNode} from "angular-tree-component/dist/defs/api";
11 import {GenericFormPopupComponent, PopupType} from "../../../../../shared/components/genericFormPopup/generic-form-popup.component";
12 import {DialogService} from "ng2-bootstrap-modal";
13 import {VfModulePopuopService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popuop.service";
14 import {AppState} from "../../../../../shared/store/reducers";
15 import {MessageBoxData} from "../../../../../shared/components/messageBox/messageBox.data";
16 import {MessageBoxService} from "../../../../../shared/components/messageBox/messageBox.service";
17 import {AvailableNodeIcons} from "../../../available-models-tree/available-models-tree.service";
18 import {IframeService} from "../../../../../shared/utils/iframe.service";
19 import {deleteActionVfModuleInstance, deleteVFModuleField, removeVfModuleInstance, undoDeleteVfModuleInstance, undoUgradeVFModule, updateVFModulePosition, upgradeVFModule} from "../../../../../shared/storeUtil/utils/vfModule/vfModule.actions";
20 import {ComponentInfoService} from "../../../component-info/component-info.service";
21 import {ComponentInfoType} from "../../../component-info/component-info-model";
22 import {ModelInformationItem} from "../../../../../shared/components/model-information/model-information.component";
23 import {VfModuleUpgradePopupService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service";
24 import {FeatureFlagsService, Features} from "../../../../../shared/services/featureFlag/feature-flags.service";
25 import {Utils} from "../../../../../shared/utils/utils";
27 export class VFModuleModelInfo implements ILevelNodeInfo {
28 constructor(private _dynamicInputsService: DynamicInputsService,
29 private _sharedTreeService: SharedTreeService,
30 private _dialogService: DialogService,
31 private _vfModulePopupService: VfModulePopuopService,
32 private _vfModuleUpgradePopupService: VfModuleUpgradePopupService,
33 private _iframeService: IframeService,
34 private _featureFlagsService: FeatureFlagsService,
35 private _store: NgRedux<AppState>,
36 private _componentInfoService: ComponentInfoService) {
39 name: string = 'vfModules';
40 type: string = 'Module';
41 typeName: string = 'M';
42 componentInfoType = ComponentInfoType.VFMODULE;
44 /***********************************************************
45 * return if user should provide instance name or not.
46 * get info from parent (VNF)
47 * @param currentModel - current Model object
48 * @param parentModel - current parent Model object
49 ************************************************************/
50 isEcompGeneratedNaming(currentModel, parentModel): boolean {
51 const ecompGeneratedNaming = !_.isNil(parentModel.properties) ? parentModel.properties.ecomp_generated_naming : undefined;
52 return ecompGeneratedNaming === "true";
55 /***********************************************************
56 * return model dynamic inputs
57 * @param currentModel - current Model object
58 ************************************************************/
59 updateDynamicInputsDataFromModel = (currentModel): any => {
60 let displayInputs = _.isNil(currentModel) ? [] : currentModel.inputs;
61 return _.isEmpty(displayInputs) ? [] : this._dynamicInputsService.getArbitraryInputs(displayInputs);
64 /***********************************************************
65 * return vfModule model
66 * @param vfModuleModelId - current Model id
68 * @param serviceHierarchy - serviceHierarchy
69 ************************************************************/
70 getModel = (vfModuleModelId: string, instance, serviceHierarchy): any => {
71 if (!_.isNil(serviceHierarchy)) {
72 if (!_.isNil(serviceHierarchy[this.name]) && !_.isNil(serviceHierarchy[this.name][vfModuleModelId])) {
73 return serviceHierarchy[this.name][vfModuleModelId];
79 createNode(instance: VfModuleInstance, currentModel: VfModule, parentModel: VNFModel, modelName: string, index: number): VfModuleTreeNode {
80 let dynamicModelName = Object.keys(instance)[index];
81 instance = instance[Object.keys(instance)[index]];
82 const isEcompGeneratedNaming: boolean = this.isEcompGeneratedNaming(currentModel, parentModel);
84 const dynamicInputs = this.updateDynamicInputsDataFromModel(currentModel);
85 let newVfModule: VfModuleTreeNode = new VfModuleTreeNode(instance, currentModel, modelName, dynamicInputs, isEcompGeneratedNaming, dynamicModelName);
87 newVfModule.missingData = this._sharedTreeService.hasMissingData(instance, newVfModule.dynamicInputs, isEcompGeneratedNaming, []);
88 newVfModule.typeName = this.typeName;
89 newVfModule.menuActions = this.getMenuAction(<any>newVfModule, currentModel.uuid);
90 newVfModule.isFailed = _.isNil(instance.isFailed) ? false : instance.isFailed;
91 newVfModule.statusMessage = !_.isNil(instance.statusMessage) ? instance.statusMessage : "";
93 newVfModule = this._sharedTreeService.addingStatusProperty(newVfModule);
97 createInstanceTreeNode(instance: VfModuleInstance, currentModel: VfModule, parentModel: VNFModel, modelName: string): VfModuleTreeNode | VfModuleTreeNode[] {
98 let numberOfChilds = Object.keys(instance).length;
99 if (numberOfChilds > 1) {
100 let result: VfModuleTreeNode[] = [];
101 for (let i = 0; i < numberOfChilds; i++) {
102 result.push(this.createNode(instance, currentModel, parentModel, modelName, i));
106 return this.createNode(instance, currentModel, parentModel, modelName, 0);
110 /***********************************************************
111 * return next level object (null because is last level)
112 ************************************************************/
113 getNextLevelObject(): any {
117 getTooltip = (): string => 'VFmodule';
119 getType = (): string => 'VFmodule';
121 /***********************************************************
122 * return if instance has missing data
123 * @param instance - vnf instance
124 * @param dynamicInputs
125 * @param isEcompGeneratedNaming
126 ************************************************************/
127 hasMissingData(instance, dynamicInputs: any, isEcompGeneratedNaming: boolean): boolean {
128 return this._sharedTreeService.hasMissingData(instance, dynamicInputs, isEcompGeneratedNaming, []);
132 /***********************************************************
133 * return if instance has missing data
134 * @param node - VFModule node
135 * @param serviceModelId - current service id
136 ************************************************************/
137 onClickAdd(node: ITreeNode, serviceModelId: string): void {
138 const vnfStoreKey = this._sharedTreeService.getSelectedVNF() || this.getDefaultVNF(node.parent, serviceModelId);
140 this._dialogService.addDialog(GenericFormPopupComponent, {
141 type: PopupType.VF_MODULE,
143 serviceId: serviceModelId,
144 modelName: node.data.name,
145 vFModuleStoreKey: null,
146 vnfStoreKey: vnfStoreKey,
147 modelId: node.data.modelId,
148 type: node.data.type,
149 popupService: this._vfModulePopupService
155 let messageBoxData: MessageBoxData = new MessageBoxData(
156 "Select a parent", // modal title
157 "There are multiple instances on the right side that can contain this vf-module Please select the VNF instance, to add this vf-module to, on the right side and then click the + sign",
161 {text: "Close", size: "medium", closeModal: true}
163 MessageBoxService.openModal.next(messageBoxData);
167 getDefaultVNF(node: ITreeNode, serviceModelId: string): string {
168 let keys = _.keys(_.pickBy(this._store.getState().service.serviceInstance[serviceModelId].vnfs, vnf => {
169 return (vnf.originalName == node.data.name);
171 return keys.length === 1 ? this._store.getState().service.serviceInstance[serviceModelId].vnfs[keys[0]].vnfStoreKey : null;
174 /***********************************************************
175 * return number of existing instances (in all VNF's)
176 * @param node - VfModule node
177 * @param serviceModelId - current service id
178 ************************************************************/
179 getNodeCount(node: ITreeNode, serviceModelId: string): number {
180 let count: number = 0;
181 if (!_.isNil(this._store.getState().service.serviceInstance) && !_.isNil(this._store.getState().service.serviceInstance[serviceModelId])) {
182 const vnfs = this._store.getState().service.serviceInstance[serviceModelId].vnfs;
184 for (let vnfKey in vnfs) {
185 count += this.countNumberOfVFModule(vnfs[vnfKey], node);
193 countNumberOfVFModule(vnf, node): number {
195 for (let vfModuleKey in vnf['vfModules']) {
196 for (let vfModule in vnf['vfModules'][vfModuleKey]) {
197 if (vnf['vfModules'][vfModuleKey][vfModule]['modelInfo'].modelCustomizationId === node.data.modelUniqueId) {
198 const vfModuleObj = vnf['vfModules'][vfModuleKey][vfModule];
199 if (!(!_.isNil(vfModuleObj) && !_.isNil(vfModuleObj.action) && vfModuleObj.action.split('_').pop() === 'Delete')) count++;
206 getCountVFModuleOfSelectedVNF(node: ITreeNode, vnfStoreKey: string, serviceModelId: string): number {
207 let count: number = 0;
208 if (!_.isNil(this._store.getState().service.serviceInstance) && !_.isNil(this._store.getState().service.serviceInstance[serviceModelId])) {
209 const vnfs = this._store.getState().service.serviceInstance[serviceModelId].vnfs;
211 for (let vnfKey in vnfs) {
212 count += this.countNumberOfVFModule(vnfs[vnfKey], node);
220 /***********************************************************
221 * should show node icon
222 * @param node - current ITrees node
223 * @param serviceModelId - service id
224 ************************************************************/
225 showNodeIcons(node: ITreeNode, serviceModelId: string): AvailableNodeIcons {
226 const selectedVNF: string = this._sharedTreeService.getSelectedVNF();
228 return this.showVFModuleOnSelectedVNF(node, selectedVNF, serviceModelId);
230 const optionalSelected = this.getOptionalVNFs(serviceModelId, node.parent.data.name);
231 if (optionalSelected.length === 1) {
232 return this.showVFModuleOnSelectedVNF(node, optionalSelected[0].vnfStoreKey, serviceModelId);
234 return new AvailableNodeIcons(false, false);
240 showVFModuleOnSelectedVNF(node: ITreeNode, selectedVNF: string, serviceModelId: string): AvailableNodeIcons {
242 if (!_.isNil(this._store.getState().service.serviceInstance[serviceModelId].vnfs[selectedVNF]) && node.parent.data.name === this._store.getState().service.serviceInstance[serviceModelId].vnfs[selectedVNF].originalName) {
243 const existingVFModules = this.getCountVFModuleOfSelectedVNF(node, selectedVNF, serviceModelId);
244 const reachedLimit = this.isVFModuleReachedLimit(node, this._store.getState().service.serviceHierarchy, serviceModelId, existingVFModules);
245 const showAddIcon = this._sharedTreeService.shouldShowAddIcon() && !reachedLimit;
246 return new AvailableNodeIcons(showAddIcon, reachedLimit);
248 return new AvailableNodeIcons(false, false);
252 getOptionalVNFs(serviceUUID: string, vnfOriginalModelName: string): any[] {
254 if (!_.isNil(this._store.getState().service.serviceInstance) && !_.isNil(this._store.getState().service.serviceInstance[serviceUUID])) {
255 const serviceVNFsInstances = this._store.getState().service.serviceInstance[serviceUUID].vnfs;
256 for (let vnfKey in serviceVNFsInstances) {
257 if (serviceVNFsInstances[vnfKey].originalName === vnfOriginalModelName) {
258 serviceVNFsInstances[vnfKey].vnfStoreKey = vnfKey;
259 result.push(serviceVNFsInstances[vnfKey]);
267 /************************************************
268 return number of instances with action Delete
269 @type: vnfs networks, vngGroups (only vfModule)
270 @node : node model from the left tree
271 ************************************************/
272 getExistingInstancesWithDeleteMode(node, serviceModelId: string, selectedVNF: string): number {
273 const existingInstances = this._store.getState().service.serviceInstance[serviceModelId].vnfs[selectedVNF].vfModules;
275 const modelUuid = node.data.uuid;
277 if (!_.isNil(existingInstances)) {
278 for (let instanceKey in existingInstances) {
279 let size = Object.keys(existingInstances[instanceKey]).length;
280 for (let i = 0; i < size; i++) {
281 let vfModuleDynamicKey = Object.keys(existingInstances[instanceKey])[i];
282 if (!_.isNil(existingInstances[instanceKey][vfModuleDynamicKey].action)) {
283 if (existingInstances[instanceKey][vfModuleDynamicKey]['uuid'] === modelUuid && existingInstances[instanceKey][vfModuleDynamicKey].action.split('_').pop() === 'Delete') {
294 isVFModuleReachedLimit(node: any, serviceHierarchy: any, serviceModelId: string, currentNodeCount: number): boolean {
295 const flags = this._featureFlagsService.getAllFlags();
296 let vnfModules = serviceHierarchy[serviceModelId].vfModules;
297 const maxInstances = vnfModules[node.data.name]
298 ? Utils.getMaxVfModule(vnfModules[node.data.name].properties, flags)
300 if (_.isNil(maxInstances)) {
304 return !(maxInstances > currentNodeCount);
307 getMenuAction(node: ITreeNode, serviceModelId: string): { [methodName: string]: { method: Function, visible: Function, enable: Function } } {
310 method: (node, serviceModelId) => {
311 this._iframeService.addClassOpenModal('content');
312 this._dialogService.addDialog(GenericFormPopupComponent, {
313 type: PopupType.VF_MODULE,
315 serviceId: serviceModelId,
316 modelName: node.data.modelName,
317 vFModuleStoreKey: node.data.dynamicModelName,
318 vnfStoreKey: node.parent.data.vnfStoreKey,
319 modelId: node.data.modelId,
320 type: node.data.type,
321 popupService: this._vfModulePopupService
327 visible: (node) => this._sharedTreeService.shouldShowRemoveAndEdit(node),
328 enable: (node) => this._sharedTreeService.shouldShowRemoveAndEdit(node),
331 method: (node, serviceModelId) => {
332 let instance = this._store.getState().service.serviceInstance[serviceModelId].vnfs[node.parent.data.vnfStoreKey].vfModules[node.data.modelName][node.data.modelVersionId];
333 this._sharedTreeService.openAuditInfoModal(node, serviceModelId, instance, 'VFMODULE', this);
335 visible: (node) => this._sharedTreeService.shouldShowAuditInfo(node),
336 enable: (node) => this._sharedTreeService.shouldShowAuditInfo(node)
339 method: (node, serviceModelId) => this._store.dispatch(removeVfModuleInstance(node.data.modelName, serviceModelId, node.parent.data.modelName, node.parent.data.vnfStoreKey, node.data.dynamicModelName)),
340 visible: (node) => this._sharedTreeService.shouldShowRemoveAndEdit(node),
341 enable: (node) => this._sharedTreeService.shouldShowRemoveAndEdit(node),
344 method: (node, serviceModelId) => {
345 this._store.dispatch(deleteActionVfModuleInstance(node.data.dynamicModelName, node.parent.data.vnfStoreKey, serviceModelId))
347 visible: (node) => this._sharedTreeService.shouldShowDelete(node),
348 enable: (node) => this._sharedTreeService.shouldShowDelete(node)
351 method: (node, serviceModelId) => {
352 this._store.dispatch(undoDeleteVfModuleInstance(node.data.dynamicModelName, node.parent.data.vnfStoreKey, serviceModelId));
353 this._store.dispatch(deleteVFModuleField(node.data.modelName, node.parent.data.vnfStoreKey, node.data.servicedId ,node.data.dynamicModelName, 'retainAssignments'));
355 visible: (node) => this._sharedTreeService.shouldShowUndoDelete(node),
356 enable: (node, serviceModelId) => this._sharedTreeService.shouldShowUndoDelete(node) && this._sharedTreeService.shouldShowDelete(node.parent) && !this._sharedTreeService.isServiceOnDeleteMode(serviceModelId)
359 method: (node, serviceModelId) => {
360 this.upgradeVFM(serviceModelId, node);
362 visible: (node,serviceModelId) => {
363 return this._sharedTreeService.shouldShowUpgrade(node, serviceModelId);
365 enable: (node, serviceModelId) => {
366 return this._sharedTreeService.shouldShowUpgrade(node, serviceModelId);
370 method: (node, serviceModelId) => {
371 this._sharedTreeService.undoUpgradeBottomUp(node, serviceModelId);
372 this._store.dispatch(undoUgradeVFModule(node.data.modelName, node.parent.data.vnfStoreKey, serviceModelId, node.data.dynamicModelName));
375 return this._sharedTreeService.shouldShowUndoUpgrade(node);
378 return this._sharedTreeService.shouldShowUndoUpgrade(node);
384 private upgradeVFM(serviceModelId, node) {
385 if (FeatureFlagsService.getFlagState(Features.FLAG_2002_VFM_UPGRADE_ADDITIONAL_OPTIONS, this._store)) {
386 this._iframeService.addClassOpenModal('content');
387 this._dialogService.addDialog(GenericFormPopupComponent, {
388 type: PopupType.VF_MODULE_UPGRADE,
390 serviceId: serviceModelId,
391 modelName: node.data.modelName,
392 vFModuleStoreKey: node.data.dynamicModelName,
393 vnfStoreKey: node.parent.data.vnfStoreKey,
394 modelId: node.data.modelId,
395 type: node.data.type,
396 popupService: this._vfModuleUpgradePopupService,
397 vfModule : _.cloneDeep(node)
403 this._sharedTreeService.upgradeBottomUp(node, serviceModelId);
404 this._store.dispatch(upgradeVFModule(node.data.modelName, node.parent.data.vnfStoreKey, serviceModelId ,node.data.dynamicModelName));
408 updatePosition(that, node, instanceId, parentStoreKey): void {
409 that.store.dispatch(updateVFModulePosition(node, instanceId, parentStoreKey));
413 getNodePosition(instance, deepDynamicName): number {
414 return (!_.isNil(instance) && !_.isNil(instance[deepDynamicName])) ? instance[deepDynamicName].position : null;
417 getInfo(model, instance): ModelInformationItem[] {
418 const modelInformation = !_.isEmpty(model) && !_.isEmpty(model.properties) ? [
419 ModelInformationItem.createInstance("Base module", model.properties.baseModule),
420 ModelInformationItem.createInstance("Min instances", !_.isNull(model.properties.minCountInstances) ? String(model.properties.minCountInstances) : null),
421 this._sharedTreeService.createMaximumToInstantiateModelInformationItem(model),
422 ModelInformationItem.createInstance("Initial instances count", !_.isNull(model.properties.initialCount) ? String(model.properties.initialCount) : null)
425 const instanceInfo = [];
426 const result = [modelInformation, instanceInfo];
427 return _.uniq(_.flatten(result));