Merge remote-tracking branch 'origin/v1.0'
[osm/UI.git] / skyquake / plugins / composer / src / src / libraries / model / DescriptorModelSerializer.js
1
2 /*
3 *
4 * Copyright 2016 RIFT.IO Inc
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
19 /**
20 * Created by onvelocity on 10/20/15.
21 */
22
23 import _ from 'lodash'
24 import utils from './../utils'
25 import DescriptorModelFields from './DescriptorModelFields'
26 import DescriptorModelMetaFactory from './DescriptorModelMetaFactory'
27
28 let nsdFields = null;
29 let vldFields = null;
30 let vnfdFields = null;
31 let cvnfdFields = null;
32
33
34
35
36 /**
37 * Serialize DescriptorModel JSON into CONFD JSON. Also, cleans up the data as needed.
38 *
39 * @type {{serialize: (function(*=)), ':clean': (function(*=)), nsd: {serialize: (function(*=))}, vld: {serialize: (function(*=))}, vnfd-connection-point-ref: {serialize: (function(*=))}, constituent-vnfd: {serialize: (function(*=))}, vnfd: {serialize: (function(*=))}, vdu: {serialize: (function(*=))}}}
40 */
41 const DescriptorModelSerializer = {
42 serialize(model) {
43 const type = model.uiState && model.uiState.type;
44 const serializer = this[type];
45 if (serializer) {
46 model = serializer.serialize(model);
47 this[':clean'](model);
48 return model;
49 }
50 return false;
51 },
52 ':clean'(model) {
53 // remove uiState from all elements accept nsd and vnfd
54 // remove empty / blank value fields
55 function clean(m) {
56 Object.keys(m).forEach(k => {
57 const isEmptyObject = typeof m[k] === 'object' && _.isEmpty(m[k]);
58 if (typeof m[k] === 'undefined' || isEmptyObject || m[k] === '') {
59 delete m[k];
60 }
61 const isMetaAllowed = /^nsd|vnfd$/.test(m.uiState && m.uiState.type);
62 if (k === 'uiState') {
63 if (isMetaAllowed) {
64 // remove any transient ui state properties
65 const uiState = _.pick(m.uiState, DescriptorModelFields.meta);
66 if (!_.isEmpty(uiState)) {
67 // uiState field must be a string
68 m['meta'] = JSON.stringify(uiState);
69 }
70 }
71 delete m[k];
72 }
73 if (typeof m[k] === 'object') {
74 clean(m[k]);
75 }
76 });
77 }
78 clean(model);
79 return model;
80 },
81 nsd: {
82 serialize(nsdModel) {
83 if(!nsdFields) nsdFields = DescriptorModelMetaFactory.getModelFieldNamesForType('nsd').concat('uiState');
84 const confd = _.pick(nsdModel, nsdFields);
85
86 // vnfd is defined in the ETSI etsi_gs reference manual but RIFT does not use it
87 delete confd.vnfd;
88
89 // map the vnfd instances into the CONFD constituent-vnfd ref instances
90 confd['constituent-vnfd'] = confd['constituent-vnfd'].map((d, index) => {
91
92 const constituentVNFD = {
93 'member-vnf-index': d['member-vnf-index'],
94 'vnfd-id-ref': d['vnfd-id-ref']
95 };
96
97 if (d['vnf-configuration']) {
98 const vnfConfig = _.cloneDeep(d['vnf-configuration']);
99 const configType = vnfConfig['config-type'] || 'none';
100 // make sure we send the correct values based on config type
101 if (configType === 'none') {
102 constituentVNFD['vnf-configuration'] = {'config-type': 'none'};
103 const configPriority = utils.resolvePath(vnfConfig, 'input-params.config-priority');
104 const configPriorityValue = _.isNumber(configPriority) ? configPriority : d.uiState['member-vnf-index'];
105 utils.assignPathValue(constituentVNFD['vnf-configuration'], 'input-params.config-priority', configPriorityValue);
106 } else {
107 // remove any unused configuration options
108 ['netconf', 'rest', 'script', 'juju'].forEach(type => {
109 if (configType !== type) {
110 delete vnfConfig[type];
111 }
112 });
113 constituentVNFD['vnf-configuration'] = vnfConfig;
114 }
115 }
116
117 if (d.hasOwnProperty('start-by-default')) {
118 constituentVNFD['start-by-default'] = d['start-by-default'];
119 }
120
121 return constituentVNFD;
122
123 });
124 for (var key in confd) {
125 checkForChoiceAndRemove(key, confd, nsdModel);
126 }
127 // serialize the VLD instances
128 confd.vld = confd.vld.map(d => {
129 return DescriptorModelSerializer.serialize(d);
130 });
131
132 return cleanEmptyTopKeys(confd);
133
134 }
135 },
136 vld: {
137 serialize(vldModel) {
138 if(!vldFields) vldFields = DescriptorModelMetaFactory.getModelFieldNamesForType('nsd.vld');
139 const confd = _.pick(vldModel, vldFields);
140 const property = 'vnfd-connection-point-ref';
141
142 // TODO: There is a bug in RIFT-REST that is not accepting empty
143 // strings for string properties.
144 // once that is fixed, remove this piece of code.
145 // fix-start
146 for (var key in confd) {
147 if (confd.hasOwnProperty(key) && confd[key] === '') {
148 delete confd[key];
149 } else {
150 //removes choice properties from top level object and copies immediate children onto it.
151 checkForChoiceAndRemove(key, confd, vldModel);
152 }
153 }
154
155
156 const deepProperty = 'provider-network';
157 for (var key in confd[deepProperty]) {
158 if (confd[deepProperty].hasOwnProperty(key) && confd[deepProperty][key] === '') {
159 delete confd[deepProperty][key];
160 }
161 }
162 // fix-end
163 confd[property] = confd[property].map(d => DescriptorModelSerializer[property].serialize(d));
164 return cleanEmptyTopKeys(confd);
165 }
166 },
167 'vnfd-connection-point-ref': {
168 serialize(ref) {
169 return _.pick(ref, ['member-vnf-index-ref', 'vnfd-id-ref', 'vnfd-connection-point-ref']);
170 }
171 },
172 'internal-connection-point': {
173 serialize(ref) {
174 return _.pick(ref, ['id-ref']);
175 }
176 },
177 'constituent-vnfd': {
178 serialize(cvnfdModel) {
179 if(!cvnfdFields) cvnfdFields = DescriptorModelMetaFactory.getModelFieldNamesForType('nsd.constituent-vnfd');
180 return _.pick(cvnfdModel, cvnfdFields);
181 }
182 },
183 vnfd: {
184 serialize(vnfdModel) {
185 if(!vnfdFields) vnfdFields = DescriptorModelMetaFactory.getModelFieldNamesForType('vnfd').concat('uiState');
186 const confd = _.pick(vnfdModel, vnfdFields);
187 confd.vdu = confd.vdu.map(d => DescriptorModelSerializer.serialize(d));
188 return cleanEmptyTopKeys(confd);
189 }
190 },
191 vdu: {
192 serialize(vduModel) {
193 const copy = _.cloneDeep(vduModel);
194 for (let k in copy) {
195 checkForChoiceAndRemove(k, copy, vduModel)
196 }
197 const confd = _.omit(copy, ['uiState']);
198 return cleanEmptyTopKeys(confd);
199 }
200 }
201 };
202
203
204 function checkForChoiceAndRemove(k, confd, model) {
205 let state = model.uiState;
206 if (state.choice) {
207 let choice = state.choice[k]
208 if(choice) {
209 if (choice.constructor.name == "Array") {
210 for(let i = 0; i < choice.length; i++) {
211 for (let key in confd[k][i]) {
212 if(choice[i] && (choice[i].selected.indexOf(key) > -1)) {
213 confd[k][i][key] = confd[k][i][key]
214 }
215 confd[key];
216 };
217 }
218 } else {
219 for (let key in confd[k]) {
220 if(choice && (choice.selected.indexOf(key) > -1)) {
221 confd[key] = confd[k][key]
222 }
223 };
224 delete confd[k];
225 }
226
227 }
228 }
229 return confd;
230 }
231
232 function cleanEmptyTopKeys(m){
233 Object.keys(m).forEach(k => {
234 const isEmptyObject = typeof m[k] === 'object' && _.isEmpty(m[k]);
235 if (typeof m[k] === 'undefined' || isEmptyObject || m[k] === '') {
236 delete m[k];
237 }
238 });
239 return m;
240 }
241
242 export default DescriptorModelSerializer;