summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitreview4
-rw-r--r--lcm/pub/database/models.py2
-rw-r--r--lcm/pub/utils/toscaparser/__init__.py4
-rw-r--r--lcm/pub/utils/toscaparser/baseinfomodel.py105
-rw-r--r--lcm/pub/utils/toscaparser/basemodel.py178
-rw-r--r--lcm/pub/utils/toscaparser/etsinsdinfomodel.py12
-rw-r--r--lcm/pub/utils/toscaparser/nsdmodel.py59
-rw-r--r--lcm/pub/utils/toscaparser/vnfdmodel.py (renamed from lcm/pub/utils/toscaparser/etsivnfdinfomodel.py)0
-rw-r--r--lcm/urls.py1
-rw-r--r--lcm/workflows/__init__.py13
-rw-r--r--lcm/workflows/tests.py31
-rw-r--r--lcm/workflows/urls.py23
-rw-r--r--lcm/workflows/views.py47
-rw-r--r--resources/dbscripts/mysql/vfc-nfvo-lcm-createobj.sql2
14 files changed, 362 insertions, 119 deletions
diff --git a/.gitreview b/.gitreview
new file mode 100644
index 00000000..136320da
--- /dev/null
+++ b/.gitreview
@@ -0,0 +1,4 @@
+[gerrit]
+host=gerrit.onap.org
+port=29418
+project=vfc/nfvo/lcm \ No newline at end of file
diff --git a/lcm/pub/database/models.py b/lcm/pub/database/models.py
index 9071c8e7..0f26c238 100644
--- a/lcm/pub/database/models.py
+++ b/lcm/pub/database/models.py
@@ -308,5 +308,7 @@ class WFPlanModel(models.Model):
deployed_id = models.CharField(db_column='DEPLOYEDID', max_length=255, primary_key=True)
process_id = models.CharField(db_column='PROCESSID', max_length=255)
+ status = models.CharField(db_column='STATUS', max_length=255)
+ message = models.CharField(db_column='MESSAGE', max_length=1024)
plan_name = models.CharField(db_column='PLANNAME', max_length=255)
diff --git a/lcm/pub/utils/toscaparser/__init__.py b/lcm/pub/utils/toscaparser/__init__.py
index 4d9064ed..b224f4ef 100644
--- a/lcm/pub/utils/toscaparser/__init__.py
+++ b/lcm/pub/utils/toscaparser/__init__.py
@@ -14,8 +14,8 @@
import json
from lcm.pub.utils.toscaparser.convert import convert_nsd, convert_vnfd
-from lcm.pub.utils.toscaparser.etsinsdinfomodel import EtsiNsdInfoModel
-from lcm.pub.utils.toscaparser.etsivnfdinfomodel import EtsiVnfdInfoModel
+from lcm.pub.utils.toscaparser.nsdmodel import EtsiNsdInfoModel
+from lcm.pub.utils.toscaparser.vnfdmodel import EtsiVnfdInfoModel
from lcm.pub.utils.toscaparser.parser import parse_nsd_model, parse_vnfd_model
diff --git a/lcm/pub/utils/toscaparser/baseinfomodel.py b/lcm/pub/utils/toscaparser/baseinfomodel.py
deleted file mode 100644
index 0e186f60..00000000
--- a/lcm/pub/utils/toscaparser/baseinfomodel.py
+++ /dev/null
@@ -1,105 +0,0 @@
-import os
-import urllib
-
-from toscaparser.tosca_template import ToscaTemplate
-
-from lcm.pub.utils.toscaparser.dataentityext import DataEntityExt
-
-
-class BaseInfoModel(object):
- def __init__(self, path, params):
- pass
-
- def buildToscaTemplate(self, path, params):
- file_name = None
- try:
- file_name = self._check_download_file(path)
- valid_params = self._validate_input_params(file_name, params)
- return self._create_tosca_template(file_name, valid_params)
- finally:
- if file_name != None and file_name != path and os.path.exists(file_name):
- try:
- os.remove(file_name)
- except Exception, e:
- pass
-
- def _validate_input_params(self, path, params):
- valid_params = {}
- if params and len(params) > 0:
- tmp = self._create_tosca_template(path, None)
- for key,value in params.items():
- if hasattr(tmp, 'inputs') and len(tmp.inputs) > 0:
- for input_def in tmp.inputs:
- if (input_def.name == key):
- valid_params[key] = DataEntityExt.validate_datatype(input_def.type, value)
-
- return valid_params
-
- def _create_tosca_template(self, file_name, valid_params):
- tosca_tpl = None
- try:
- tosca_tpl = ToscaTemplate(file_name, valid_params)
- print "-----------------------------"
- print '\n'.join(['%s:%s' % item for item in tosca_tpl.__dict__.items()])
- print "-----------------------------"
- return tosca_tpl
- finally:
- pass
- # if tosca_tpl != None and hasattr(tosca_tpl, "temp_dir") and os.path.exists(tosca_tpl.temp_dir):
- # try:
- # shutil.rmtree(tosca_tpl.temp_dir)
- # except Exception, e:
- # pass
- # # if tosca_tpl != None and tosca_tpl.temp_dir != None and os.path.exists(tosca_tpl.temp_dir):
- # # try:
- # # shutil.rmtree(tosca_tpl.temp_dir)
- # # except Exception, e:
- # # pass
-
- def _check_download_file(self, path):
- if (path.startswith("ftp") or path.startswith("sftp")):
- return self.downloadFileFromFtpServer(path)
- elif (path.startswith("http")):
- return self.download_file_from_httpserver(path)
- return path
-
- def download_file_from_httpserver(self, path):
- path = path.encode("utf-8")
- tmps = str.split(path, '/')
- localFileName = tmps[len(tmps) - 1]
- urllib.urlretrieve(path, localFileName)
- return localFileName
-
- def downloadFileFromFtpServer(self, path):
- path = path.encode("utf-8")
- tmp = str.split(path, '://')
- protocol = tmp[0]
- tmp = str.split(tmp[1], ':')
- if len(tmp) == 2:
- userName = tmp[0]
- tmp = str.split(tmp[1], '@')
- userPwd = tmp[0]
- index = tmp[1].index('/')
- hostIp = tmp[1][0:index]
- remoteFileName = tmp[1][index:len(tmp[1])]
- if protocol.lower() == 'ftp':
- hostPort = 21
- else:
- hostPort = 22
-
- if len(tmp) == 3:
- userName = tmp[0]
- userPwd = str.split(tmp[1], '@')[0]
- hostIp = str.split(tmp[1], '@')[1]
- index = tmp[2].index('/')
- hostPort = tmp[2][0:index]
- remoteFileName = tmp[2][index:len(tmp[2])]
-
- localFileName = str.split(remoteFileName, '/')
- localFileName = localFileName[len(localFileName) - 1]
-
- if protocol.lower() == 'sftp':
- self.sftp_get(userName, userPwd, hostIp, hostPort, remoteFileName, localFileName)
- else:
- self.ftp_get(userName, userPwd, hostIp, hostPort, remoteFileName, localFileName)
- return localFileName
diff --git a/lcm/pub/utils/toscaparser/basemodel.py b/lcm/pub/utils/toscaparser/basemodel.py
new file mode 100644
index 00000000..143120e6
--- /dev/null
+++ b/lcm/pub/utils/toscaparser/basemodel.py
@@ -0,0 +1,178 @@
+import copy
+import json
+import os
+import re
+import shutil
+import urllib
+
+from toscaparser.functions import GetInput
+from toscaparser.tosca_template import ToscaTemplate
+
+from lcm.pub.utils.toscaparser.dataentityext import DataEntityExt
+
+
+class BaseInfoModel(object):
+
+ def buildToscaTemplate(self, path, params):
+ file_name = None
+ try:
+ file_name = self._check_download_file(path)
+ valid_params = self._validate_input_params(file_name, params)
+ return self._create_tosca_template(file_name, valid_params)
+ finally:
+ if file_name != None and file_name != path and os.path.exists(file_name):
+ try:
+ os.remove(file_name)
+ except Exception, e:
+ pass
+
+ def _validate_input_params(self, path, params):
+ valid_params = {}
+ if params and len(params) > 0:
+ tmp = self._create_tosca_template(path, None)
+ for key,value in params.items():
+ if hasattr(tmp, 'inputs') and len(tmp.inputs) > 0:
+ for input_def in tmp.inputs:
+ if (input_def.name == key):
+ valid_params[key] = DataEntityExt.validate_datatype(input_def.type, value)
+
+ return valid_params
+
+ def _create_tosca_template(self, file_name, valid_params):
+ tosca_tpl = None
+ try:
+ tosca_tpl = ToscaTemplate(file_name, valid_params)
+ print "-----------------------------"
+ print '\n'.join(['%s:%s' % item for item in tosca_tpl.__dict__.items()])
+ print "-----------------------------"
+ return tosca_tpl
+ finally:
+ if tosca_tpl != None and hasattr(tosca_tpl, "temp_dir") and os.path.exists(tosca_tpl.temp_dir):
+ try:
+ shutil.rmtree(tosca_tpl.temp_dir)
+ except Exception, e:
+ pass
+
+ def _check_download_file(self, path):
+ if (path.startswith("ftp") or path.startswith("sftp")):
+ return self.downloadFileFromFtpServer(path)
+ elif (path.startswith("http")):
+ return self.download_file_from_httpserver(path)
+ return path
+
+ def download_file_from_httpserver(self, path):
+ path = path.encode("utf-8")
+ tmps = str.split(path, '/')
+ localFileName = tmps[len(tmps) - 1]
+ urllib.urlretrieve(path, localFileName)
+ return localFileName
+
+ def downloadFileFromFtpServer(self, path):
+ path = path.encode("utf-8")
+ tmp = str.split(path, '://')
+ protocol = tmp[0]
+ tmp = str.split(tmp[1], ':')
+ if len(tmp) == 2:
+ userName = tmp[0]
+ tmp = str.split(tmp[1], '@')
+ userPwd = tmp[0]
+ index = tmp[1].index('/')
+ hostIp = tmp[1][0:index]
+ remoteFileName = tmp[1][index:len(tmp[1])]
+ if protocol.lower() == 'ftp':
+ hostPort = 21
+ else:
+ hostPort = 22
+
+ if len(tmp) == 3:
+ userName = tmp[0]
+ userPwd = str.split(tmp[1], '@')[0]
+ hostIp = str.split(tmp[1], '@')[1]
+ index = tmp[2].index('/')
+ hostPort = tmp[2][0:index]
+ remoteFileName = tmp[2][index:len(tmp[2])]
+
+ localFileName = str.split(remoteFileName, '/')
+ localFileName = localFileName[len(localFileName) - 1]
+
+ if protocol.lower() == 'sftp':
+ self.sftp_get(userName, userPwd, hostIp, hostPort, remoteFileName, localFileName)
+ else:
+ self.ftp_get(userName, userPwd, hostIp, hostPort, remoteFileName, localFileName)
+ return localFileName
+
+ def buidMetadata(self, tosca):
+ if 'metadata' in tosca.tpl:
+ self.metadata = copy.deepcopy(tosca.tpl['metadata'])
+
+ def buildProperties(self, nodeTemplate, parsed_params):
+ properties = {}
+ isMappingParams = parsed_params and len(parsed_params) > 0
+ for k, item in nodeTemplate.get_properties().items():
+ properties[k] = item.value
+ if isinstance(item.value, GetInput):
+ if item.value.result() and isMappingParams:
+ properties[k] = DataEntityExt.validate_datatype(item.type, item.value.result())
+ else:
+ tmp = {}
+ tmp[item.value.name] = item.value.input_name
+ properties[k] = tmp
+ if 'attributes' in nodeTemplate.entity_tpl:
+ for k, item in nodeTemplate.entity_tpl['attributes'].items():
+ properties[k] = str(item)
+ return properties
+
+ def buildProperties(self, nodeTemplate, parsed_params):
+ properties = {}
+ isMappingParams = parsed_params and len(parsed_params) > 0
+ for k, item in nodeTemplate.get_properties().items():
+ properties[k] = item.value
+ if isinstance(item.value, GetInput):
+ if item.value.result() and isMappingParams:
+ properties[k] = DataEntityExt.validate_datatype(item.type, item.value.result())
+ else:
+ tmp = {}
+ tmp[item.value.name] = item.value.input_name
+ properties[k] = tmp
+ if 'attributes' in nodeTemplate.entity_tpl:
+ for k, item in nodeTemplate.entity_tpl['attributes'].items():
+ properties[k] = str(item)
+ return properties
+
+
+ def verify_properties(self, props, inputs, parsed_params):
+ ret_props = {}
+ if (props and len(props) > 0):
+ for key, value in props.items():
+ ret_props[key] = self._verify_value(value, inputs, parsed_params)
+ # if isinstance(value, str):
+ # ret_props[key] = self._verify_string(inputs, parsed_params, value);
+ # continue
+ # if isinstance(value, list):
+ # ret_props[key] = map(lambda x: self._verify_dict(inputs, parsed_params, x), value)
+ # continue
+ # if isinstance(value, dict):
+ # ret_props[key] = self._verify_map(inputs, parsed_params, value)
+ # continue
+ # ret_props[key] = value
+ return ret_props
+
+ def build_requirements(self, node_template):
+ rets = []
+ for req in node_template.requirements:
+ for req_name, req_value in req.items():
+ if (isinstance(req_value, dict)):
+ if ('node' in req_value and req_value['node'] not in node_template.templates):
+ continue # No target requirement for aria parser, not add to result.
+ rets.append({req_name : req_value})
+ return rets
+
+ def buildCapabilities(self, nodeTemplate, inputs, ret):
+ capabilities = json.dumps(nodeTemplate.entity_tpl.get('capabilities', None))
+ match = re.findall(r'\{"get_input":\s*"([\w|\-]+)"\}',capabilities)
+ for m in match:
+ aa= [input_def for input_def in inputs
+ if m == input_def.name][0]
+ capabilities = re.sub(r'\{"get_input":\s*"([\w|\-]+)"\}', json.dumps(aa.default), capabilities,1)
+ if capabilities != 'null':
+ ret['capabilities'] = json.loads(capabilities) \ No newline at end of file
diff --git a/lcm/pub/utils/toscaparser/etsinsdinfomodel.py b/lcm/pub/utils/toscaparser/etsinsdinfomodel.py
deleted file mode 100644
index 693a7fdd..00000000
--- a/lcm/pub/utils/toscaparser/etsinsdinfomodel.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from lcm.pub.utils.toscaparser.baseinfomodel import BaseInfoModel
-
-
-class EtsiNsdInfoModel(BaseInfoModel):
-
- def __init__(self, path, params):
- tosca = self.buildToscaTemplate(path, params)
- self.parseModel(tosca)
-
-
- def parseModel(self, tosca):
- pass \ No newline at end of file
diff --git a/lcm/pub/utils/toscaparser/nsdmodel.py b/lcm/pub/utils/toscaparser/nsdmodel.py
new file mode 100644
index 00000000..f0512068
--- /dev/null
+++ b/lcm/pub/utils/toscaparser/nsdmodel.py
@@ -0,0 +1,59 @@
+import functools
+
+from lcm.pub.utils.toscaparser.basemodel import BaseInfoModel
+
+
+class EtsiNsdInfoModel(BaseInfoModel):
+
+ def __init__(self, path, params):
+ tosca = self.buildToscaTemplate(path, params)
+ self.parseModel(tosca)
+
+ def parseModel(self, tosca):
+ self.buidMetadata(tosca)
+ if hasattr(tosca, 'topology_template') and hasattr(tosca.topology_template, 'inputs'):
+ self.inputs = self.buildInputs(tosca.topology_template.inputs)
+
+ nodeTemplates = map(functools.partial(self.buildNode, inputs=tosca.inputs, parsed_params=tosca.parsed_params),
+ tosca.nodetemplates)
+
+ # self.vnfs = self._get_all_vnf(nodeTemplates)
+ # self.pnfs = self._get_all_pnf(nodeTemplates)
+ # self.vls = self.get_all_vl(nodeTemplates)
+ # self.cps = self.get_all_cp(nodeTemplates)
+ # self.routers = self.get_all_router(nodeTemplates)
+ # self.fps = self._get_all_fp(nodeTemplates)
+ # self.vnffgs = self._get_all_vnffg(tosca.topology_template.groups)
+ # self.server_groups = self.get_all_server_group(tosca.topology_template.groups)
+ # self.ns_exposed = self.get_all_endpoint_exposed(tosca.topology_template)
+ # self.policies = self._get_policies_scaling(tosca.topology_template.policies)
+ # self.ns_flavours = self.get_all_flavour(tosca.topology_template.groups)
+ # self.nested_ns = self.get_all_nested_ns(nodeTemplates)
+
+ def buildInputs(self, top_inputs):
+ ret = {}
+ for tmpinput in top_inputs:
+ tmp = {}
+ tmp['type'] = tmpinput.type
+ tmp['description'] = tmpinput.description
+ tmp['default'] = tmpinput.default
+
+ ret[tmpinput.name] = tmp
+ return ret
+
+ def buildNode(self, nodeTemplate, inputs, parsed_params):
+ ret ={}
+ ret['name'] = nodeTemplate.name
+ ret['nodeType'] = nodeTemplate.type
+ if 'description' in nodeTemplate.entity_tpl:
+ ret['description'] = nodeTemplate.entity_tpl['description']
+ else:
+ ret['description'] = ''
+ props = self.buildProperties(nodeTemplate, parsed_params)
+ ret['properties'] = self.verify_properties(props, inputs, parsed_params)
+ ret['requirements'] = self.build_requirements(nodeTemplate)
+ self.buildCapabilities(nodeTemplate, inputs, ret)
+ # self.buildArtifacts(nodeTemplate, inputs, ret)
+ # interfaces = self.build_interfaces(nodeTemplate)
+ # if interfaces: ret['interfaces'] = interfaces
+ return ret
diff --git a/lcm/pub/utils/toscaparser/etsivnfdinfomodel.py b/lcm/pub/utils/toscaparser/vnfdmodel.py
index 39e9a18b..39e9a18b 100644
--- a/lcm/pub/utils/toscaparser/etsivnfdinfomodel.py
+++ b/lcm/pub/utils/toscaparser/vnfdmodel.py
diff --git a/lcm/urls.py b/lcm/urls.py
index c9a808b3..9471def9 100644
--- a/lcm/urls.py
+++ b/lcm/urls.py
@@ -23,6 +23,7 @@ urlpatterns = [
url(r'^', include('lcm.ns.sfcs.urls')),
url(r'^', include('lcm.ns.urls')),
url(r'^', include('lcm.jobs.urls')),
+ url(r'^', include('lcm.workflows.urls')),
]
# regist to MSB when startup
diff --git a/lcm/workflows/__init__.py b/lcm/workflows/__init__.py
new file mode 100644
index 00000000..c7b6818e
--- /dev/null
+++ b/lcm/workflows/__init__.py
@@ -0,0 +1,13 @@
+# Copyright 2017 ZTE Corporation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
diff --git a/lcm/workflows/tests.py b/lcm/workflows/tests.py
new file mode 100644
index 00000000..31651624
--- /dev/null
+++ b/lcm/workflows/tests.py
@@ -0,0 +1,31 @@
+# Copyright 2017 ZTE Corporation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+import json
+from django.test import Client
+from rest_framework import status
+
+
+class WorkflowViewTest(unittest.TestCase):
+ def setUp(self):
+ self.client = Client()
+
+ def tearDown(self):
+ pass
+
+ def test_deploy_workflow(self):
+ response = self.client.post("/api/nslcm/v1/workflow",
+ {"filePath": "/home/init.zip"}, format='json')
+ self.assertEqual(status.HTTP_202_ACCEPTED, response.status_code, response.content)
diff --git a/lcm/workflows/urls.py b/lcm/workflows/urls.py
new file mode 100644
index 00000000..2545ffba
--- /dev/null
+++ b/lcm/workflows/urls.py
@@ -0,0 +1,23 @@
+# Copyright 2017 ZTE Corporation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from django.conf.urls import url
+from rest_framework.urlpatterns import format_suffix_patterns
+from lcm.workflows import views
+
+urlpatterns = [
+ url(r'^api/nslcm/v1/workflow$', views.deploy_workflow, name='deploy_workflow'),
+]
+
+urlpatterns = format_suffix_patterns(urlpatterns)
diff --git a/lcm/workflows/views.py b/lcm/workflows/views.py
new file mode 100644
index 00000000..92f029fb
--- /dev/null
+++ b/lcm/workflows/views.py
@@ -0,0 +1,47 @@
+# Copyright 2017 ZTE Corporation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import logging
+import traceback
+
+from rest_framework import status
+from rest_framework.decorators import api_view
+from rest_framework.response import Response
+
+from lcm.pub.database import models
+from lcm.pub.utils.syscomm import fun_name
+from lcm.pub.utils.values import ignore_case_get
+
+
+logger = logging.getLogger(__name__)
+
+
+@api_view(http_method_names=['POST'])
+def deploy_workflow(request, *args, **kwargs):
+ logger.debug("Enter %s", fun_name())
+ file_path = ignore_case_get(request.data, "filePath")
+ logger.debug("file_path is %s", file_path)
+ ret = None
+ try:
+ ret = [0, "TODO"]
+ except:
+ logger.error(traceback.format_exc())
+ return Response(data={'error': str(sys.exc_info())}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+ logger.debug("Leave %s, Return value is %s", fun_name(), ret)
+ return Response(data=ret[1], status=status.HTTP_202_ACCEPTED)
+
+
+
+
+
diff --git a/resources/dbscripts/mysql/vfc-nfvo-lcm-createobj.sql b/resources/dbscripts/mysql/vfc-nfvo-lcm-createobj.sql
index 36c9ffb6..b2588f05 100644
--- a/resources/dbscripts/mysql/vfc-nfvo-lcm-createobj.sql
+++ b/resources/dbscripts/mysql/vfc-nfvo-lcm-createobj.sql
@@ -273,5 +273,7 @@ DROP TABLE IF EXISTS NFVO_WF_PLAN;
CREATE TABLE NFVO_WF_PLAN (
`DEPLOYEDID` varchar(255) NOT NULL PRIMARY KEY,
`PROCESSID` varchar(255) NOT NULL,
+ `STATUS` varchar(255) NOT NULL,
+ `MESSAGE` varchar(1024) NULL,
`PLANNAME` varchar(255) NOT NULL
);