summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/specs/multicloud_event_federation.rst145
-rw-r--r--docs/specs/multicloud_image_service.rst117
-rw-r--r--docs/specs/parallelism_improvement.rst199
-rw-r--r--multivimbroker/multivimbroker/forwarder/urls.py3
-rw-r--r--multivimbroker/multivimbroker/forwarder/views.py49
-rw-r--r--multivimbroker/multivimbroker/middleware.py64
-rw-r--r--multivimbroker/multivimbroker/pub/config/config.py23
-rw-r--r--multivimbroker/multivimbroker/pub/config/log.yml8
-rw-r--r--multivimbroker/multivimbroker/pub/utils/syscomm.py8
-rw-r--r--multivimbroker/multivimbroker/settings.py2
-rw-r--r--multivimbroker/multivimbroker/tests/test_check_capacity.py54
-rw-r--r--multivimbroker/multivimbroker/tests/test_vim_types.py (renamed from multivimbroker/multivimbroker/tests/test_urls.py)19
-rw-r--r--multivimbroker/multivimbroker/urls.py15
-rw-r--r--multivimbroker/pom.xml7
-rw-r--r--multivimbroker/requirements.txt2
-rwxr-xr-xmultivimbroker/sonar.sh81
-rw-r--r--pom.xml69
-rwxr-xr-xsonar.sh81
18 files changed, 882 insertions, 64 deletions
diff --git a/docs/specs/multicloud_event_federation.rst b/docs/specs/multicloud_event_federation.rst
new file mode 100644
index 0000000..02de57e
--- /dev/null
+++ b/docs/specs/multicloud_event_federation.rst
@@ -0,0 +1,145 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+.. Copyright (c) 2017-2018 VMware, Inc.
+
+=================
+Event/Alert/Metrics Federation
+=================
+
+As a cloud mediation layer, Multicloud could be invoked by many projects, through this feature, Multicloud will provide
+VM status/events check and also can customize the type of event which user would like to receive. There are some
+kinds of VM status can be chosen: DELETE, PAUSE, POWER_OFF, REBUILD,SHUT_DOWN, SOFT_DELETE, etc.. In VMware VIO Plugin,
+once any change of VM status is detected of a given type, Multicloud will catch the event and throw it to DMaaP.
+Other projects can try this way of getting VM status messages in the future. Also, for other Multicloud plugin providers,
+due to some issues, there will be rest apis for them to grab the VM status messages.
+
+The APP-C won't be impacted since APP-C can still call the existing API which implemented in Amsterdam Release
+ and the API is an existing API
+
+Use Cases
+===================
+
+In VIO, one typical use case is to allow VIO users to fetch messages from DMaaP, this will provide a easier way for fetching status of
+VMs, it may drastically reduce the time of close loop, for other Multicloud plugin providers, Multicloud will provide a set of
+rest apis to get them
+
+
+Proposed change
+===================
+
+In VIO plugin:
+
+The proposed change will include two parts: * listener: to listen the events of the status change of VM, for others it
+will have rest apis to get the messages * publisher: to throw the event to DMaaP.The message we try to send is something like this:
+{
+ "state_description": "powering-off",
+ "availability_zone": "nova",
+ "terminated_at": "",
+ "ephemeral_gb": 0,
+ "instance_type_id": 5,
+ "deleted_at": "",
+ "reservation_id": "r-pvx3l6s2",
+ "memory_mb": 2048,
+ "display_name": "VM1",
+ "hostname": "vm1",
+ "state": "active",
+ "progress": "",
+ "launched_at": "2018-03-07T05:59:46.000000",
+ "metadata": {},
+ "node": "domain-c202.22bfc05c-da55-4ba6-ba93-08d9a067138e",
+ "ramdisk_id": "",
+ "access_ip_v6": null,
+ "disk_gb": 20,
+ "access_ip_v4": null,
+ "kernel_id": "",
+ "host": "compute01",
+ "user_id": "aa90efa5c84c4084b39094da952e0bd1",
+ "image_ref_url": "http://10.154.9.172:9292/images/207b9b7c-9450-4a95-852b-0d6d41f35d24",
+ "cell_name": "",
+ "root_gb": 20,
+ "tenant_id": "943ecb804cdf4103976b8a02cea12fdb",
+ "created_at": "2018-03-07 05:58:01+00:00",
+ "instance_id": "4f398943-7d39-4119-8058-74768d6dfa52",
+ "instance_type": "m1.small",
+ "vcpus": 1,
+ "image_meta": {
+ "is_copying": "1",
+ "container_format": "bare",
+ "min_ram": "0",
+ "vmware_disktype": "streamOptimized",
+ "disk_format": "vmdk",
+ "source_type": "url",
+ "image_url": "https://cloud-images.ubuntu.com/releases/14.04/release/ubuntu-14.04-server-cloudimg-amd64-disk1.img",
+ "vmware_adaptertype": "lsiLogic",
+ "min_disk": "20",
+ "base_image_ref": "207b9b7c-9450-4a95-852b-0d6d41f35d24"
+ },
+ "architecture": null,
+ "os_type": null,
+ "instance_flavor_id": "2"
+}
+
+The eventual work flow looks like as follows:
+
+ +------------------+
+ | |
+ | Multicloud |
+ | Broker |
+ | |
+ +---------+--------+
+ |
+ |
+ V
+ +-----------------------+ +------------------+
+ | Multicloud VIO Plugin |----------->| Dmaap |
+ | | Event | |
+ +--------|-----^--------+ +------------------+
+ Oslo | |
+ Listener | |
+ V |
+ +----------------------+
+ | VIO |
+ +----------------------+
+
+
+In Other Plugins:
+
+Since the security rules of VIMs and network connectivity issues, other multicloud plugins won't be suitable for the
+oslo notification listener, so we will provide rest apis for them, the specific implementation will be dicided by them
+
+Input of <vim_id>/check_vim_status will be
+
+::
+ {
+ "states": array // the set of VIM status which user wants to get
+ }
+
+Output of check_vim_status will be
+
+::
+ {
+ "state_description": string // VIM's state
+ "launched_at": string // time of state change
+ }
+
+The work flow looks like as follows:
+
+ +------------------+
+ | |
+ | Multicloud |
+ | Broker |
+ | |
+ +---------+--------+
+ |
+ |
+ V
+ +-----------------------+
+ | Multicloud Plugins |
+ | |
+ +--------|-----^--------+
+ polling | |
+ or other way | |
+ V |
+ +----------------------+
+ | Openstack |
+ +----------------------+
diff --git a/docs/specs/multicloud_image_service.rst b/docs/specs/multicloud_image_service.rst
new file mode 100644
index 0000000..728d389
--- /dev/null
+++ b/docs/specs/multicloud_image_service.rst
@@ -0,0 +1,117 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+.. Copyright (c) 2017-2018 VMware, Inc.
+
+
+=================
+Image Service
+=================
+
+Because Multicloud provides a cloud mediation layer supporting multiple clouds. It's necessary to
+introduces some function enhancements in it. Image Service could let user upload/download images
+in a convinient way just by using Multicloud.
+
+
+Problem Description
+===================
+
+The original functions which Multicloud possesses are to use urls to upload images, while in this
+spec we intend to upload images as raw file which means it has to store a copy in Multicloud then
+upload the images to the backend openstack. So this spec is to extend multicloud to support
+download/upload images as raw file rather than a through a url
+
+
+Use Cases
+===================
+
+One typical use case is to allow users to upload/download images by Multicloud
+
+
+Proposed change
+===================
+
+The proposed change mainly means introducing glance python APIs to enable multicloud support openstack
+image service. This feature needs two changes: Upload API to import an image to backend OpenStack
+and the image that just imported can be queried from MultiCloud. Download API to download an image
+from backend Openstack and the image can be downloaded from MultiCloud.
+
+The eventual work flow looks like as follows:
+
+ user request to upload image
+ |
+ V
+ +------------------+
+ | |
+ | image file(iso, |
+ | vmdk... ) |
+ | |
+ +---------+--------+
+ |
+ |
+ |
+ +-----------|----------+
+ | multicloud| |
+ | V |
+ | +------------------+ |
+ | | image service API| |
+ | +---------+--------+ |
+ +-----------|----------+
+ | glance
+ |
+ V
+ +----------------------+
+ | openstack |
+ +----------------------+
+
+The APIs look like this:
+
+upload:
+
+Input of /{vimid}/{tenantid}/images/file will be
+
+::
+ required: image file
+ {
+ "imageType": string, // image type: ami, ari, aki, vhd, vhdx, vmdk, raw, qcow2, vdi, iso
+ "containerFormat": string, // image container format: ami, ari, aki, bare, ovf, ova, docker
+ "visibility": string, // public, private, shared, or community
+ "properties": arrary // list of properties
+ }
+
+Output of upload_image will be
+
+::
+ "responses": {
+ "201": {
+ "description": "upload successfully",
+ },
+ "404": {
+ "description": "the vim id or tenant UUID is wrong"
+ },
+ "500": {
+ "description": "the vim image is not accessable"
+ }
+
+download:
+
+Input of /{vimid}/{tenantid}/images/file/{imageid} will be
+
+::
+ {
+ "imagepath": string, // the path of the downloaded image
+ "properties": arrary // list of properties
+ }
+
+Output of download_image will be
+
+::
+ "responses": {
+ "200": {
+ "description": "download successfully",
+ },
+ "404": {
+ "description": "the vim id or tenant UUID is wrong"
+ },
+ "500": {
+ "description": "the vim image is not accessable"
+ }
diff --git a/docs/specs/parallelism_improvement.rst b/docs/specs/parallelism_improvement.rst
new file mode 100644
index 0000000..00d66df
--- /dev/null
+++ b/docs/specs/parallelism_improvement.rst
@@ -0,0 +1,199 @@
+..
+ This work is licensed under a Creative Commons Attribution 4.0
+ International License.
+
+===============================================
+Parallelism improvement of Multi Cloud Services
+===============================================
+
+
+Problem Description
+===================
+
+Multi-Cloud runs Django by using Django's built-in webserver currently.
+According to Django Document[Django_Document]_, this mode should not be used
+in production. This mode has not gone through security audits or performance
+tests, and should only be used in development. From test on local computer,
+this mode can only handle ONE API request at one time. This can not meet the
+performance requirement.
+
+.. [Django_Document] https://docs.djangoproject.com/en/dev/ref/django-admin/#runserver
+
+Although security and scalability might be improved as the side effect of
+resolving the performance issue, this spec will only focus on how to improve
+the parallelism(performance) of current MultiCloud API framework.
+
+Possible Solutions
+==================
+
+Solution 1
+----------
+
+Django is a mature framework. And it has its own way to improve parallelism.
+Instead of running Django's build-in webserver, Django APP can be deployed in
+some dedicated web server. Django’s primary deployment platform is WSGI[django_deploy]_,
+the Python standard for web servers and applications.
+
+.. [django_deploy] https://docs.djangoproject.com/en/2.0/howto/deployment/wsgi/
+
+
+But on the other side, Danjgo is very huge. And Django is a black box if one
+doesn't have good knowledge of it. Adding feature based on Django may be
+time-consuming. For example, the unit test[unit_test]_ of Multi-Cloud can't use
+regular python test library because of Django. The unit test has to base on
+Django's test framework. When we want to improve the parallelism of Multi-Cloud
+services, we need to find out how Django can implement it, instead of using some
+common method.
+
+.. [unit_test] https://gerrit.onap.org/r/#/c/8909/
+
+Besides, Django's code pattern is too much like web code. And, most famous use
+cases of Django are web UI. Current code of Multi-Cloud puts many logic in
+files named `views.py`, but actually there is no view to expose. It is confusing.
+
+The benefit of this solution is that most current code needs no change.
+
+Solution 2
+----------
+
+Given the fact that Django has shortcomings to move on, this solution propose
+to use a alternative framework. Eventlet[Eventlet]_ with Pecan[Pecan]_ will be the
+idea web framework in this case, because it is lightweight, lean and widely
+used.
+
+.. [Eventlet] http://eventlet.net/doc/modules/wsgi.html
+
+.. [Pecan] https://pecan.readthedocs.io/en/latest/
+
+For example, most OpenStack projects use such framework. This framework is so
+thin that it can provide flexibility for future architecture design.
+
+However, it needs to change existing code of API exposing.
+
+
+Performance Test Comparison
+===========================
+
+Test Environment
+----------------
+
+Apache Benchmark is used as test tool. It is shipped with Ubuntu, if you
+don’t find it, just run “sudo apt install -y apache2-utils”
+
+2 Virtual Machine with Ubuntu1604. Virtual Machines are hosted in a multi-core
+hardware server. One VM is for Apache Benchmark. This VM is 1 CPU core, 8G mem.
+The other VM is for Multicloud. The VM is 4 CPU core, 6G mem.
+
+Test Command
+~~~~~~~~~~~~
+
+`ab -n <num of total requests> -c <concurrency level> http://<IP:port>/api/multicloud/v0/vim_types`
+
+Test result
+-----------
+
+It should be noted that data may vary in different test run, but overall result is
+similar as below.
+
+100 requests, concurrency level 1
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Command: `ab -n 100 -c 1 http://<IP:port>/api/multicloud/v0/vim_types`
+Result:
+ Django runserver: total takes 0.512 seconds, all requests success
+ Django+uwsgi: totally takes 0.671 seconds, all requests success.
+ Pecan+eventlet: totally takes 0.149 seconds, all requests success.
+
+10000 requests, concurrency level 100
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Command: `ab -n 10000 -c 100 http://<IP:port>/api/multicloud/v0/vim_types`
+Result:
+ Django runserver: total takes 85.326 seconds, all requests success
+ Django+uwsgi: totally takes 3.808 seconds, all requests success.
+ Pecan+eventlet: totally takes 3.181 seconds, all requests success.
+
+100000 requests, concurrency level 1000
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Command: `ab -n 10000 -c 100 http://<IP:port>/api/multicloud/v0/vim_types`
+Result:
+ Django runserver: Apache Benchmark quit because it reports timeout after
+ running a random portion of all requests.
+ Django+uwsgi: totally takes 37.316 seconds, about 32% requests fail. I see
+ some error says that tcp socket open too many.
+ Pecan+eventlet: totally takes 35.315 seconds, all requests success.
+
+Proposed Change
+===============
+
+Given the test result above, this spec proposes to use solution 2. Based on
+the consideration of Elastic API exposure[jira_workitem]_, Multi-Cloud will
+provide a new way to expose its API. That is to say, existing code of API
+exposing needs rewrite in [jira_workitem]_. So the disadvantage of solution
+2 doesn't exist.
+
+.. [jira_workitem] https://jira.onap.org/browse/MULTICLOUD-152
+
+To define a clear scope of this spec, VoLTE is the use case that will be used
+to perform test to this spec. All functionality that VoLTE needed should be
+implemented in this spec and [jira_workitem]_.
+
+Backward compatibility
+----------------------
+
+This spec will NOT change current API. This spec will NOT replace the current
+API framework in R2, nor will switch to new API framework in R2. Instead,
+this spec will provide a configuration option, named `web_framework`, to make
+sure use case and functionalities not be broken. Default value of the
+configuration will BE `django`, which will still run current Django API
+framework. An alternative value is `pecan`, which will run the API framework
+proposed in this spec. So users don't care about the change won't be
+affected.
+
+WSGI Server
+-----------
+
+No matter what API framework will be used, a WSGI Server needs to be provided.
+This spec will use Eventlet WSGI server. API framework will be run as an
+application in WSGI server.
+
+Multi processes framework
+-------------------------
+
+This spec proposes to run Multi-Cloud API server in multiple processes mode.
+Multi-process can provide parallel API handlers. So, when multiple API
+requests come to Multi-Cloud, they can be handled simultaneously. On the other
+hand, different processes can effectively isolate different API request. So
+that, one API request will not affect another.
+
+Managing multiple processes could be overwhelming difficult and sometimes
+dangerous. Some mature library could be used to reduce related work here, for
+example oslo.service[oslo_service]_. Since oslo is used by all OpenStack
+projects for many releases, and oslo project is actively updated, it can be
+seen as a stable library.
+
+.. [oslo_service] https://github.com/openstack/oslo.service
+
+Number of processes
+~~~~~~~~~~~~~~~~~~~
+
+To best utilize multi-core CPU, the number of processes will be set to the
+number of CPU cores by default.
+
+Shared socket file
+~~~~~~~~~~~~~~~~~~
+
+To make multiple processes work together and provide a unified port number,
+multiple processes need to share a socket file. To achieve this, a bootstrap
+process will be started and will initialize the socket file. Other processes
+can be forked from this bootstrap process.
+
+Work Items
+==========
+
+#. Add WSGI server.
+#. Run Pecan application in WSGI server.
+#. Add multiple processes support.
+#. Update deploy script to support new API framework.
+
diff --git a/multivimbroker/multivimbroker/forwarder/urls.py b/multivimbroker/multivimbroker/forwarder/urls.py
index 6a60df4..771f052 100644
--- a/multivimbroker/multivimbroker/forwarder/urls.py
+++ b/multivimbroker/multivimbroker/forwarder/urls.py
@@ -16,6 +16,7 @@
from django.conf.urls import url
from rest_framework.urlpatterns import format_suffix_patterns
+from multivimbroker.forwarder.views import CheckCapacity
from multivimbroker.forwarder.views import Extension
from multivimbroker.forwarder.views import Forward
from multivimbroker.forwarder.views import Identity
@@ -27,6 +28,8 @@ from multivimbroker.forwarder.views import VIMTypes
urlpatterns = [
url(r'^api/multicloud/v0/vim_types$',
VIMTypes.as_view()),
+ url(r'^api/multicloud/v0/check_vim_capacity$',
+ CheckCapacity.as_view()),
url(r'^api/multicloud/v0/(?P<vimid>[0-9a-zA-Z_-]+)/identity/v3$',
Identity.as_view()),
url(r'^api/multicloud/v0/(?P<vimid>[0-9a-zA-Z_-]+)/identity/v3'
diff --git a/multivimbroker/multivimbroker/forwarder/views.py b/multivimbroker/multivimbroker/forwarder/views.py
index 7935642..c77fe94 100644
--- a/multivimbroker/multivimbroker/forwarder/views.py
+++ b/multivimbroker/multivimbroker/forwarder/views.py
@@ -20,8 +20,7 @@ from rest_framework.views import APIView
from rest_framework.views import Response
from rest_framework.views import status
from multivimbroker.forwarder.base import BaseHandler
-
-#
+from multivimbroker.pub.utils.syscomm import originHeaders
class BaseServer(BaseHandler, APIView):
@@ -50,18 +49,21 @@ class Identity(BaseServer):
def get(self, request, vimid):
- return self.send(vimid, request.get_full_path(), request.body, "GET")
+ return self.send(vimid, request.get_full_path(), request.body, "GET",
+ headers=originHeaders(request))
def post(self, request, vimid):
- return self.send(vimid, request.get_full_path(), request.body, "POST")
+ return self.send(vimid, request.get_full_path(), request.body, "POST",
+ headers=originHeaders(request))
class Registry(BaseServer):
def post(self, request, vimid):
- return self.send(vimid, request.get_full_path(), request.body, "POST")
+ return self.send(vimid, request.get_full_path(), request.body, "POST",
+ headers=originHeaders(request))
class UnRegistry(BaseServer):
@@ -69,14 +71,15 @@ class UnRegistry(BaseServer):
def delete(self, request, vimid):
return self.send(vimid, request.get_full_path(), request.body,
- "DELETE")
+ "DELETE", headers=originHeaders(request))
class Extension(BaseServer):
def get(self, request, vimid):
- return self.send(vimid, request.get_full_path(), request.body, "GET")
+ return self.send(vimid, request.get_full_path(), request.body, "GET",
+ headers=originHeaders(request))
class VIMTypes(BaseServer):
@@ -96,6 +99,38 @@ class VIMTypes(BaseServer):
return Response(data=ret, status=status.HTTP_200_OK)
+class CheckCapacity(BaseServer):
+
+ def post(self, request):
+ try:
+ body = json.loads(request.body)
+ except json.JSONDecodeError as e:
+ return Response(
+ data={'error': 'Invalidate request body %s.' % e},
+ status=status.HTTP_400_BAD_REQUEST)
+
+ ret = {"VIMs": []}
+ newbody = {
+ "vCPU": body.get("vCPU", 0),
+ "Memory": body.get("Memory", 0),
+ "Storage": body.get("Storage", 0)
+ }
+ for vim in body.get("VIMs", []):
+ url = request.get_full_path().replace(
+ "check_vim_capacity", "%s/capacity_check" % vim)
+ resp = self.send(vim, url, newbody, "POST")
+ if resp.status_code != status.HTTP_200_OK:
+ continue
+ try:
+ resp_body = json.loads(resp.body)
+ except json.JSONDecodeError:
+ continue
+ if not resp_body.get("result", False):
+ continue
+ ret['VIMs'].append(vim)
+ return Response(data=ret, status=status.HTTP_200_OK)
+
+
# forward handler
class Forward(BaseServer):
diff --git a/multivimbroker/multivimbroker/middleware.py b/multivimbroker/multivimbroker/middleware.py
new file mode 100644
index 0000000..5b320a3
--- /dev/null
+++ b/multivimbroker/multivimbroker/middleware.py
@@ -0,0 +1,64 @@
+# Copyright (c) 2017-2018 VMware, Inc.
+#
+# 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.
+
+
+import uuid
+from onaplogging.mdcContext import MDC
+from multivimbroker.pub.config.config import SERVICE_NAME
+from multivimbroker.pub.config.config import FORWARDED_FOR_FIELDS
+
+
+class LogContextMiddleware(object):
+
+ # the last IP behind multiple proxies, if no exist proxies
+ # get local host ip.
+ def _getLastIp(self, request):
+
+ ip = ""
+ try:
+ for field in FORWARDED_FOR_FIELDS:
+ if field in request.META:
+ if ',' in request.META[field]:
+ parts = request.META[field].split(',')
+ ip = parts[-1].strip().split(":")[0]
+ else:
+ ip = request.META[field].split(":")[0]
+
+ if ip == "":
+ ip = request.META.get("HTTP_HOST").split(":")[0]
+
+ except Exception:
+ pass
+
+ return ip
+
+ def process_request(self, request):
+
+ # Fetch TRANSACTIONID Id and pass to plugin server
+ ReqeustID = request.META.get("HTTP_X_TRANSACTIONID", None)
+ if ReqeustID is None:
+ ReqeustID = uuid.uuid3(uuid.NAMESPACE_URL, SERVICE_NAME)
+ request.META["HTTP_X_TRANSACTIONID"] = ReqeustID
+ MDC.put("requestID", ReqeustID)
+ # generate the unique id
+ InovocationID = uuid.uuid3(uuid.NAMESPACE_DNS, SERVICE_NAME)
+ MDC.put("invocationID", InovocationID)
+ MDC.put("serviceName", SERVICE_NAME)
+ # access ip
+ MDC.put("serviceIP", self._getLastIp(request))
+
+ return None
+
+ def process_response(self, request, response):
+
+ MDC.clear()
+ return response
diff --git a/multivimbroker/multivimbroker/pub/config/config.py b/multivimbroker/multivimbroker/pub/config/config.py
index 8fba115..192c743 100644
--- a/multivimbroker/multivimbroker/pub/config/config.py
+++ b/multivimbroker/multivimbroker/pub/config/config.py
@@ -24,26 +24,15 @@ MSB_SERVICE_PORT = '10080'
AAI_ADDR = "aai.api.simpledemo.openecomp.org"
AAI_PORT = "8443"
AAI_SERVICE_URL = 'https://%s:%s/aai' % (AAI_ADDR, AAI_PORT)
-AAI_SCHEMA_VERSION = "v11"
+AAI_SCHEMA_VERSION = "v13"
AAI_USERNAME = 'AAI'
AAI_PASSWORD = 'AAI'
+# [MDC]
+SERVICE_NAME = "multicloud-broker"
+FORWARDED_FOR_FIELDS = ["HTTP_X_FORWARDED_FOR", "HTTP_X_FORWARDED_HOST",
+ "HTTP_X_FORWARDED_SERVER"]
+
# [IMAGE LOCAL PATH]
ROOT_PATH = os.path.dirname(
os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
-
-# [register]
-REG_TO_MSB_WHEN_START = False
-REG_TO_MSB_REG_URL = "/api/microservices/v1/services"
-REG_TO_MSB_REG_PARAM = {
- "serviceName": "multicloud",
- "version": "v0",
- "url": "/api/multicloud/v0",
- "protocol": "REST",
- "visualRange": "1",
- "nodes": [{
- "ip": "127.0.0.1",
- "port": "9001",
- "ttl": 0
- }]
-}
diff --git a/multivimbroker/multivimbroker/pub/config/log.yml b/multivimbroker/multivimbroker/pub/config/log.yml
index 12da69f..09be40d 100644
--- a/multivimbroker/multivimbroker/pub/config/log.yml
+++ b/multivimbroker/multivimbroker/pub/config/log.yml
@@ -12,14 +12,14 @@ handlers:
class: "logging.handlers.RotatingFileHandler"
filename: "/var/log/onap/multicloud/multivimbroker/multivimbroker.log"
formatter: "mdcFormat"
- maxBytes: 1024*1024*50
+ maxBytes: 52428800
backupCount: 10
formatters:
standard:
- format: "%(asctime)s:[%(name)s]:[%(filename)s]-[%(lineno)d] [%(levelname)s]:%(message)s"
+ format: "%(asctime)s|||||%(name)s||%(thread)||%(funcName)s||%(levelname)s||%(message)s"
mdcFormat:
- format: "%(asctime)s:[%(name)s]:[%(filename)s]-[%(lineno)d] [%(levelname)s]:[%(mdc)s]: %(message)s"
- mdcfmt: "{requestID}"
+ format: "%(asctime)s|||||%(name)s||%(thread)s||%(funcName)s||%(levelname)s||%(message)s||||%(mdc)s \t"
+ mdcfmt: "{requestID} {invocationID} {serviceName} {serviceIP}"
datefmt: "%Y-%m-%d %H:%M:%S"
(): onaplogging.mdcformatter.MDCFormatter
diff --git a/multivimbroker/multivimbroker/pub/utils/syscomm.py b/multivimbroker/multivimbroker/pub/utils/syscomm.py
index 0b2b557..bd4bbb5 100644
--- a/multivimbroker/multivimbroker/pub/utils/syscomm.py
+++ b/multivimbroker/multivimbroker/pub/utils/syscomm.py
@@ -36,6 +36,14 @@ def getHeadersKeys(response):
return [header for header in response.keys() if header not in hopbyhop]
+# trim out 'HTTP_' prefix part and replace "_" wiht "-".
+def originHeaders(request):
+ regex = re.compile('^HTTP_')
+ return dict((regex.sub('', header).replace("_", "-"), value)
+ for (header, value) in request.META.items()
+ if header.startswith('HTTP_'))
+
+
def findMultivimDriver(vim=None):
json_file = os.path.join(os.path.dirname(__file__),
'../config/provider-plugin.json')
diff --git a/multivimbroker/multivimbroker/settings.py b/multivimbroker/multivimbroker/settings.py
index dca2dd6..8d1fba5 100644
--- a/multivimbroker/multivimbroker/settings.py
+++ b/multivimbroker/multivimbroker/settings.py
@@ -51,6 +51,7 @@ MIDDLEWARE_CLASSES = [
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
+ 'multivimbroker.middleware.LogContextMiddleware',
]
ROOT_URLCONF = 'multivimbroker.urls'
@@ -96,7 +97,6 @@ config.yamlConfig(filepath=LOGGING_FILE, watchDog=True)
if 'test' in sys.argv:
from multivimbroker.pub.config import config
- config.REG_TO_MSB_WHEN_START = False
DATABASES = {}
DATABASES['default'] = {
'ENGINE': 'django.db.backends.sqlite3',
diff --git a/multivimbroker/multivimbroker/tests/test_check_capacity.py b/multivimbroker/multivimbroker/tests/test_check_capacity.py
new file mode 100644
index 0000000..0a852e8
--- /dev/null
+++ b/multivimbroker/multivimbroker/tests/test_check_capacity.py
@@ -0,0 +1,54 @@
+# Copyright (c) 2017-2018 VMware, Inc.
+#
+# 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.
+
+import mock
+import unittest
+
+from rest_framework import status
+
+from multivimbroker.forwarder.views import CheckCapacity
+
+
+class CheckCapacityTest(unittest.TestCase):
+
+ def setUp(self):
+ self.view = CheckCapacity()
+ super(CheckCapacityTest, self).setUp()
+
+ def tearDown(self):
+ pass
+
+ def test_check_capacity_success(self):
+ req = mock.Mock()
+ req.body = """
+ {
+ "vCPU": 1,
+ "Memory": 1,
+ "Storage": 500,
+ "VIMs": ["openstack_RegionOne"]
+ }"""
+ req.get_full_path.return_value = ("http://msb.onap.org/api/multicloud"
+ "/v0/check_vim_capacity")
+ with mock.patch.object(self.view, "send") as send:
+ plugin_resp = mock.Mock()
+ plugin_resp.body = """{
+ "result": true
+ }"""
+ plugin_resp.status_code = status.HTTP_200_OK
+ send.return_value = plugin_resp
+
+ resp = self.view.post(req)
+ expect_body = {
+ "VIMs": ["openstack_RegionOne"]
+ }
+ self.assertEqual(status.HTTP_200_OK, resp.status_code)
+ self.assertDictEqual(expect_body, resp.data)
diff --git a/multivimbroker/multivimbroker/tests/test_urls.py b/multivimbroker/multivimbroker/tests/test_vim_types.py
index 7990033..b8a5080 100644
--- a/multivimbroker/multivimbroker/tests/test_urls.py
+++ b/multivimbroker/multivimbroker/tests/test_vim_types.py
@@ -8,20 +8,19 @@
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-import json
import mock
import unittest
-from multivimbroker.pub.config import config
-from multivimbroker import urls
+from rest_framework.views import status
+
+from multivimbroker.forwarder.views import VIMTypes
class TestUrls(unittest.TestCase):
+ def setUp(self):
+ self.view = VIMTypes()
- def test_request_msb(self):
- with mock.patch("multivimbroker.pub.utils.restcall."
- "req_by_msb") as req_by_msb:
- urls.req_msb(True)
- req_by_msb.assert_called_once_with(
- config.REG_TO_MSB_REG_URL, "POST",
- json.JSONEncoder().encode(config.REG_TO_MSB_REG_PARAM))
+ def test_vim_types_success(self):
+ resp = self.view.get(mock.Mock())
+ self.assertEqual(status.HTTP_200_OK, resp.status_code)
+ self.assertEqual(2, len(resp.data))
diff --git a/multivimbroker/multivimbroker/urls.py b/multivimbroker/multivimbroker/urls.py
index 0843bb3..c393210 100644
--- a/multivimbroker/multivimbroker/urls.py
+++ b/multivimbroker/multivimbroker/urls.py
@@ -11,23 +11,8 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
from django.conf.urls import include, url
-import json
-
-from multivimbroker.pub.config import config
-
urlpatterns = [
url(r'^', include('multivimbroker.swagger.urls')),
url(r'^', include('multivimbroker.forwarder.urls')),
]
-
-
-def req_msb(request_when_start):
- # regist to MSB when startup
- if request_when_start:
- from multivimbroker.pub.utils.restcall import req_by_msb
- req_by_msb(config.REG_TO_MSB_REG_URL, "POST",
- json.JSONEncoder().encode(config.REG_TO_MSB_REG_PARAM))
-
-
-req_msb(config.REG_TO_MSB_WHEN_START)
diff --git a/multivimbroker/pom.xml b/multivimbroker/pom.xml
index 274f54d..fbd40c0 100644
--- a/multivimbroker/pom.xml
+++ b/multivimbroker/pom.xml
@@ -32,13 +32,6 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<nexusproxy>https://nexus.onap.org</nexusproxy>
- <sonar.sources>.</sonar.sources>
- <sonar.junit.reportsPath>xunit-results.xml</sonar.junit.reportsPath>
- <sonar.python.coverage.reportPath>vio/coverage.xml</sonar.python.coverage.reportPath>
- <sonar.language>py</sonar.language>
- <sonar.pluginName>Python</sonar.pluginName>
- <sonar.inclusions>**/*.py</sonar.inclusions>
- <sonar.exclusions>tests/*,setup.py</sonar.exclusions>
</properties>
<build>
<plugins>
diff --git a/multivimbroker/requirements.txt b/multivimbroker/requirements.txt
index 1378612..ef24d49 100644
--- a/multivimbroker/requirements.txt
+++ b/multivimbroker/requirements.txt
@@ -24,4 +24,4 @@ mock==2.0.0
unittest_xml_reporting==1.12.0
# for onap logging
-onappylog>=1.0.5 \ No newline at end of file
+onappylog>=1.0.6 \ No newline at end of file
diff --git a/multivimbroker/sonar.sh b/multivimbroker/sonar.sh
new file mode 100755
index 0000000..e173d1f
--- /dev/null
+++ b/multivimbroker/sonar.sh
@@ -0,0 +1,81 @@
+#!/bin/bash
+# Copyright 2018 VMware 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.
+
+
+set -e
+
+echo "running script: [$0] for module [$1] at stage [$2]"
+
+export SETTINGS_FILE=${SETTINGS_FILE:-$HOME/.m2/settings.xml}
+MVN_PROJECT_MODULEID="$1"
+MVN_PHASE="$2"
+
+
+FQDN="${MVN_PROJECT_GROUPID}.${MVN_PROJECT_ARTIFACTID}"
+if [ "$MVN_PROJECT_MODULEID" == "__" ]; then
+ MVN_PROJECT_MODULEID=""
+fi
+
+if [ -z "$WORKSPACE" ]; then
+ WORKSPACE=$(pwd)
+fi
+
+# mvn phase in life cycle
+MVN_PHASE="$2"
+
+
+echo "MVN_PROJECT_MODULEID is [$MVN_PROJECT_MODULEID]"
+echo "MVN_PHASE is [$MVN_PHASE]"
+echo "MVN_PROJECT_GROUPID is [$MVN_PROJECT_GROUPID]"
+echo "MVN_PROJECT_ARTIFACTID is [$MVN_PROJECT_ARTIFACTID]"
+echo "MVN_PROJECT_VERSION is [$MVN_PROJECT_VERSION]"
+
+run_tox_test()
+{
+ set -x
+ CURDIR=$(pwd)
+ TOXINIS=$(find . -name "tox.ini")
+ for TOXINI in "${TOXINIS[@]}"; do
+ DIR=$(echo "$TOXINI" | rev | cut -f2- -d'/' | rev)
+ cd "${CURDIR}/${DIR}"
+ rm -rf ./venv-tox ./.tox
+ virtualenv ./venv-tox
+ source ./venv-tox/bin/activate
+ pip install --upgrade pip
+ pip install --upgrade tox argparse
+ pip freeze
+ cd multivimbroker
+ tox -e cover
+ deactivate
+ cd ..
+ rm -rf ./venv-tox ./.tox
+ done
+}
+
+
+case $MVN_PHASE in
+clean)
+ echo "==> clean phase script"
+ rm -rf ./venv-*
+ ;;
+test)
+ echo "==> test phase script"
+ run_tox_test
+ ;;
+*)
+ echo "==> unprocessed phase"
+ ;;
+esac
+
diff --git a/pom.xml b/pom.xml
index 2982b70..bdd5736 100644
--- a/pom.xml
+++ b/pom.xml
@@ -18,7 +18,8 @@
<parent>
<groupId>org.onap.oparent</groupId>
<artifactId>oparent</artifactId>
- <version>0.1.1</version>
+ <version>1.1.0</version>
+ <relativePath>../oparent</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.onap.multicloud.framework</groupId>
@@ -27,4 +28,68 @@
<packaging>pom</packaging>
<name>multicloud-framework</name>
<description>multivim broker</description>
-</project>
+ <properties>
+ <sonar.sourceEncoding>UTF-8</sonar.sourceEncoding>
+ <sonar.sources>.</sonar.sources>
+ <sonar.junit.reportsPath>xunit-results.xml</sonar.junit.reportsPath>
+ <sonar.python.coverage.reportPath>multivimbroker/coverage.xml</sonar.python.coverage.reportPath>
+ <sonar.language>py</sonar.language>
+ <sonar.pluginName>Python</sonar.pluginName>
+ <sonar.inclusions>**/*.py</sonar.inclusions>
+ <sonar.exclusions>tests/*,setup.py</sonar.exclusions>
+ </properties>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.1.1</version>
+ <configuration>
+ <executable>${session.executionRootDirectory}/sonar.sh</executable>
+ <environmentVariables>
+ <!-- make mvn properties as env for our script -->
+ <MVN_PROJECT_GROUPID>${project.groupId}</MVN_PROJECT_GROUPID>
+ <MVN_PROJECT_ARTIFACTID>${project.artifactId}</MVN_PROJECT_ARTIFACTID>
+ <MVN_PROJECT_VERSION>${project.version}</MVN_PROJECT_VERSION>
+ </environmentVariables>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.1.1</version>
+ <executions>
+ <execution>
+ <id>clean phase script</id>
+ <phase>clean</phase>
+ <goals>
+ <goal>exec</goal>
+ </goals>
+ <configuration>
+ <arguments>
+ <argument>__</argument>
+ <argument>clean</argument>
+ </arguments>
+ </configuration>
+ </execution>
+ <execution>
+ <id>test script</id>
+ <phase>test</phase>
+ <goals>
+ <goal>exec</goal>
+ </goals>
+ <configuration>
+ <arguments>
+ <argument>__</argument>
+ <argument>test</argument>
+ </arguments>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build></project>
diff --git a/sonar.sh b/sonar.sh
new file mode 100755
index 0000000..e173d1f
--- /dev/null
+++ b/sonar.sh
@@ -0,0 +1,81 @@
+#!/bin/bash
+# Copyright 2018 VMware 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.
+
+
+set -e
+
+echo "running script: [$0] for module [$1] at stage [$2]"
+
+export SETTINGS_FILE=${SETTINGS_FILE:-$HOME/.m2/settings.xml}
+MVN_PROJECT_MODULEID="$1"
+MVN_PHASE="$2"
+
+
+FQDN="${MVN_PROJECT_GROUPID}.${MVN_PROJECT_ARTIFACTID}"
+if [ "$MVN_PROJECT_MODULEID" == "__" ]; then
+ MVN_PROJECT_MODULEID=""
+fi
+
+if [ -z "$WORKSPACE" ]; then
+ WORKSPACE=$(pwd)
+fi
+
+# mvn phase in life cycle
+MVN_PHASE="$2"
+
+
+echo "MVN_PROJECT_MODULEID is [$MVN_PROJECT_MODULEID]"
+echo "MVN_PHASE is [$MVN_PHASE]"
+echo "MVN_PROJECT_GROUPID is [$MVN_PROJECT_GROUPID]"
+echo "MVN_PROJECT_ARTIFACTID is [$MVN_PROJECT_ARTIFACTID]"
+echo "MVN_PROJECT_VERSION is [$MVN_PROJECT_VERSION]"
+
+run_tox_test()
+{
+ set -x
+ CURDIR=$(pwd)
+ TOXINIS=$(find . -name "tox.ini")
+ for TOXINI in "${TOXINIS[@]}"; do
+ DIR=$(echo "$TOXINI" | rev | cut -f2- -d'/' | rev)
+ cd "${CURDIR}/${DIR}"
+ rm -rf ./venv-tox ./.tox
+ virtualenv ./venv-tox
+ source ./venv-tox/bin/activate
+ pip install --upgrade pip
+ pip install --upgrade tox argparse
+ pip freeze
+ cd multivimbroker
+ tox -e cover
+ deactivate
+ cd ..
+ rm -rf ./venv-tox ./.tox
+ done
+}
+
+
+case $MVN_PHASE in
+clean)
+ echo "==> clean phase script"
+ rm -rf ./venv-*
+ ;;
+test)
+ echo "==> test phase script"
+ run_tox_test
+ ;;
+*)
+ echo "==> unprocessed phase"
+ ;;
+esac
+