aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfujinhua <fu.jinhua@zte.com.cn>2017-08-18 15:03:18 +0800
committerfujinhua <fu.jinhua@zte.com.cn>2017-08-18 15:03:58 +0800
commit25bbfb14f191992f407d957d524ffb1cd0378655 (patch)
tree3968484183acb96c0b6f7babb07e43e622466fd6
parent169a896f8fc4db5a0054d31bb5bfd254f2352bb0 (diff)
Add seed codes of nfvo catalog
Change-Id: Id0646870cbb297cbeddfe223feb2235f11a4a511 Issue-Id: VFC-108 Signed-off-by: fujinhua <fu.jinhua@zte.com.cn>
-rw-r--r--.gitignore3
-rw-r--r--README.md15
-rw-r--r--assembly.xml68
-rw-r--r--catalog/__init__.py13
-rw-r--r--catalog/pub/__init__.py13
-rw-r--r--catalog/pub/config/__init__.py13
-rw-r--r--catalog/pub/config/config.py60
-rw-r--r--catalog/pub/database/__init__.py13
-rw-r--r--catalog/pub/database/models.py23
-rw-r--r--catalog/pub/exceptions.py17
-rw-r--r--catalog/pub/msapi/__init__.py13
-rw-r--r--catalog/pub/msapi/sdc.py69
-rw-r--r--catalog/pub/utils/__init__.py13
-rw-r--r--catalog/pub/utils/fileutil.py52
-rw-r--r--catalog/pub/utils/restcall.py95
-rw-r--r--catalog/pub/utils/syscomm.py19
-rw-r--r--catalog/pub/utils/timeutil.py19
-rw-r--r--catalog/pub/utils/values.py25
-rw-r--r--catalog/samples/__init__.py13
-rw-r--r--catalog/samples/tests.py32
-rw-r--r--catalog/samples/urls.py20
-rw-r--r--catalog/samples/views.py65
-rw-r--r--catalog/settings.py151
-rw-r--r--catalog/urls.py26
-rw-r--r--catalog/wsgi.py22
-rw-r--r--initialize.sh16
-rw-r--r--logs/empty.txt0
-rw-r--r--manage.py22
-rw-r--r--pom.xml52
-rw-r--r--requirements.txt21
-rw-r--r--resources/bin/initDB.sh50
-rw-r--r--resources/dbscripts/mysql/vfc-nfvo-catalog-createdb.sql31
-rw-r--r--resources/dbscripts/mysql/vfc-nfvo-catalog-createobj.sql23
-rw-r--r--run.sh16
-rw-r--r--static/catalog/empty.txt0
-rw-r--r--stop.sh16
-rw-r--r--tox.ini10
37 files changed, 1129 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..67c551bb
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+logs/*.log
+*.pyc
+.idea \ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 00000000..15867162
--- /dev/null
+++ b/README.md
@@ -0,0 +1,15 @@
+# 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.
+
+# Micro service of nfvo catalog.
diff --git a/assembly.xml b/assembly.xml
new file mode 100644
index 00000000..9143ac9f
--- /dev/null
+++ b/assembly.xml
@@ -0,0 +1,68 @@
+<!--
+ 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.
+-->
+<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>catalog</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <fileSets>
+ <fileSet>
+ <directory>catalog</directory>
+ <outputDirectory>/catalog</outputDirectory>
+ <includes>
+ <include>**/*.py</include>
+ <include>**/*.json</include>
+ <include>**/*.xml</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>logs</directory>
+ <outputDirectory>/logs</outputDirectory>
+ <includes>
+ <include>*.txt</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>static</directory>
+ <outputDirectory>/static</outputDirectory>
+ <includes>
+ <include>**/*.txt</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>resources</directory>
+ <outputDirectory>/resources</outputDirectory>
+ <includes>
+ <include>**/*.sh</include>
+ <include>**/*.sql</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>.</directory>
+ <outputDirectory>/</outputDirectory>
+ <includes>
+ <include>*.py</include>
+ <include>*.txt</include>
+ <include>*.sh</include>
+ <include>*.ini</include>
+ <include>*.md</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+ <baseDirectory>vfc/nfvo/catalog</baseDirectory>
+</assembly>
diff --git a/catalog/__init__.py b/catalog/__init__.py
new file mode 100644
index 00000000..c7b6818e
--- /dev/null
+++ b/catalog/__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/catalog/pub/__init__.py b/catalog/pub/__init__.py
new file mode 100644
index 00000000..c7b6818e
--- /dev/null
+++ b/catalog/pub/__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/catalog/pub/config/__init__.py b/catalog/pub/config/__init__.py
new file mode 100644
index 00000000..c7b6818e
--- /dev/null
+++ b/catalog/pub/config/__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/catalog/pub/config/config.py b/catalog/pub/config/config.py
new file mode 100644
index 00000000..0a64cb58
--- /dev/null
+++ b/catalog/pub/config/config.py
@@ -0,0 +1,60 @@
+# 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 os
+
+# [MSB]
+MSB_SERVICE_IP = '127.0.0.1'
+MSB_SERVICE_PORT = '80'
+
+# [REDIS]
+REDIS_HOST = '127.0.0.1'
+REDIS_PORT = '6379'
+REDIS_PASSWD = ''
+
+# [mysql]
+DB_IP = "127.0.0.1"
+DB_PORT = 3306
+DB_NAME = "nfvocatalog"
+DB_USER = "nfvocatalog"
+DB_PASSWD = "nfvocatalog"
+
+# [register]
+REG_TO_MSB_WHEN_START = True
+REG_TO_MSB_REG_URL = "/api/microservices/v1/services"
+REG_TO_MSB_REG_PARAM = {
+ "serviceName": "nfvocatalog",
+ "version": "v1",
+ "url": "/api/nfvocatalog/v1",
+ "protocol": "REST",
+ "visualRange": "1",
+ "nodes": [{
+ "ip": "127.0.0.1",
+ "port": "8806",
+ "ttl": 0
+ }]
+}
+
+# catalog path(values is defined in settings.py)
+CATALOG_ROOT_PATH = None
+CATALOG_URL_PATH = None
+
+# [sdc config]
+SDC_BASE_URL = "https://127.0.0.1:1234/api"
+SDC_USER = "admin"
+SDC_PASSWD = "admin"
+
+
+
+
+
diff --git a/catalog/pub/database/__init__.py b/catalog/pub/database/__init__.py
new file mode 100644
index 00000000..c7b6818e
--- /dev/null
+++ b/catalog/pub/database/__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/catalog/pub/database/models.py b/catalog/pub/database/models.py
new file mode 100644
index 00000000..2d2ee330
--- /dev/null
+++ b/catalog/pub/database/models.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.db import models
+
+
+class SampleModel(models.Model):
+ class Meta:
+ db_table = 'NFVO_SAMPLE'
+
+ id = models.CharField(db_column='SAMPLEID', primary_key=True, max_length=255)
+ name = models.CharField(db_column='SAMPLENAME', max_length=255)
+
diff --git a/catalog/pub/exceptions.py b/catalog/pub/exceptions.py
new file mode 100644
index 00000000..c994b46e
--- /dev/null
+++ b/catalog/pub/exceptions.py
@@ -0,0 +1,17 @@
+# 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.
+
+
+class CatalogException(Exception):
+ pass
diff --git a/catalog/pub/msapi/__init__.py b/catalog/pub/msapi/__init__.py
new file mode 100644
index 00000000..c7b6818e
--- /dev/null
+++ b/catalog/pub/msapi/__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/catalog/pub/msapi/sdc.py b/catalog/pub/msapi/sdc.py
new file mode 100644
index 00000000..a4b157c3
--- /dev/null
+++ b/catalog/pub/msapi/sdc.py
@@ -0,0 +1,69 @@
+# 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 json
+import logging
+
+from catalog.pub.exceptions import CatalogException
+from catalog.pub.utils import restcall
+from catalog.pub.config.config import SDC_BASE_URL, SDC_USER, SDC_PASSWD
+
+logger = logging.getLogger(__name__)
+
+ASSETTYPE_RESOURCES = "resources"
+ASSETTYPE_SERVICES = "services"
+
+def call_sdc(resource, method, content=''):
+ return restcall.call_req(base_url=SDC_BASE_URL,
+ user=SDC_USER,
+ passwd=SDC_PASSWD,
+ auth_type=restcall.rest_no_auth,
+ resource=resource,
+ method=method,
+ content=content)
+
+def get_artifacts(asset_type):
+ resource = "/sdc/v1/catalog/{assetType}"
+ resource = resource.format(assetType=asset_type)
+ ret = call_sdc(resource, "GET")
+ if ret[0] != 0:
+ logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
+ raise CatalogException("Failed to query artifacts(%s) from sdc." % asset_type)
+ return json.JSONDecoder().decode(ret[1])
+
+def get_artifact(asset_type, csar_id):
+ artifacts = get_artifacts(asset_type)
+ for artifact in artifacts:
+ if artifact["uuid"] == csar_id:
+ return artifact
+ raise CatalogException("Failed to query artifact(%s,%s) from sdc." % (asset_type, csar_id))
+
+def delete_artifact(asset_type, asset_id, artifact_id):
+ resource = "/sdc/v1/catalog/{assetType}/{uuid}/artifacts/{artifactUUID}"
+ resource = resource.format(assetType=asset_type, uuid=asset_id, artifactUUID=artifact_id)
+ ret = call_sdc(resource, "DELETE")
+ if ret[0] != 0:
+ logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
+ raise CatalogException("Failed to delete artifacts(%s) from sdc." % artifact_id)
+ return json.JSONDecoder().decode(ret[1])
+
+def download_artifacts(download_url, local_path):
+ ret = restcall.call_req(base_url=download_url,
+ user=SDC_USER,
+ passwd=SDC_PASSWD,
+ auth_type=rest_no_auth,
+ resource="",
+ method="GET")
+ # TODO:
+
diff --git a/catalog/pub/utils/__init__.py b/catalog/pub/utils/__init__.py
new file mode 100644
index 00000000..c7b6818e
--- /dev/null
+++ b/catalog/pub/utils/__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/catalog/pub/utils/fileutil.py b/catalog/pub/utils/fileutil.py
new file mode 100644
index 00000000..bd1a4aff
--- /dev/null
+++ b/catalog/pub/utils/fileutil.py
@@ -0,0 +1,52 @@
+# 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 os
+import shutil
+import logging
+import traceback
+import urllib2
+
+logger = logging.getLogger(__name__)
+
+
+def make_dirs(path):
+ if not os.path.exists(path):
+ os.makedirs(path, 0777)
+
+
+def delete_dirs(path):
+ try:
+ if os.path.exists(path):
+ shutil.rmtree(path)
+ except Exception as e:
+ logger.error(traceback.format_exc())
+ logger.error("Failed to delete %s:%s", path, e.message)
+
+
+def download_file_from_http(url, local_dir, file_name):
+ local_file_name = os.path.join(local_dir, file_name)
+ is_download_ok = False
+ try:
+ make_dirs(local_dir)
+ r = urllib2.Request(url)
+ req = urllib2.urlopen(r)
+ save_file = open(local_file_name, 'wb')
+ save_file.write(req.read())
+ save_file.close()
+ req.close()
+ is_download_ok = True
+ except:
+ logger.error(traceback.format_exc())
+ logger.error("Failed to download %s to %s.", url, local_file_name)
+ return is_download_ok, local_file_name
diff --git a/catalog/pub/utils/restcall.py b/catalog/pub/utils/restcall.py
new file mode 100644
index 00000000..a027fae4
--- /dev/null
+++ b/catalog/pub/utils/restcall.py
@@ -0,0 +1,95 @@
+# 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 sys
+import traceback
+import logging
+import urllib2
+import uuid
+import httplib2
+
+from catalog.pub.config.config import MSB_SERVICE_IP, MSB_SERVICE_PORT
+
+rest_no_auth, rest_oneway_auth, rest_bothway_auth = 0, 1, 2
+HTTP_200_OK, HTTP_201_CREATED, HTTP_204_NO_CONTENT, HTTP_202_ACCEPTED = '200', '201', '204', '202'
+status_ok_list = [HTTP_200_OK, HTTP_201_CREATED, HTTP_204_NO_CONTENT, HTTP_202_ACCEPTED]
+HTTP_404_NOTFOUND, HTTP_403_FORBIDDEN, HTTP_401_UNAUTHORIZED, HTTP_400_BADREQUEST = '404', '403', '401', '400'
+
+logger = logging.getLogger(__name__)
+
+
+def call_req(base_url, user, passwd, auth_type, resource, method, content=''):
+ callid = str(uuid.uuid1())
+ logger.debug("[%s]call_req('%s','%s','%s',%s,'%s','%s','%s')" % (
+ callid, base_url, user, passwd, auth_type, resource, method, content))
+ ret = None
+ resp_status = ''
+ try:
+ full_url = combine_url(base_url, resource)
+ headers = {'content-type': 'application/json', 'accept': 'application/json'}
+ if user:
+ headers['Authorization'] = 'Basic ' + ('%s:%s' % (user, passwd)).encode("base64")
+ ca_certs = None
+ for retry_times in range(3):
+ http = httplib2.Http(ca_certs=ca_certs, disable_ssl_certificate_validation=(auth_type == rest_no_auth))
+ http.follow_all_redirects = True
+ try:
+ resp, resp_content = http.request(full_url, method=method.upper(), body=content, headers=headers)
+ resp_status, resp_body = resp['status'], resp_content.decode('UTF-8')
+ logger.debug("[%s][%d]status=%s,resp_body=%s)" % (callid, retry_times, resp_status, resp_body))
+ if resp_status in status_ok_list:
+ ret = [0, resp_body, resp_status]
+ else:
+ ret = [1, resp_body, resp_status]
+ break
+ except Exception as ex:
+ if 'httplib.ResponseNotReady' in str(sys.exc_info()):
+ logger.debug("retry_times=%d", retry_times)
+ logger.error(traceback.format_exc())
+ ret = [1, "Unable to connect to %s" % full_url, resp_status]
+ continue
+ raise ex
+ except urllib2.URLError as err:
+ ret = [2, str(err), resp_status]
+ except Exception as ex:
+ logger.error(traceback.format_exc())
+ logger.error("[%s]ret=%s" % (callid, str(sys.exc_info())))
+ res_info = str(sys.exc_info())
+ if 'httplib.ResponseNotReady' in res_info:
+ res_info = "The URL[%s] request failed or is not responding." % full_url
+ ret = [3, res_info, resp_status]
+ except:
+ logger.error(traceback.format_exc())
+ ret = [4, str(sys.exc_info()), resp_status]
+
+ logger.debug("[%s]ret=%s" % (callid, str(ret)))
+ return ret
+
+
+def req_by_msb(resource, method, content=''):
+ base_url = "http://%s:%s/" % (MSB_SERVICE_IP, MSB_SERVICE_PORT)
+ return call_req(base_url, "", "", rest_no_auth, resource, method, content)
+
+
+def combine_url(base_url, resource):
+ full_url = None
+ if base_url.endswith('/') and resource.startswith('/'):
+ full_url = base_url[:-1] + resource
+ elif base_url.endswith('/') and not resource.startswith('/'):
+ full_url = base_url + resource
+ elif not base_url.endswith('/') and resource.startswith('/'):
+ full_url = base_url + resource
+ else:
+ full_url = base_url + '/' + resource
+ return full_url
diff --git a/catalog/pub/utils/syscomm.py b/catalog/pub/utils/syscomm.py
new file mode 100644
index 00000000..89219ec9
--- /dev/null
+++ b/catalog/pub/utils/syscomm.py
@@ -0,0 +1,19 @@
+# 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 inspect
+
+
+def fun_name():
+ return inspect.stack()[1][3]
diff --git a/catalog/pub/utils/timeutil.py b/catalog/pub/utils/timeutil.py
new file mode 100644
index 00000000..1d97e9d7
--- /dev/null
+++ b/catalog/pub/utils/timeutil.py
@@ -0,0 +1,19 @@
+# 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 datetime
+
+
+def now_time(fmt="%Y-%m-%d %H:%M:%S"):
+ return datetime.datetime.now().strftime(fmt)
diff --git a/catalog/pub/utils/values.py b/catalog/pub/utils/values.py
new file mode 100644
index 00000000..e3ac599e
--- /dev/null
+++ b/catalog/pub/utils/values.py
@@ -0,0 +1,25 @@
+# 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.
+
+
+def ignore_case_get(args, key, def_val=""):
+ if not key:
+ return def_val
+ if key in args:
+ return args[key]
+ for old_key in args:
+ if old_key.upper() == key.upper():
+ return args[old_key]
+ return def_val
+
diff --git a/catalog/samples/__init__.py b/catalog/samples/__init__.py
new file mode 100644
index 00000000..c7b6818e
--- /dev/null
+++ b/catalog/samples/__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/catalog/samples/tests.py b/catalog/samples/tests.py
new file mode 100644
index 00000000..d2673d4b
--- /dev/null
+++ b/catalog/samples/tests.py
@@ -0,0 +1,32 @@
+# 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 SampleViewTest(unittest.TestCase):
+ def setUp(self):
+ self.client = Client()
+
+ def tearDown(self):
+ pass
+
+ def test_sample(self):
+ response = self.client.get("/samples/")
+ self.assertEqual(status.HTTP_200_OK, response.status_code, response.content)
+ resp_data = json.loads(response.content)
+ self.assertEqual({"status": "active"}, resp_data)
diff --git a/catalog/samples/urls.py b/catalog/samples/urls.py
new file mode 100644
index 00000000..7d65b36c
--- /dev/null
+++ b/catalog/samples/urls.py
@@ -0,0 +1,20 @@
+# 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 catalog.samples import views
+
+urlpatterns = [
+ url(r'^api/nfvocatalog/v1/mandb/(?P<modelName>[a-zA-Z\-]+)$', views.TablesList.as_view()),
+ url(r'^samples/$', views.SampleList.as_view()), ]
diff --git a/catalog/samples/views.py b/catalog/samples/views.py
new file mode 100644
index 00000000..bc1ebea2
--- /dev/null
+++ b/catalog/samples/views.py
@@ -0,0 +1,65 @@
+# 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.views import APIView
+from rest_framework.response import Response
+from rest_framework import status
+from catalog.pub.database import models
+
+
+logger = logging.getLogger(__name__)
+
+
+class SampleList(APIView):
+ """
+ List all samples.
+ """
+ def get(self, request, format=None):
+ logger.debug("get")
+ return Response({"status": "active"})
+
+class TablesList(APIView):
+ def delete(self, request, modelName):
+ logger.debug("Start delete model %s", modelName)
+ try:
+ modelNames = modelName.split("-")
+ for name in modelNames:
+ model_obj = eval("models.%s.objects" % name)
+ model_obj.filter().delete()
+ logger.debug("End delete model %s", name)
+ except:
+ logger.error(traceback.format_exc())
+ return Response(data={"error": "failed"},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+ return Response(data={}, status=status.HTTP_204_NO_CONTENT)
+
+
+ def get(self, request, modelName):
+ logger.debug("Get model %s", modelName)
+ count = 0
+ try:
+ model_obj = eval("models.%s.objects" % modelName)
+ count = len(model_obj.filter())
+ except:
+ logger.error(traceback.format_exc())
+ return Response(data={"error": "failed"},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+ return Response(data={"count": count}, status=status.HTTP_200_OK)
+
+
+
+
diff --git a/catalog/settings.py b/catalog/settings.py
new file mode 100644
index 00000000..629f68a1
--- /dev/null
+++ b/catalog/settings.py
@@ -0,0 +1,151 @@
+# 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 os
+import sys
+
+import redisco
+
+from catalog.pub.config.config import REDIS_HOST, REDIS_PORT, REDIS_PASSWD
+from catalog.pub.config.config import DB_NAME, DB_IP, DB_USER, DB_PASSWD, DB_PORT
+from catalog.pub.config import config
+
+# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
+BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+
+# Quick-start development settings - unsuitable for production
+# See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/
+
+# SECURITY WARNING: keep the secret key used in production secret!
+SECRET_KEY = '3o-wney!99y)^h3v)0$j16l9=fdjxcb+a8g+q3tfbahcnu2b0o'
+
+# SECURITY WARNING: don't run with debug turned on in production!
+DEBUG = True
+
+ALLOWED_HOSTS = []
+
+# Application definition
+
+INSTALLED_APPS = [
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ 'django.contrib.messages',
+ 'django.contrib.staticfiles',
+ 'rest_framework',
+ 'catalog.pub.database',
+ 'catalog.samples'
+]
+
+MIDDLEWARE_CLASSES = [
+ 'django.middleware.security.SecurityMiddleware',
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.middleware.common.CommonMiddleware',
+ 'django.middleware.csrf.CsrfViewMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
+ 'django.contrib.messages.middleware.MessageMiddleware',
+ 'django.middleware.clickjacking.XFrameOptionsMiddleware',
+]
+
+ROOT_URLCONF = 'catalog.urls'
+
+WSGI_APPLICATION = 'catalog.wsgi.application'
+
+REST_FRAMEWORK = {
+ 'DEFAULT_RENDERER_CLASSES': (
+ 'rest_framework.renderers.JSONRenderer',
+ ),
+
+ 'DEFAULT_PARSER_CLASSES': (
+ 'rest_framework.parsers.JSONParser',
+ 'rest_framework.parsers.MultiPartParser',
+ # 'rest_framework.parsers.FormParser',
+ # 'rest_framework.parsers.FileUploadParser',
+ )
+}
+
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.mysql',
+ 'NAME': DB_NAME,
+ 'HOST': DB_IP,
+ 'PORT': DB_PORT,
+ 'USER': DB_USER,
+ 'PASSWORD': DB_PASSWD,
+ },
+}
+
+redisco.connection_setup(host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWD, db=0)
+# CACHE_BACKEND = 'redis_cache.cache://%s@%s:%s' % (REDIS_PASSWD, REDIS_HOST, REDIS_PORT)
+
+TIME_ZONE = 'UTC'
+
+# Static files (CSS, JavaScript, Images)
+# https://docs.djangoproject.com/en/1.6/howto/static-files/
+
+STATIC_URL = '/static/'
+
+STATICFILES_DIRS = [
+ os.path.join(BASE_DIR, "static")
+]
+
+config.CATALOG_ROOT_PATH = os.path.join(STATICFILES_DIRS[0], "catalog")
+config.CATALOG_URL_PATH = "static/catalog"
+
+LOGGING = {
+ 'version': 1,
+ 'disable_existing_loggers': True,
+ 'formatters': {
+ 'standard': {
+ 'format': '%(asctime)s:[%(name)s]:[%(filename)s]-[%(lineno)d] [%(levelname)s]:%(message)s',
+ },
+ },
+ 'filters': {
+ },
+ 'handlers': {
+ 'catalog_handler': {
+ 'level': 'DEBUG',
+ 'class': 'logging.handlers.RotatingFileHandler',
+ 'filename': os.path.join(BASE_DIR, 'logs/runtime_catalog.log'),
+ 'formatter': 'standard',
+ 'maxBytes': 1024 * 1024 * 50,
+ 'backupCount': 5,
+ },
+ },
+
+ 'loggers': {
+ 'catalog': {
+ 'handlers': ['catalog_handler'],
+ 'level': 'DEBUG',
+ 'propagate': False
+ },
+ }
+}
+
+if 'test' in sys.argv:
+ config.REG_TO_MSB_WHEN_START = False
+ DATABASES = {}
+ DATABASES['default'] = {
+ 'ENGINE': 'django.db.backends.sqlite3',
+ 'NAME': ':memory:',
+ }
+ REST_FRAMEWORK = {}
+ import platform
+
+ if platform.system() == 'Linux':
+ TEST_RUNNER = 'xmlrunner.extra.djangotestrunner.XMLTestRunner'
+ TEST_OUTPUT_VERBOSE = True
+ TEST_OUTPUT_DESCRIPTIONS = True
+ TEST_OUTPUT_DIR = 'test-reports'
diff --git a/catalog/urls.py b/catalog/urls.py
new file mode 100644
index 00000000..46ae345c
--- /dev/null
+++ b/catalog/urls.py
@@ -0,0 +1,26 @@
+# 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 include, url
+from catalog.pub.config.config import REG_TO_MSB_WHEN_START, REG_TO_MSB_REG_URL, REG_TO_MSB_REG_PARAM
+
+urlpatterns = [
+ url(r'^', include('catalog.samples.urls')),
+]
+
+# regist to MSB when startup
+if REG_TO_MSB_WHEN_START:
+ import json
+ from catalog.pub.utils.restcall import req_by_msb
+ req_by_msb(REG_TO_MSB_REG_URL, "POST", json.JSONEncoder().encode(REG_TO_MSB_REG_PARAM))
diff --git a/catalog/wsgi.py b/catalog/wsgi.py
new file mode 100644
index 00000000..35f6db05
--- /dev/null
+++ b/catalog/wsgi.py
@@ -0,0 +1,22 @@
+# 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 os
+
+from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "catalog.settings")
+
+application = get_wsgi_application()
diff --git a/initialize.sh b/initialize.sh
new file mode 100644
index 00000000..3425019b
--- /dev/null
+++ b/initialize.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# 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.
+
+pip install -r requirements.txt
diff --git a/logs/empty.txt b/logs/empty.txt
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/logs/empty.txt
diff --git a/manage.py b/manage.py
new file mode 100644
index 00000000..74b03610
--- /dev/null
+++ b/manage.py
@@ -0,0 +1,22 @@
+# 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 os
+import sys
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "catalog.settings")
+
+if __name__ == "__main__":
+ from django.core.management import execute_from_command_line
+ execute_from_command_line(sys.argv)
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 00000000..0ca4b5ec
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <groupId>org.onap.oparent</groupId>
+ <artifactId>oparent</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.onap.vfc.nfvo.catalog</groupId>
+ <artifactId>vfc-nfvo-catalog</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ <packaging>pom</packaging>
+ <name>vfc/nfvo/catalog</name>
+ <description>vfc nfvo catalog</description>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <appendAssemblyId>false</appendAssemblyId>
+ <descriptors>
+ <descriptor>assembly.xml</descriptor>
+ </descriptors>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 00000000..c98aff71
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,21 @@
+# rest framework
+Django==1.9.6
+djangorestframework==3.3.3
+
+# for access MySQL
+MySQL-python==1.2.5
+
+# redis cache
+redis==2.10.5
+
+# for access redis cache
+redisco==0.1.4
+django-redis-cache==0.13.1
+
+# for call rest api
+httplib2==0.9.2
+
+# for unit test
+coverage==4.2
+mock==2.0.0
+unittest_xml_reporting==1.12.0
diff --git a/resources/bin/initDB.sh b/resources/bin/initDB.sh
new file mode 100644
index 00000000..0971e00a
--- /dev/null
+++ b/resources/bin/initDB.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+#
+# 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.
+#
+
+DIRNAME=`dirname $0`
+HOME=`cd $DIRNAME/; pwd`
+user=$1
+password=$2
+port=$3
+host=$4
+echo "start create nfvocatalog db"
+sql_path=$HOME/../
+mysql -u$user -p$password -P$port -h$host <$sql_path/dbscripts/mysql/vfc-nfvo-catalog-createdb.sql
+sql_result=$?
+if [ $sql_result != 0 ] ; then
+ echo "failed to create nfvocatalog database"
+ exit 1
+fi
+fileFlag=*createobj.sql
+location=$sql_path/dbscripts/mysql
+fileName=""
+for i in `ls $location`
+do
+ if [[ $i == ${fileFlag} ]];then
+ fileName=${i};
+ echo "start create table:${fileName}"
+ mysql -u$user -p$password -P$port -h$host <$sql_path/dbscripts/mysql/$fileName
+ sql_result=$?
+ if [ $sql_result != 0 ] ; then
+ echo "failed to init nfvocatalog table:${fileName}"
+ exit 1
+ fi
+ fi
+done
+echo "init nfvocatalog database success!"
+exit 0
+
diff --git a/resources/dbscripts/mysql/vfc-nfvo-catalog-createdb.sql b/resources/dbscripts/mysql/vfc-nfvo-catalog-createdb.sql
new file mode 100644
index 00000000..5e72e608
--- /dev/null
+++ b/resources/dbscripts/mysql/vfc-nfvo-catalog-createdb.sql
@@ -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.
+--
+
+/******************drop old database and user***************************/
+use mysql;
+drop database IF EXISTS nfvocatalog;
+delete from user where User='nfvocatalog';
+FLUSH PRIVILEGES;
+
+/******************create new database and user***************************/
+create database nfvocatalog CHARACTER SET utf8;
+
+GRANT ALL PRIVILEGES ON nfvocatalog.* TO 'nfvocatalog'@'%' IDENTIFIED BY 'nfvocatalog' WITH GRANT OPTION;
+GRANT ALL PRIVILEGES ON mysql.* TO 'nfvocatalog'@'%' IDENTIFIED BY 'nfvocatalog' WITH GRANT OPTION;
+
+GRANT ALL PRIVILEGES ON nfvocatalog.* TO 'nfvocatalog'@'localhost' IDENTIFIED BY 'nfvocatalog' WITH GRANT OPTION;
+GRANT ALL PRIVILEGES ON mysql.* TO 'nfvocatalog'@'localhost' IDENTIFIED BY 'nfvocatalog' WITH GRANT OPTION;
+FLUSH PRIVILEGES; \ No newline at end of file
diff --git a/resources/dbscripts/mysql/vfc-nfvo-catalog-createobj.sql b/resources/dbscripts/mysql/vfc-nfvo-catalog-createobj.sql
new file mode 100644
index 00000000..53b5b4f0
--- /dev/null
+++ b/resources/dbscripts/mysql/vfc-nfvo-catalog-createobj.sql
@@ -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.
+--
+
+use nfvocatalog;
+
+DROP TABLE IF EXISTS NFVO_SAMPLE;
+CREATE TABLE NFVO_SAMPLE (
+ `SAMPLEID` varchar(255) NOT NULL PRIMARY KEY,
+ `SAMPLENAME` varchar(255) NOT NULL
+);
diff --git a/run.sh b/run.sh
new file mode 100644
index 00000000..40136547
--- /dev/null
+++ b/run.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# 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.
+sip=127.0.0.1
+nohup python manage.py runserver $sip:8806 > /dev/null &
diff --git a/static/catalog/empty.txt b/static/catalog/empty.txt
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/static/catalog/empty.txt
diff --git a/stop.sh b/stop.sh
new file mode 100644
index 00000000..67aceb90
--- /dev/null
+++ b/stop.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# 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.
+sip=127.0.0.1
+ps auxww | grep "manage.py runserver $sip:8806" | awk '{print $2}' | xargs kill -9
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 00000000..baf2214a
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,10 @@
+[tox]
+envlist = py27
+skipsdist = true
+
+[tox:jenkins]
+downloadcache = ~/cache/pip
+
+[testenv]
+deps = -r{toxinidir}/requirements.txt
+commands = coverage run --branch manage.py test lcm