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";
12 GenericFormPopupComponent,
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";
23 deleteActionVfModuleInstance,
25 pauseActionVFModuleInstance,
26 removePauseActionVFModuleInstance,
27 removeVfModuleInstance,
28 undoDeleteVfModuleInstance,
30 updateVFModulePosition,
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";
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) {
52 name: string = 'vfModules';
53 type: string = 'Module';
54 typeName: string = 'M';
55 componentInfoType = ComponentInfoType.VFMODULE;
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";
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);
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());
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);
94 const dynamicInputs = this.updateDynamicInputsDataFromModel(currentModel);
95 let newVfModule: VfModuleTreeNode = new VfModuleTreeNode(instance, currentModel, modelName, dynamicInputs, isEcompGeneratedNaming, dynamicModelName);
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);
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));
117 return this.createNode(instance, model, parentModel, storeKey, 0, serviceModelId);
121 /***********************************************************
122 * return next level object (null because is last level)
123 ************************************************************/
124 getNextLevelObject(): any {
128 getTooltip = (): string => 'VFmodule';
130 getType = (): string => 'VFmodule';
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, []);
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);
151 this._dialogService.addDialog(GenericFormPopupComponent, {
152 type: PopupType.VF_MODULE,
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
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",
172 {text: "Close", size: "medium", closeModal: true}
174 MessageBoxService.openModal.next(messageBoxData);
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);
182 return keys.length === 1 ? this._store.getState().service.serviceInstance[serviceModelId].vnfs[keys[0]].vnfStoreKey : null;
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();
196 count += this.countNumberOfVFModule(vnfs[selectedVNF], node);
198 for (let vnfKey in vnfs) {
199 count += this.countNumberOfVFModule(vnfs[vnfKey], node);
208 countNumberOfVFModule(vnf, node): number {
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++;
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);
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();
240 return this.showVFModuleOnSelectedVNF(node, selectedVNF, serviceModelId);
242 const optionalSelected = this.getOptionalVNFs(serviceModelId, node.parent.data.modelUniqueId);
243 if (optionalSelected.length === 1) {
244 return this.showVFModuleOnSelectedVNF(node, optionalSelected[0].vnfStoreKey, serviceModelId);
246 return new AvailableNodeIcons(false, false);
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);
260 return new AvailableNodeIcons(false, false);
264 getOptionalVNFs(serviceUUID: string, vnfModelUniqueId: string): any[] {
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]);
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;
287 const modelUuid = node.data.uuid;
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') {
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)
312 if (_.isNil(maxInstances)) {
316 return !(maxInstances > currentNodeCount);
319 getMenuAction(node: ITreeNode, serviceModelId: string): { [methodName: string]: { method: Function, visible: Function, enable: Function } } {
322 method: (node, serviceModelId) => {
323 this._iframeService.addClassOpenModal('content');
324 this._dialogService.addDialog(GenericFormPopupComponent, {
325 type: PopupType.VF_MODULE,
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
339 visible: (node) => this._sharedTreeService.shouldShowRemoveAndEdit(node),
340 enable: (node) => this._sharedTreeService.shouldShowRemoveAndEdit(node),
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);
347 visible: (node) => this._sharedTreeService.shouldShowAuditInfo(node),
348 enable: (node) => this._sharedTreeService.shouldShowAuditInfo(node)
351 method: (node, serviceModelId) => this._store.dispatch(removeVfModuleInstance(node.data.modelName, serviceModelId, node.parent.data.modelName, node.parent.data.vnfStoreKey, node.data.dynamicModelName)),
352 visible: (node) => this._sharedTreeService.shouldShowRemoveAndEdit(node),
353 enable: (node) => this._sharedTreeService.shouldShowRemoveAndEdit(node),
356 method: (node, serviceModelId) => {
357 this._store.dispatch(deleteActionVfModuleInstance(node.data.dynamicModelName, node.parent.data.vnfStoreKey, serviceModelId, node.data.modelName))
359 visible: (node) => this._sharedTreeService.shouldShowDelete(node, serviceModelId),
360 enable: (node) => this._sharedTreeService.shouldShowDelete(node, serviceModelId)
363 method: (node, serviceModelId) => {
364 this._store.dispatch(undoDeleteVfModuleInstance(node.data.dynamicModelName, node.parent.data.vnfStoreKey, serviceModelId, node.data.modelName));
365 this._store.dispatch(deleteVFModuleField(node.data.modelName, node.parent.data.vnfStoreKey, node.data.servicedId ,node.data.dynamicModelName, 'retainAssignments'));
367 visible: (node) => this._sharedTreeService.shouldShowUndoDelete(node),
368 enable: (node, serviceModelId) => this._sharedTreeService.shouldShowUndoDelete(node) && this._sharedTreeService.shouldShowDelete(node.parent, serviceModelId) && !this._sharedTreeService.isServiceOnDeleteMode(serviceModelId)
371 method: (node, serviceModelId) => {
372 this.upgradeVFM(serviceModelId, node);
374 visible: (node,serviceModelId) => {
375 return this._sharedTreeService.shouldShowUpgrade(node, serviceModelId);
377 enable: (node, serviceModelId) => {
378 return this._sharedTreeService.shouldShowUpgrade(node, serviceModelId);
382 method: (node, serviceModelId) => {
383 this._sharedTreeService.undoUpgradeBottomUp(node, serviceModelId);
384 this._store.dispatch(undoUgradeVFModule(node.data.modelName, node.parent.data.vnfStoreKey, serviceModelId, node.data.dynamicModelName));
387 return this._sharedTreeService.shouldShowUndoUpgrade(node);
390 return this._sharedTreeService.shouldShowUndoUpgrade(node);
393 pauseInstantiation: {
394 method: (node, serviceModelId) => {
395 this._store.dispatch(pauseActionVFModuleInstance(node.data.dynamicModelName, node.parent.data.vnfStoreKey, serviceModelId, node.data.modelName));
397 visible: () => this._sharedTreeService.shouldShowPauseInstantiation(node),
401 method: (node, serviceModelId) => {
402 this._store.dispatch(removePauseActionVFModuleInstance(node.data.dynamicModelName, node.parent.data.vnfStoreKey, serviceModelId, node.data.modelName));
404 visible: () => this._sharedTreeService.shouldShowRemovePause(node),
410 private upgradeVFM(serviceModelId, node) {
411 if (FeatureFlagsService.getFlagState(Features.FLAG_2002_VFM_UPGRADE_ADDITIONAL_OPTIONS, this._store)) {
412 this._iframeService.addClassOpenModal('content');
413 this._dialogService.addDialog(GenericFormPopupComponent, {
414 type: PopupType.VF_MODULE_UPGRADE,
416 serviceId: serviceModelId,
417 modelName: node.data.modelName,
418 vFModuleStoreKey: node.data.dynamicModelName,
419 vnfStoreKey: node.parent.data.vnfStoreKey,
420 modelId: node.data.modelId,
421 type: node.data.type,
422 popupService: this._vfModuleUpgradePopupService,
423 vfModule : _.cloneDeep(node)
429 this._sharedTreeService.upgradeBottomUp(node, serviceModelId);
430 this._store.dispatch(upgradeVFModule(node.data.modelName, node.parent.data.vnfStoreKey, serviceModelId ,node.data.dynamicModelName));
434 updatePosition(that, node, instanceId, parentStoreKey): void {
435 this._store.dispatch(updateVFModulePosition(node, instanceId, parentStoreKey));
439 getNodePosition(instance, deepDynamicName): number {
440 return (!_.isNil(instance) && !_.isNil(instance[deepDynamicName])) ? instance[deepDynamicName].position : null;
443 getInfo(model:Partial<VfModule>, instance): ModelInformationItem[] {
444 const modelInformation = !_.isEmpty(model) ? [
445 ModelInformationItem.createInstance("Base module", model.baseModule),
446 ModelInformationItem.createInstance("Min instances", !_.isNull(model.min) ? String(model.min) : null),
447 this._sharedTreeService.createMaximumToInstantiateModelInformationItem(model),
448 ModelInformationItem.createInstance("Initial instances count", !_.isNull(model.initial) ? String(model.initial) : null)
451 const instanceInfo = [];
452 const result = [modelInformation, instanceInfo];
453 return _.uniq(_.flatten(result));