Visualization of the VF Module Sequencing
[vid.git] / vid-webpack-master / src / app / drawingBoard / service-planning / objectsToTree / models / vfModule / vfModule.model.info.ts
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 {
12   GenericFormPopupComponent,
13   PopupType
14 } from "../../../../../shared/components/genericFormPopup/generic-form-popup.component";
15 import {DialogService} from "ng2-bootstrap-modal";
16 import {VfModulePopupService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popup.service";
17 import {AppState} from "../../../../../shared/store/reducers";
18 import {MessageBoxData} from "../../../../../shared/components/messageBox/messageBox.data";
19 import {MessageBoxService} from "../../../../../shared/components/messageBox/messageBox.service";
20 import {AvailableNodeIcons} from "../../../available-models-tree/available-models-tree.service";
21 import {IframeService} from "../../../../../shared/utils/iframe.service";
22 import {
23   deleteActionVfModuleInstance,
24   deleteVFModuleField,
25   pauseActionVFModuleInstance,
26   removePauseActionVFModuleInstance,
27   removeVfModuleInstance,
28   undoDeleteVfModuleInstance,
29   undoUgradeVFModule,
30   updateVFModulePosition,
31   upgradeVFModule
32 } from "../../../../../shared/storeUtil/utils/vfModule/vfModule.actions";
33 import {ComponentInfoService} from "../../../component-info/component-info.service";
34 import {ComponentInfoType} from "../../../component-info/component-info-model";
35 import {ModelInformationItem} from "../../../../../shared/components/model-information/model-information.component";
36 import {VfModuleUpgradePopupService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service";
37 import {FeatureFlagsService, Features} from "../../../../../shared/services/featureFlag/feature-flags.service";
38 import {Utils} from "../../../../../shared/utils/utils";
39
40 export class VFModuleModelInfo implements ILevelNodeInfo {
41   constructor(private _dynamicInputsService: DynamicInputsService,
42               private _sharedTreeService: SharedTreeService,
43               private _dialogService: DialogService,
44               private _vfModulePopupService: VfModulePopupService,
45               private _vfModuleUpgradePopupService: VfModuleUpgradePopupService,
46               private _iframeService: IframeService,
47               private _featureFlagsService: FeatureFlagsService,
48               private _store: NgRedux<AppState>,
49               private _componentInfoService: ComponentInfoService) {
50   }
51
52   name: string = 'vfModules';
53   type: string = 'Module';
54   typeName: string = 'M';
55   componentInfoType = ComponentInfoType.VFMODULE;
56
57   /***********************************************************
58    * return if user should provide instance name or not.
59    *        get info from parent (VNF)
60    * @param currentModel - current Model object
61    * @param parentModel - current parent Model object
62    ************************************************************/
63   isEcompGeneratedNaming(currentModel, parentModel): boolean {
64     const ecompGeneratedNaming = !_.isNil(parentModel.properties) ? parentModel.properties.ecomp_generated_naming : undefined;
65     return ecompGeneratedNaming === "true";
66   }
67
68   /***********************************************************
69    * return model dynamic inputs
70    * @param currentModel - current Model object
71    ************************************************************/
72   updateDynamicInputsDataFromModel = (currentModel): any => {
73     let displayInputs = _.isNil(currentModel) ? [] : currentModel.inputs;
74     return _.isEmpty(displayInputs) ? [] : this._dynamicInputsService.getArbitraryInputs(displayInputs);
75   };
76
77   /***********************************************************
78    * return vfModule model
79    * @param instanceModel - The model of the instance (usually extracted from
80    *        serviceHierarchy store)
81    ************************************************************/
82   getModel = (instanceModel: any): Partial<VfModule> => {
83     if (!_.isNil(instanceModel)) {
84       return new VfModule(instanceModel, this._featureFlagsService.getAllFlags());
85     }
86     return {};
87   };
88
89   createNode(instance: VfModuleInstance, currentModel: VfModule, parentModel: VNFModel, modelName: string, index: number, serviceModelId: string): VfModuleTreeNode {
90     let dynamicModelName = Object.keys(instance)[index];
91     instance = instance[Object.keys(instance)[index]];
92     const isEcompGeneratedNaming: boolean = this.isEcompGeneratedNaming(currentModel, parentModel);
93
94     const dynamicInputs = this.updateDynamicInputsDataFromModel(currentModel);
95     let newVfModule: VfModuleTreeNode = new VfModuleTreeNode(instance, currentModel, modelName, dynamicInputs, isEcompGeneratedNaming, dynamicModelName);
96
97     newVfModule.missingData = this._sharedTreeService.hasMissingData(instance, newVfModule.dynamicInputs, isEcompGeneratedNaming, []);
98     newVfModule.typeName = this.typeName;
99     newVfModule.menuActions = this.getMenuAction(<any>newVfModule, serviceModelId);
100     newVfModule.isFailed = _.isNil(instance.isFailed) ? false : instance.isFailed;
101     newVfModule.statusMessage = !_.isNil(instance.statusMessage) ? instance.statusMessage : "";
102     newVfModule.pauseInstantiation = instance.pauseInstantiation;
103     newVfModule.position = instance.position;
104     newVfModule = this._sharedTreeService.addingStatusProperty(newVfModule);
105     return newVfModule;
106   }
107
108   createInstanceTreeNode(instance: any, model: any, parentModel: any, storeKey: string, serviceModelId: string): any {
109     let numberOfChilds = Object.keys(instance).length;
110     if (numberOfChilds > 1) {
111       let result: VfModuleTreeNode[] = [];
112       for (let i = 0; i < numberOfChilds; i++) {
113         result.push(this.createNode(instance, model, parentModel, storeKey, i, serviceModelId));
114       }
115       return result;
116     } else {
117       return this.createNode(instance, model, parentModel, storeKey, 0, serviceModelId);
118     }
119   }
120
121   /***********************************************************
122    * return next level object (null because is last level)
123    ************************************************************/
124   getNextLevelObject(): any {
125     return null;
126   }
127
128   getTooltip = (): string => 'VFmodule';
129
130   getType = (): string => 'VFmodule';
131
132   /***********************************************************
133    * return if instance has missing data
134    * @param instance - vnf instance
135    * @param dynamicInputs
136    * @param isEcompGeneratedNaming
137    ************************************************************/
138   hasMissingData(instance, dynamicInputs: any, isEcompGeneratedNaming: boolean): boolean {
139     return this._sharedTreeService.hasMissingData(instance, dynamicInputs, isEcompGeneratedNaming, []);
140   }
141
142
143   /***********************************************************
144    * return if instance has missing data
145    * @param node - VFModule node
146    * @param serviceModelId - current service id
147    ************************************************************/
148   onClickAdd(node: ITreeNode, serviceModelId: string): void {
149     const vnfStoreKey = this._sharedTreeService.getSelectedVNF() || this.getDefaultVNF(node.parent, serviceModelId);
150     if (vnfStoreKey) {
151       this._dialogService.addDialog(GenericFormPopupComponent, {
152         type: PopupType.VF_MODULE,
153         uuidData: <any>{
154           serviceId: serviceModelId,
155           modelName: node.data.name,
156           vFModuleStoreKey: null,
157           vnfStoreKey: vnfStoreKey,
158           modelId: node.data.modelId,
159           type: node.data.type,
160           popupService: this._vfModulePopupService
161         },
162         node: node,
163         isUpdateMode: false
164       });
165     } else {
166       let messageBoxData: MessageBoxData = new MessageBoxData(
167         "Select a parent",  // modal title
168         "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",
169         <any>"warning",
170         <any>"md",
171         [
172           {text: "Close", size: "medium", closeModal: true}
173         ]);
174       MessageBoxService.openModal.next(messageBoxData);
175     }
176   }
177
178   getDefaultVNF(node: ITreeNode, serviceModelId: string): string {
179     let keys = _.keys(_.pickBy(this._store.getState().service.serviceInstance[serviceModelId].vnfs, vnf => {
180       return (this._sharedTreeService.modelUniqueId(vnf) === node.data.modelUniqueId);
181     }));
182     return keys.length === 1 ? this._store.getState().service.serviceInstance[serviceModelId].vnfs[keys[0]].vnfStoreKey : null;
183   }
184
185   /***********************************************************
186    * return number of existing instances (in all VNF's)
187    * @param node - VfModule node
188    * @param serviceModelId - current service id
189    ************************************************************/
190   getNodeCount(node: ITreeNode, serviceModelId: string): number {
191     const vnfs = this._store.getState().service.serviceInstance[serviceModelId].vnfs;
192     let count: number = 0;
193     if (!_.isNil(this._store.getState().service.serviceInstance) && !_.isNil(this._store.getState().service.serviceInstance[serviceModelId])) {
194       const selectedVNF: string = this._sharedTreeService.getSelectedVNF();
195       if (selectedVNF) {
196         count += this.countNumberOfVFModule(vnfs[selectedVNF], node);
197       }else {
198         for (let vnfKey in vnfs) {
199           count += this.countNumberOfVFModule(vnfs[vnfKey], node);
200         }
201       }
202       return count;
203     }
204     return count;
205   }
206
207
208   countNumberOfVFModule(vnf, node): number {
209     let count = 0;
210     for (let vfModuleKey in vnf['vfModules']) {
211       for (let vfModule in vnf['vfModules'][vfModuleKey]) {
212         if (this._sharedTreeService.modelUniqueId(vnf['vfModules'][vfModuleKey][vfModule]) === node.data.modelUniqueId) {
213           const vfModuleObj = vnf['vfModules'][vfModuleKey][vfModule];
214           if (!(!_.isNil(vfModuleObj) && !_.isNil(vfModuleObj.action) && vfModuleObj.action.split('_').pop() === 'Delete')) count++;
215         }
216       }
217     }
218     return count;
219   }
220
221   getCountVFModuleOfSelectedVNF(node: ITreeNode, vnfStoreKey: string, serviceModelId: string): number {
222     let count: number = 0;
223     if (!_.isNil(this._store.getState().service.serviceInstance) && !_.isNil(this._store.getState().service.serviceInstance[serviceModelId])) {
224       const vnf = this._store.getState().service.serviceInstance[serviceModelId].vnfs[vnfStoreKey];
225       count += this.countNumberOfVFModule(vnf, node);
226       return count;
227     }
228     return count;
229   }
230
231
232   /***********************************************************
233    * should show node icon
234    * @param node - current ITrees node
235    * @param serviceModelId - service id
236    ************************************************************/
237   showNodeIcons(node: ITreeNode, serviceModelId: string): AvailableNodeIcons {
238     const selectedVNF: string = this._sharedTreeService.getSelectedVNF();
239     if (selectedVNF) {
240       return this.showVFModuleOnSelectedVNF(node, selectedVNF, serviceModelId);
241     } else {
242       const optionalSelected = this.getOptionalVNFs(serviceModelId, node.parent.data.modelUniqueId);
243       if (optionalSelected.length === 1) {
244         return this.showVFModuleOnSelectedVNF(node, optionalSelected[0].vnfStoreKey, serviceModelId);
245       } else {
246         return new AvailableNodeIcons(false, false);
247       }
248     }
249   }
250
251
252   showVFModuleOnSelectedVNF(node: ITreeNode, selectedVNF: string, serviceModelId: string): AvailableNodeIcons {
253     if (!_.isNil(this._store.getState().service.serviceInstance[serviceModelId].vnfs[selectedVNF])
254         && node.parent.data.modelUniqueId === this._sharedTreeService.modelUniqueId(this._store.getState().service.serviceInstance[serviceModelId].vnfs[selectedVNF])) {
255       const existingVFModules = this.getCountVFModuleOfSelectedVNF(node, selectedVNF, serviceModelId);
256       const reachedLimit = this.isVFModuleReachedLimit(node, this._store.getState().service.serviceHierarchy, serviceModelId, existingVFModules);
257       const showAddIcon = this._sharedTreeService.shouldShowAddIcon() && !reachedLimit;
258       return new AvailableNodeIcons(showAddIcon, reachedLimit);
259     }
260     return new AvailableNodeIcons(false, false);
261
262   }
263
264   getOptionalVNFs(serviceUUID: string, vnfModelUniqueId: string): any[] {
265     let result = [];
266     if (!_.isNil(this._store.getState().service.serviceInstance) && !_.isNil(this._store.getState().service.serviceInstance[serviceUUID])) {
267       const serviceVNFsInstances = this._store.getState().service.serviceInstance[serviceUUID].vnfs;
268       for (let vnfKey in serviceVNFsInstances) {
269         if (this._sharedTreeService.modelUniqueId(serviceVNFsInstances[vnfKey]) === vnfModelUniqueId) {
270           serviceVNFsInstances[vnfKey].vnfStoreKey = vnfKey;
271           result.push(serviceVNFsInstances[vnfKey]);
272         }
273       }
274     }
275     return result;
276   }
277
278
279   /************************************************
280    return number of instances with action Delete
281    @type: vnfs networks, vngGroups (only vfModule)
282    @node : node model from the left tree
283    ************************************************/
284   getExistingInstancesWithDeleteMode(node, serviceModelId: string, selectedVNF: string): number {
285     const existingInstances = this._store.getState().service.serviceInstance[serviceModelId].vnfs[selectedVNF].vfModules;
286     let counter = 0;
287     const modelUuid = node.data.uuid;
288
289     if (!_.isNil(existingInstances)) {
290       for (let instanceKey in existingInstances) {
291         let size = Object.keys(existingInstances[instanceKey]).length;
292         for (let i = 0; i < size; i++) {
293           let vfModuleDynamicKey = Object.keys(existingInstances[instanceKey])[i];
294           if (!_.isNil(existingInstances[instanceKey][vfModuleDynamicKey].action)) {
295             if (existingInstances[instanceKey][vfModuleDynamicKey]['uuid'] === modelUuid && existingInstances[instanceKey][vfModuleDynamicKey].action.split('_').pop() === 'Delete') {
296               counter++;
297             }
298           }
299         }
300
301       }
302     }
303     return counter;
304   }
305
306   isVFModuleReachedLimit(node: any, serviceHierarchy: any, serviceModelId: string, currentNodeCount: number): boolean {
307     const flags = this._featureFlagsService.getAllFlags();
308     let vnfModules = serviceHierarchy[serviceModelId].vfModules;
309     const maxInstances = vnfModules[node.data.name]
310       ? Utils.getMaxVfModule(vnfModules[node.data.name].properties, flags)
311       : null;
312     if (_.isNil(maxInstances)) {
313       return false;
314     }
315
316     return !(maxInstances > currentNodeCount);
317   }
318
319   getMenuAction(node: ITreeNode, serviceModelId: string): { [methodName: string]: { method: Function, visible: Function, enable: Function } } {
320     return {
321       edit: {
322         method: (node, serviceModelId) => {
323           this._iframeService.addClassOpenModal('content');
324           this._dialogService.addDialog(GenericFormPopupComponent, {
325             type: PopupType.VF_MODULE,
326             uuidData: <any>{
327               serviceId: serviceModelId,
328               modelName: node.data.modelName,
329               vFModuleStoreKey: node.data.dynamicModelName,
330               vnfStoreKey: node.parent.data.vnfStoreKey,
331               modelId: node.data.modelId,
332               type: node.data.type,
333               popupService: this._vfModulePopupService
334             },
335             node: node,
336             isUpdateMode: true
337           });
338         },
339         visible: (node) => this._sharedTreeService.shouldShowRemoveAndEdit(node),
340         enable: (node) => this._sharedTreeService.shouldShowRemoveAndEdit(node),
341       },
342       showAuditInfo: {
343         method: (node, serviceModelId) => {
344           let instance = this._store.getState().service.serviceInstance[serviceModelId].vnfs[node.parent.data.vnfStoreKey].vfModules[node.data.modelName][node.data.modelVersionId];
345           this._sharedTreeService.openAuditInfoModal(node, serviceModelId, instance, 'VFMODULE', this);
346         },
347         visible: (node) => this._sharedTreeService.shouldShowAuditInfo(node),
348         enable: (node) => this._sharedTreeService.shouldShowAuditInfo(node)
349       },
350       remove: {
351         method: (node, serviceModelId) => {
352           this.removeVFM(serviceModelId,node);
353         },
354         visible: (node) => this._sharedTreeService.shouldShowRemoveAndEdit(node),
355         enable: (node) => this._sharedTreeService.shouldShowRemoveAndEdit(node),
356       },
357       delete: {
358         method: (node, serviceModelId) => {
359           this._store.dispatch(deleteActionVfModuleInstance(node.data.dynamicModelName, node.parent.data.vnfStoreKey, serviceModelId, node.data.modelName))
360         },
361         visible: (node) => this._sharedTreeService.shouldShowDelete(node, serviceModelId),
362         enable: (node) => this._sharedTreeService.shouldShowDelete(node, serviceModelId)
363       },
364       undoDelete: {
365         method: (node, serviceModelId) => {
366           this._store.dispatch(undoDeleteVfModuleInstance(node.data.dynamicModelName, node.parent.data.vnfStoreKey, serviceModelId, node.data.modelName));
367           this._store.dispatch(deleteVFModuleField(node.data.modelName,  node.parent.data.vnfStoreKey, node.data.servicedId ,node.data.dynamicModelName, 'retainAssignments'));
368         },
369         visible: (node) => this._sharedTreeService.shouldShowUndoDelete(node),
370         enable: (node, serviceModelId) => this._sharedTreeService.shouldShowUndoDelete(node) && this._sharedTreeService.shouldShowDelete(node.parent, serviceModelId) && !this._sharedTreeService.isServiceOnDeleteMode(serviceModelId)
371       },
372       upgrade: {
373         method: (node, serviceModelId) => {
374           this.upgradeVFM(serviceModelId, node);
375         },
376         visible: (node,serviceModelId) => {
377           return this._sharedTreeService.shouldShowUpgrade(node, serviceModelId);
378         },
379         enable:  (node, serviceModelId) => {
380           return this._sharedTreeService.shouldShowUpgrade(node, serviceModelId);
381         }
382       },
383       undoUpgrade: {
384         method: (node, serviceModelId) => {
385           this._sharedTreeService.undoUpgradeBottomUp(node, serviceModelId);
386           this._store.dispatch(undoUgradeVFModule(node.data.modelName, node.parent.data.vnfStoreKey, serviceModelId, node.data.dynamicModelName));
387         },
388         visible: (node) => {
389           return this._sharedTreeService.shouldShowUndoUpgrade(node);
390         },
391         enable: (node) => {
392           return this._sharedTreeService.shouldShowUndoUpgrade(node);
393         }
394       },
395       pauseInstantiation: {
396         method: (node, serviceModelId) => {
397           this._store.dispatch(pauseActionVFModuleInstance(node.data.dynamicModelName, node.parent.data.vnfStoreKey, serviceModelId, node.data.modelName));
398         },
399         visible: () => this._sharedTreeService.shouldShowPauseInstantiation(node),
400         enable: () => true,
401       },
402       removePause: {
403         method: (node, serviceModelId) => {
404           this._store.dispatch(removePauseActionVFModuleInstance(node.data.dynamicModelName, node.parent.data.vnfStoreKey, serviceModelId, node.data.modelName));
405         },
406         visible: () => this._sharedTreeService.shouldShowRemovePause(node),
407         enable: () => true,
408       }
409     };
410   }
411
412   private upgradeVFM(serviceModelId, node) {
413     if (FeatureFlagsService.getFlagState(Features.FLAG_2002_VFM_UPGRADE_ADDITIONAL_OPTIONS, this._store)) {
414       this._iframeService.addClassOpenModal('content');
415       this._dialogService.addDialog(GenericFormPopupComponent, {
416         type: PopupType.VF_MODULE_UPGRADE,
417         uuidData: <any>{
418           serviceId: serviceModelId,
419           modelName: node.data.modelName,
420           vFModuleStoreKey: node.data.dynamicModelName,
421           vnfStoreKey: node.parent.data.vnfStoreKey,
422           modelId: node.data.modelId,
423           type: node.data.type,
424           popupService: this._vfModuleUpgradePopupService,
425           vfModule : _.cloneDeep(node)
426         },
427         node,
428         isUpdateMode: true
429       });
430     } else {
431       this._sharedTreeService.upgradeBottomUp(node, serviceModelId);
432       this._store.dispatch(upgradeVFModule(node.data.modelName,  node.parent.data.vnfStoreKey, serviceModelId ,node.data.dynamicModelName));
433     }
434   }
435
436   updatePosition(that, node,instanceId, parentStoreKey): void {
437     that.store.dispatch(updateVFModulePosition(node.modelName,node.dynamicModelName, node.position,instanceId, parentStoreKey));
438   }
439
440
441   getNodePosition(instance, deepDynamicName): number {
442     return (!_.isNil(instance) && !_.isNil(instance[deepDynamicName])) ? instance[deepDynamicName].position : null;
443   }
444
445   getInfo(model:Partial<VfModule>, instance): ModelInformationItem[] {
446     const modelInformation = !_.isEmpty(model) ? [
447       ModelInformationItem.createInstance("Base module", model.baseModule),
448       ModelInformationItem.createInstance("Min instances", !_.isNull(model.min) ? String(model.min) : null),
449       this._sharedTreeService.createMaximumToInstantiateModelInformationItem(model),
450       ModelInformationItem.createInstance("Initial instances count", !_.isNull(model.initial) ? String(model.initial) : null)
451     ] : [];
452
453     const instanceInfo = [];
454     const result = [modelInformation, instanceInfo];
455     return _.uniq(_.flatten(result));
456   }
457
458   private removeVFM(serviceModelId, node) {
459     if (FeatureFlagsService.getFlagState(Features.FLAG_2008_CREATE_VFMODULE_INSTANTIATION_ORDER_NUMBER, this._store)) {
460       let nodeArray = node.parent.children;
461       let totalNumOfNodes = nodeArray.length;
462       let removedNodeIndex = node.index;
463       let remainingNodes = totalNumOfNodes - (removedNodeIndex+1);
464       if(!_.isNull(remainingNodes)) {
465         if(remainingNodes !== 0 && remainingNodes >0) {
466           for(let i= 0;i<remainingNodes;i++) {
467             let temp = nodeArray[removedNodeIndex];
468             nodeArray[removedNodeIndex] = nodeArray[removedNodeIndex + 1];
469             nodeArray[removedNodeIndex + 1] = temp;
470             removedNodeIndex= removedNodeIndex+1;
471           }
472           let removedNode = nodeArray[nodeArray.length - 1];
473           this._store.dispatch(removeVfModuleInstance(removedNode.data.modelName, serviceModelId, removedNode.parent.data.modelName, removedNode.parent.data.vnfStoreKey, removedNode.data.dynamicModelName));
474           nodeArray.pop();
475           nodeArray.forEach((item, index) => {
476             if (item.position !== index + 1) {
477               item.position = index + 1;
478               this._store.dispatch(updateVFModulePosition(item.data.modelName,item.data.dynamicModelName, item.position,serviceModelId, item.parent.data.vnfStoreKey));
479             }
480           });
481
482
483         }else{
484           this._store.dispatch(removeVfModuleInstance(node.data.modelName, serviceModelId, node.parent.data.modelName, node.parent.data.vnfStoreKey, node.data.dynamicModelName));
485
486         }
487       }
488     } else {
489       this._store.dispatch(removeVfModuleInstance(node.data.modelName, serviceModelId, node.parent.data.modelName, node.parent.data.vnfStoreKey, node.data.dynamicModelName));
490     }
491   }
492 }