Add parser convert vnfd vdu logic
[vfc/nfvo/lcm.git] / lcm / pub / utils / toscaparser / basemodel.py
1 # Copyright 2017 ZTE Corporation.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #         http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 import copy
16 import ftplib
17 import json
18 import os
19 import re
20 import shutil
21 import urllib
22
23 import paramiko
24 from toscaparser.functions import GetInput
25 from toscaparser.tosca_template import ToscaTemplate
26
27 from lcm.pub.utils.toscaparser.dataentityext import DataEntityExt
28
29
30 class BaseInfoModel(object):
31
32     def buildToscaTemplate(self, path, params):
33         file_name = None
34         try:
35             file_name = self._check_download_file(path)
36             valid_params = self._validate_input_params(file_name, params)
37             return self._create_tosca_template(file_name, valid_params)
38         finally:
39             if file_name != None and file_name != path and os.path.exists(file_name):
40                 try:
41                     os.remove(file_name)
42                 except Exception, e:
43                     pass
44
45     def _validate_input_params(self, path, params):
46         valid_params = {}
47         if params and len(params) > 0:
48             tmp = self._create_tosca_template(path, None)
49             for key,value in params.items():
50                 if hasattr(tmp, 'inputs') and len(tmp.inputs) > 0:
51                     for input_def in tmp.inputs:
52                         if (input_def.name == key):
53                             valid_params[key] = DataEntityExt.validate_datatype(input_def.type, value)
54
55         return valid_params
56
57     def _create_tosca_template(self, file_name, valid_params):
58         tosca_tpl = None
59         try:
60             tosca_tpl = ToscaTemplate(file_name, valid_params)
61             print "-----------------------------"
62             print '\n'.join(['%s:%s' % item for item in tosca_tpl.__dict__.items()])
63             print "-----------------------------"
64             return tosca_tpl
65         finally:
66             if tosca_tpl != None and hasattr(tosca_tpl, "temp_dir") and os.path.exists(tosca_tpl.temp_dir):
67                 try:
68                     shutil.rmtree(tosca_tpl.temp_dir)
69                 except Exception, e:
70                     pass
71
72     def _check_download_file(self, path):
73         if (path.startswith("ftp") or path.startswith("sftp")):
74             return self.downloadFileFromFtpServer(path)
75         elif (path.startswith("http")):
76             return self.download_file_from_httpserver(path)
77         return path
78
79     def download_file_from_httpserver(self, path):
80         path = path.encode("utf-8")
81         tmps = str.split(path, '/')
82         localFileName = tmps[len(tmps) - 1]
83         urllib.urlretrieve(path, localFileName)
84         return localFileName
85
86     def downloadFileFromFtpServer(self, path):
87         path = path.encode("utf-8")
88         tmp = str.split(path, '://')
89         protocol = tmp[0]
90         tmp = str.split(tmp[1], ':')
91         if len(tmp) == 2:
92             userName = tmp[0]
93             tmp = str.split(tmp[1], '@')
94             userPwd = tmp[0]
95             index = tmp[1].index('/')
96             hostIp = tmp[1][0:index]
97             remoteFileName = tmp[1][index:len(tmp[1])]
98             if protocol.lower() == 'ftp':
99                 hostPort = 21
100             else:
101                 hostPort = 22
102
103         if len(tmp) == 3:
104             userName = tmp[0]
105             userPwd = str.split(tmp[1], '@')[0]
106             hostIp = str.split(tmp[1], '@')[1]
107             index = tmp[2].index('/')
108             hostPort = tmp[2][0:index]
109             remoteFileName = tmp[2][index:len(tmp[2])]
110
111         localFileName = str.split(remoteFileName, '/')
112         localFileName = localFileName[len(localFileName) - 1]
113
114         if protocol.lower() == 'sftp':
115             self.sftp_get(userName, userPwd, hostIp, hostPort, remoteFileName, localFileName)
116         else:
117             self.ftp_get(userName, userPwd, hostIp, hostPort, remoteFileName, localFileName)
118         return localFileName
119
120     def sftp_get(self, userName, userPwd, hostIp, hostPort, remoteFileName, localFileName):
121         # return
122         t = None
123         try:
124             t = paramiko.Transport(hostIp, int(hostPort))
125             t.connect(username=userName, password=userPwd)
126             sftp = paramiko.SFTPClient.from_transport(t)
127             sftp.get(remoteFileName, localFileName)
128         finally:
129             if t != None:
130                 t.close()
131
132
133     def ftp_get(self, userName, userPwd, hostIp, hostPort, remoteFileName, localFileName):
134         f = None
135         try:
136             ftp = ftplib.FTP()
137             ftp.connect(hostIp, hostPort)
138             ftp.login(userName, userPwd)
139             f = open(localFileName, 'wb')
140             ftp.retrbinary('RETR ' + remoteFileName, f.write, 1024)
141             f.close()
142         finally:
143             if f != None:
144                 f.close()
145
146     def buidMetadata(self, tosca):
147         if 'metadata' in tosca.tpl:
148             self.metadata = copy.deepcopy(tosca.tpl['metadata'])
149
150     def buildProperties(self, nodeTemplate, parsed_params):
151         properties = {}
152         isMappingParams = parsed_params and len(parsed_params) > 0
153         for k, item in nodeTemplate.get_properties().items():
154             properties[k] = item.value
155             if isinstance(item.value, GetInput):
156                 if item.value.result() and isMappingParams:
157                     properties[k] = DataEntityExt.validate_datatype(item.type, item.value.result())
158                 else:
159                     tmp = {}
160                     tmp[item.value.name] = item.value.input_name
161                     properties[k] = tmp
162         if 'attributes' in nodeTemplate.entity_tpl:
163             for k, item in nodeTemplate.entity_tpl['attributes'].items():
164                 properties[k] = str(item)
165         return properties
166
167
168     def verify_properties(self, props, inputs, parsed_params):
169         ret_props = {}
170         if (props and len(props) > 0):
171             for key, value in props.items():
172                 ret_props[key] = self._verify_value(value, inputs, parsed_params)
173                 #                 if isinstance(value, str):
174                 #                     ret_props[key] = self._verify_string(inputs, parsed_params, value);
175                 #                     continue
176                 #                 if isinstance(value, list):
177                 #                     ret_props[key] = map(lambda x: self._verify_dict(inputs, parsed_params, x), value)
178                 #                     continue
179                 #                 if isinstance(value, dict):
180                 #                     ret_props[key] = self._verify_map(inputs, parsed_params, value)
181                 #                     continue
182                 #                 ret_props[key] = value
183         return ret_props
184
185     def build_requirements(self, node_template):
186         rets = []
187         for req in node_template.requirements:
188             for req_name, req_value in req.items():
189                 if (isinstance(req_value, dict)):
190                     if ('node' in req_value and req_value['node'] not in node_template.templates):
191                         continue  # No target requirement for aria parser, not add to result.
192                 rets.append({req_name : req_value})
193         return rets
194
195     def buildCapabilities(self, nodeTemplate, inputs, ret):
196         capabilities = json.dumps(nodeTemplate.entity_tpl.get('capabilities', None))
197         match = re.findall(r'\{"get_input":\s*"([\w|\-]+)"\}',capabilities)
198         for m in match:
199             aa= [input_def for input_def in inputs
200                  if m == input_def.name][0]
201             capabilities = re.sub(r'\{"get_input":\s*"([\w|\-]+)"\}', json.dumps(aa.default), capabilities,1)
202         if capabilities != 'null':
203             ret['capabilities'] = json.loads(capabilities)
204
205     def buildArtifacts(self, nodeTemplate, inputs, ret):
206         artifacts = json.dumps(nodeTemplate.entity_tpl.get('artifacts', None))
207         match = re.findall(r'\{"get_input":\s*"([\w|\-]+)"\}',artifacts)
208         for m in match:
209             aa= [input_def for input_def in inputs
210                  if m == input_def.name][0]
211             artifacts = re.sub(r'\{"get_input":\s*"([\w|\-]+)"\}', json.dumps(aa.default), artifacts,1)
212         if artifacts != 'null':
213             ret['artifacts'] = json.loads(artifacts)
214
215     def build_interfaces(self, node_template):
216         if 'interfaces' in node_template.entity_tpl:
217             return node_template.entity_tpl['interfaces']
218         return None
219
220     def isVnf(self, node):
221         return node['nodeType'].upper().find('.VNF.') >= 0 or node['nodeType'].upper().endswith('.VNF')
222
223     def isPnf(self, node):
224         return node['nodeType'].upper().find('.PNF.') >= 0 or node['nodeType'].upper().endswith('.PNF')
225
226     def isCp(self, node):
227         return node['nodeType'].upper().find('.CP.') >= 0 or node['nodeType'].upper().endswith('.CP')
228
229     def isVl(self, node):
230         return node['nodeType'].upper().find('.VIRTUALLINK.') >= 0 or node['nodeType'].upper().find('.VL.') >= 0 or \
231                node['nodeType'].upper().endswith('.VIRTUALLINK') or node['nodeType'].upper().endswith('.VL')
232
233     def isService(self, node):
234         return node['nodeType'].upper().find('.SERVICE.') >= 0 or node['nodeType'].upper().endswith('.SERVICE')
235
236     def get_requirement_node_name(self, req_value):
237         return self.get_prop_from_obj(req_value, 'node')
238
239     def get_prop_from_obj(self, obj, prop):
240         if isinstance(obj, str):
241             return obj
242         if (isinstance(obj, dict) and prop in obj):
243             return obj[prop]
244         return None
245
246     def getNodeDependencys(self, node):
247         return self.getRequirementByName(node, 'dependency')
248
249     def getVirtualLinks(self, node):
250         return self.getRequirementByName(node, 'virtualLink')
251
252     def getVirtualbindings(self, node):
253         return self.getRequirementByName(node, 'virtualbinding')
254
255
256     def getRequirementByName(self, node, requirementName):
257         requirements = []
258         if 'requirements' in node:
259             for item in node['requirements']:
260                 for key, value in item.items():
261                     if key == requirementName:
262                         requirements.append(value)
263         return requirements
264
265     def get_networks(self, node):
266         rets = []
267         if 'requirements' in node:
268             for item in node['requirements']:
269                 for key, value in item.items():
270                     if key.upper().find('VIRTUALLINK') >=0:
271                         rets.append({"key_name":key, "vl_id":self.get_requirement_node_name(value)})
272         return rets
273
274     def _verify_value(self, value, inputs, parsed_params):
275         if isinstance(value, str):
276             return self._verify_string(inputs, parsed_params, value)
277         if isinstance(value, list) or isinstance(value, dict):
278             return self._verify_object(value, inputs, parsed_params)
279         return value
280
281     def _verify_object(self, value, inputs, parsed_params):
282         s = self._verify_string(inputs, parsed_params, json.dumps(value))
283         return json.loads(s)
284
285     def _get_input_name(self, getInput):
286         input_name = getInput.split(':')[1]
287         input_name = input_name.strip()
288         return input_name.replace('"', '').replace('}', '')
289
290     def _verify_string(self, inputs, parsed_params, value):
291         getInputs = re.findall(r'{"get_input": "[a-zA-Z_0-9]+"}', value)
292         for getInput in getInputs:
293             input_name = self._get_input_name(getInput)
294             if parsed_params and input_name in parsed_params:
295                 value = value.replace(getInput, json.dumps(parsed_params[input_name]))
296             else:
297                 for input_def in inputs:
298                     if input_def.default and input_name == input_def.name:
299                         value = value.replace(getInput, json.dumps(input_def.default))
300         return value
301
302     def get_node_vl_id(self, node):
303         vl_ids = map(lambda x: self.get_requirement_node_name(x), self.getVirtualLinks(node))
304         if len(vl_ids) > 0:
305             return vl_ids[0]
306         return ""
307
308     def get_node_by_name(self, node_templates, name):
309         for node in node_templates:
310             if node['name'] == name:
311                 return node
312         return None
313
314     def get_all_nested_ns(self, nodes):
315         nss = []
316         for node in nodes:
317             if self.is_nested_ns(node):
318                 ns = {}
319                 ns['ns_id'] = node['name']
320                 ns['description'] = node['description']
321                 ns['properties'] = node['properties']
322                 ns['networks'] = self.get_networks(node)
323
324                 nss.append(ns)
325         return nss
326
327     def is_nested_ns(self, node):
328         return node['nodeType'].upper().find('.NS.') >= 0 or node['nodeType'].upper().endswith('.NS')
329
330     def isVdu(self, node):
331         return node['nodeType'].upper().find('.VDU.') >= 0 or node['nodeType'].upper().endswith('.VDU')
332
333     def getCapabilityByName(self, node, capabilityName):
334         if 'capabilities' in node and capabilityName in node['capabilities']:
335             return node['capabilities'][capabilityName]
336         return None