summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--share/common/msapi/helper.py10
-rw-r--r--windriver/titanium_cloud/resource/tests/tests_infra_workload.py214
-rw-r--r--windriver/titanium_cloud/resource/views/infra_workload.py146
-rw-r--r--windriver/titanium_cloud/urls.py4
-rw-r--r--windriver/titanium_cloud/vesagent/tests/__init__.py16
-rw-r--r--windriver/titanium_cloud/vesagent/tests/tests_fault_vm.py (renamed from windriver/titanium_cloud/vesagent/event_domain/tests_fault_vm.py)0
-rw-r--r--windriver/titanium_cloud/vesagent/tests/tests_tasks.py (renamed from windriver/titanium_cloud/vesagent/tests_tasks.py)0
-rw-r--r--windriver/titanium_cloud/vesagent/tests/tests_vesagent_ctrl.py (renamed from windriver/titanium_cloud/vesagent/tests.py)0
-rw-r--r--windriver/titanium_cloud/vesagent/tests/tests_vespublish.py54
9 files changed, 401 insertions, 43 deletions
diff --git a/share/common/msapi/helper.py b/share/common/msapi/helper.py
index 0c27990b..3ec404eb 100644
--- a/share/common/msapi/helper.py
+++ b/share/common/msapi/helper.py
@@ -32,10 +32,11 @@ class Helper(object):
ret = restcall._call_req(multicloud_api_prefix, "", "", 0, auth_api_url, "POST", extra_headers, json.dumps(data))
if ret[0] > 0 or ret[1] is None:
logger.critical("call url %s failed with status %s" % (multicloud_api_prefix+auth_api_url, ret[0]))
- return None
+ return ret
resp = json.JSONDecoder().decode(ret[1])
- return resp
+ ret[1] = resp
+ return ret
# The consumer of this api must be attaching to the same management network of multicloud,
# The constraints comes from the returned catalog endpoint url e.g. "http://10.0.14.1:80/api/multicloud-titaniumcloud/v0/pod25_RegionOne/identity/v3"
@@ -52,8 +53,9 @@ class Helper(object):
ret = restcall._call_req(endpoint_url, "", "", 0, uri, method, extra_headers, json.dumps(data) if data else "")
if ret[0] > 0 or ret[1] is None:
logger.critical("call url %s failed with status %s" % (endpoint_url+uri, ret[0]))
- return None
+ return ret
content = json.JSONDecoder().decode(ret[1])
- return content
+ ret[1] = content
+ return ret
pass
diff --git a/windriver/titanium_cloud/resource/tests/tests_infra_workload.py b/windriver/titanium_cloud/resource/tests/tests_infra_workload.py
new file mode 100644
index 00000000..05a9d8d6
--- /dev/null
+++ b/windriver/titanium_cloud/resource/tests/tests_infra_workload.py
@@ -0,0 +1,214 @@
+# Copyright (c) 2017-2018 Wind River Systems, 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.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import mock
+
+import unittest
+import json
+from rest_framework import status
+
+from common.utils import restcall
+from common.msapi.helper import Helper as helper
+from titanium_cloud.resource.views.infra_workload import InfraWorkload
+from titanium_cloud.resource.views.infra_workload import APIv1InfraWorkload
+
+MOCK_TOKEN_RESPONSE = {"access":
+ {"token":
+ {"issued_at":"2018-05-10T16:56:56.000000Z",
+ "expires":"2018-05-10T17:56:56.000000Z",
+ "id":"4a832860dd744306b3f66452933f939e",
+ "tenant":{"domain":{"id":"default","name":"Default"},
+ "enabled":"true","id":"0e148b76ee8c42f78d37013bf6b7b1ae",
+ "name":"VIM"}},"serviceCatalog":[],
+ "user":{"domain":{"id":"default","name":"Default"},
+ "id":"ba76c94eb5e94bb7bec6980e5507aae2",
+ "name":"demo"}}}
+
+MOCK_HEAT_CREATE_BODY1 = {
+ "generic-vnf-id":"MOCK_GENERIF_VNF_ID1",
+ "vf-module-id":"MOCK_VF_MODULE_ID1",
+ "oof_directives":{
+ "directives":[
+ {
+ "id":"MOCK_VNFC_ID1",
+ "type": "vnfc",
+ "directives":[{
+ "type":"flavor_directives",
+ "attributes":[
+ {
+ "attribute_name":"flavor1",
+ "attribute_value":"m1.hpa.medium"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "sdnc_directives":{},
+ "template_type":"HEAT",
+ "template_data":{
+ "files":{ },
+ "disable_rollback":True,
+ "parameters":{
+ "flavor1":"m1.heat"
+ },
+ "stack_name":"teststack",
+ "template":{
+ "heat_template_version":"2013-05-23",
+ "description":"Simple template to test heat commands",
+ "parameters":
+ {
+ "flavor":{
+ "default":"m1.tiny",
+ "type":"string"
+ }
+ },
+ "resources":{
+ "hello_world":{
+ "type":"OS::Nova::Server",
+ "properties":{
+ "key_name":"heat_key",
+ "flavor":{
+ "get_param":"flavor"
+ },
+ "image":"40be8d1a-3eb9-40de-8abd-43237517384f",
+ "user_data":"#!/bin/bash -xv\necho \"hello world\" > /root/hello-world.txt\n"
+ }
+ }
+ }
+ },
+ "timeout_mins":60
+ }
+}
+
+MOCK_HEAT_CREATE_RESPONSE1 = {
+ 'stack': {
+ 'id': "MOCKED_HEAT_STACK_ID1"
+ }
+}
+
+MOCK_HEAT_LIST_RESPONSE1 = {
+ 'stacks': [
+ {
+ 'resource_status':"CREATE_IN_PROCESS"
+ }
+ ]
+}
+
+class InfraWorkloadTest(unittest.TestCase):
+ def setUp(self):
+ self._InfraWorkload = InfraWorkload()
+ pass
+
+ def tearDown(self):
+ pass
+
+ @mock.patch.object(helper, 'MultiCloudServiceHelper')
+ @mock.patch.object(helper, 'MultiCloudIdentityHelper')
+ def test_post(self, mock_MultiCloudIdentityHelper, mock_MultiCloudServiceHelper):
+ mock_request = mock.Mock()
+ mock_request.META = {"testkey": "testvalue"}
+ mock_request.data = MOCK_HEAT_CREATE_BODY1
+
+ mock_MultiCloudIdentityHelper.side_effect= [
+ (0, MOCK_TOKEN_RESPONSE, status.HTTP_201_CREATED)
+ ]
+
+ mock_MultiCloudServiceHelper.side_effect= [
+ (0, MOCK_HEAT_CREATE_RESPONSE1, status.HTTP_201_CREATED)
+ ]
+
+ vimid = "CloudOwner_Region1"
+
+ response = self._InfraWorkload.post(mock_request, vimid)
+ self.assertEqual(response.status_code, status.HTTP_201_CREATED)
+ pass
+
+
+ @mock.patch.object(helper, 'MultiCloudServiceHelper')
+ @mock.patch.object(helper, 'MultiCloudIdentityHelper')
+ def test_get(self, mock_MultiCloudIdentityHelper, mock_MultiCloudServiceHelper):
+ mock_request = mock.Mock()
+ mock_request.META = {"testkey": "testvalue"}
+
+ mock_MultiCloudIdentityHelper.side_effect= [
+ (0, MOCK_TOKEN_RESPONSE, status.HTTP_201_CREATED)
+ ]
+
+ mock_MultiCloudServiceHelper.side_effect= [
+ (0, MOCK_HEAT_LIST_RESPONSE1, status.HTTP_200_OK)
+ ]
+
+ vimid = "CloudOwner_Region1"
+ mock_stack_id = "MOCKED_HEAT_STACK_ID1"
+
+ response = self._InfraWorkload.get(mock_request, vimid, mock_stack_id)
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ pass
+
+
+class APIv1InfraWorkloadTest(unittest.TestCase):
+ def setUp(self):
+ self._APIv1InfraWorkload = APIv1InfraWorkload()
+ pass
+
+ def tearDown(self):
+ pass
+
+ @mock.patch.object(helper, 'MultiCloudServiceHelper')
+ @mock.patch.object(helper, 'MultiCloudIdentityHelper')
+ def test_post(self, mock_MultiCloudIdentityHelper, mock_MultiCloudServiceHelper):
+ mock_request = mock.Mock()
+ mock_request.META = {"testkey": "testvalue"}
+ mock_request.data = MOCK_HEAT_CREATE_BODY1
+
+ mock_MultiCloudIdentityHelper.side_effect= [
+ (0, MOCK_TOKEN_RESPONSE, status.HTTP_201_CREATED)
+ ]
+
+ mock_MultiCloudServiceHelper.side_effect= [
+ (0, MOCK_HEAT_CREATE_RESPONSE1, status.HTTP_201_CREATED)
+ ]
+
+ cloud_owner = "CloudOwner"
+ cloud_region_id = "Region1"
+
+ response = self._APIv1InfraWorkload.post(mock_request, cloud_owner, cloud_region_id)
+ self.assertEqual(response.status_code, status.HTTP_201_CREATED)
+ pass
+
+
+ @mock.patch.object(helper, 'MultiCloudServiceHelper')
+ @mock.patch.object(helper, 'MultiCloudIdentityHelper')
+ def test_get(self, mock_MultiCloudIdentityHelper, mock_MultiCloudServiceHelper):
+ mock_request = mock.Mock()
+ mock_request.META = {"testkey": "testvalue"}
+
+ mock_MultiCloudIdentityHelper.side_effect= [
+ (0, MOCK_TOKEN_RESPONSE, status.HTTP_201_CREATED)
+ ]
+
+ mock_MultiCloudServiceHelper.side_effect= [
+ (0, MOCK_HEAT_LIST_RESPONSE1, status.HTTP_200_OK)
+ ]
+
+
+ cloud_owner = "CloudOwner"
+ cloud_region_id = "Region1"
+ mock_stack_id = "MOCKED_HEAT_STACK_ID1"
+
+ response = self._APIv1InfraWorkload.get(mock_request, cloud_owner, cloud_region_id, mock_stack_id)
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ pass \ No newline at end of file
diff --git a/windriver/titanium_cloud/resource/views/infra_workload.py b/windriver/titanium_cloud/resource/views/infra_workload.py
index dce66dec..5ce3e233 100644
--- a/windriver/titanium_cloud/resource/views/infra_workload.py
+++ b/windriver/titanium_cloud/resource/views/infra_workload.py
@@ -39,33 +39,71 @@ class InfraWorkload(APIView):
def __init__(self):
self._logger = logger
- def post(self, request, vimid="", requri=""):
- self._logger.info("vimid,requri: %s, %s" % (vimid, requri))
- self._logger.info("data: %s, %s" % (request.data))
+ def post(self, request, vimid=""):
+ self._logger.info("vimid: %s" % (vimid))
+ self._logger.info("data: %s" % (request.data))
self._logger.debug("META: %s" % request.META)
try :
- # stub response
- resp_template = {
- "template_type": "heat",
- "workload_id": "3095aefc-09fb-4bc7-b1f0-f21a304e864c",
- "template_response":
- {
- "stack": {
- "id": "3095aefc-09fb-4bc7-b1f0-f21a304e864c",
- "links": [
- {
- "href": "http://192.168.123.200:8004/v1/eb1c63a4f77141548385f113a28f0f52/stacks/teststack/3095aefc-09fb-4bc7-b1f0-f21a304e864c",
- "rel": "self"
- }
- ]
- }
+ data = request.data
+ oof_directive = data["oof_directives"]
+ template_type = data["template_type"]
+ template_data = data["template_data"]
+ resp_template = None
+ if template_type and "heat" == template_type.lower():
+ # update heat parameters from oof_directive
+ parameters = template_data.get("parameters", {})
+
+ for directive in oof_directive.get("directives",[]):
+ if directive["type"] == "vnfc":
+ for directive2 in directive.get("directives",[]):
+ if directive2["type"] == "flavor_directives":
+ for attr in directive2.get("attributes",[]):
+ flavor_label = attr.get("attribute_name", None)
+ flavor_value = attr.get("attribute_value", None)
+ if parameters.has_key(flavor_label):
+ parameters[flavor_label] = flavor_value
+ else:
+ self._logger.warn("There is no parameter exist: %s" %
+ flavor_label)
+
+ # update parameters
+ template_data["parameters"]=parameters
+
+ # reset to make sure "files" are empty
+ template_data["files"] = {}
+
+ # authenticate
+ cloud_owner, regionid = extsys.decode_vim_id(vimid)
+ # should go via multicloud proxy so that the selflink is updated by multicloud
+ retcode, v2_token_resp_json, os_status = helper.MultiCloudIdentityHelper(settings.MULTICLOUD_API_V1_PREFIX,
+ cloud_owner, regionid, "/v2.0/tokens")
+ if retcode > 0 or not v2_token_resp_json:
+ logger.error("authenticate fails:%s,%s, %s" % (cloud_owner, regionid, v2_token_resp_json))
+ return
+ # tenant_id = v2_token_resp_json["access"]["token"]["tenant"]["id"]
+
+ service_type = "orchestration"
+ resource_uri = "/stacks"
+ self._logger.info("retrieve stack resources, URI:%s" % resource_uri)
+ retcode, content, os_status = helper.MultiCloudServiceHelper(cloud_owner, regionid, v2_token_resp_json, service_type,
+ resource_uri, None, "POST")
+ stack1 = content.get('stack', None) if retcode == 0 and content else None
+ resp_template = {
+ "template_type": template_type,
+ "workload_id": stack1["id"] if stack1 else "",
+ "template_response": content
}
- }
+ self._logger.info("RESP with data> result:%s" % resp_template)
+
+ return Response(data=resp_template, status=os_status)
+
+ else:
+ msg = "The template type %s is not supported" % (template_type)
+ self._logger.warn(msg)
+ return Response(data={"error":msg}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
- self._logger.info("RESP with data> result:%s" % resp_template)
- return Response(data=resp_template, status=status.HTTP_201_CREATED)
except VimDriverNewtonException as e:
self._logger.error("Plugin exception> status:%s,error:%s"
% (e.status_code, e.content))
@@ -84,18 +122,44 @@ class InfraWorkload(APIView):
self._logger.debug("META: %s" % request.META)
try :
+ # assume the workload_type is heat
stack_id = requri
- workload_data = self.heatbridge_update(request, vimid, stack_id)
+ cloud_owner, regionid = extsys.decode_vim_id(vimid)
+ # should go via multicloud proxy so that the selflink is updated by multicloud
+ retcode, v2_token_resp_json, os_status = helper.MultiCloudIdentityHelper(
+ settings.MULTICLOUD_API_V1_PREFIX,
+ cloud_owner, regionid, "/v2.0/tokens")
+ if retcode > 0 or not v2_token_resp_json:
+ logger.error("authenticate fails:%s, %s, %s" % (cloud_owner, regionid, v2_token_resp_json))
+ return
+ # tenant_id = v2_token_resp_json["access"]["token"]["tenant"]["id"]
+ # tenant_name = v2_token_resp_json["access"]["token"]["tenant"]["name"]
+
+ # get stack status
+ service_type = "orchestration"
+ resource_uri = "/stacks?id=%s" % stack_id if stack_id else "/stacks"
+ self._logger.info("retrieve stack resources, URI:%s" % resource_uri)
+ retcode, content, os_status = helper.MultiCloudServiceHelper(cloud_owner, regionid, v2_token_resp_json,
+ service_type, resource_uri, None, "GET")
+ resources = content.get('stacks', []) if retcode > 0 and content else []
+
+ resource_status = resources[0]["resource_status"] if len(resources)>0 else ""
+
# stub response
resp_template = {
- "template_type": "heat",
- "workload_id": "3095aefc-09fb-4bc7-b1f0-f21a304e864c",
- "workload_status": "CREATE_IN_PROCESS",
- 'workload_data': workload_data
+ "template_type": "HEAT",
+ "workload_id": stack_id,
+ "workload_status": resource_status
}
+ if retcode > 0:
+ resp_template['workload_response'] = content
+
+ if ('CREATE_COMPLETE' == resource_status):
+ self.heatbridge_update(request, vimid, stack_id)
+
self._logger.info("RESP with data> result:%s" % resp_template)
- return Response(data=resp_template, status=status.HTTP_200_OK)
+ return Response(data=resp_template, status=os_status)
except VimDriverNewtonException as e:
self._logger.error("Plugin exception> status:%s,error:%s"
% (e.status_code, e.content))
@@ -142,11 +206,11 @@ class InfraWorkload(APIView):
cloud_owner, regionid = extsys.decode_vim_id(vimid)
# should go via multicloud proxy so that the selflink is updated by multicloud
- v2_token_resp_json = helper.MultiCloudIdentityHelper(settings.MULTICLOUD_API_V1_PREFIX,
+ retcode, v2_token_resp_json, os_status = helper.MultiCloudIdentityHelper(settings.MULTICLOUD_API_V1_PREFIX,
cloud_owner, regionid, "/v2.0/tokens")
- if not v2_token_resp_json:
- logger.error("authenticate fails:%s,%s" % (cloud_owner, regionid))
- return
+ if retcode > 0:
+ logger.error("authenticate fails:%s, %s, %s" % (cloud_owner, regionid, v2_token_resp_json))
+ return None
tenant_id = v2_token_resp_json["access"]["token"]["tenant"]["id"]
# tenant_name = v2_token_resp_json["access"]["token"]["tenant"]["name"]
@@ -158,21 +222,23 @@ class InfraWorkload(APIView):
service_type = "orchestration"
resource_uri = "/stacks/%s/resources"%(stack_id)
self._logger.info("retrieve stack resources, URI:%s" % resource_uri)
- content = helper.MultiCloudServiceHelper(cloud_owner, regionid, v2_token_resp_json, service_type, resource_uri, None, "GET")
- resources = content.get('resources', []) if content else []
+ retcode, content, os_status = helper.MultiCloudServiceHelper(cloud_owner, regionid, v2_token_resp_json, service_type, resource_uri, None, "GET")
+ resources = content.get('resources', []) if retcode==0 and content else []
#find and update resources
transactions = []
for resource in resources:
+ if resource.get('resource_status', None) != "CREATED_COMPLETE":
+ continue
if resource.get('resource_type', None) == 'OS::Nova::Server':
# retrieve vserver details
service_type = "compute"
resource_uri = "/servers/%s" % (resource['physical_resource_id'])
self._logger.info("retrieve vserver detail, URI:%s" % resource_uri)
- content = helper.MultiCloudServiceHelper(cloud_owner, regionid, v2_token_resp_json, service_type,
+ retcode, content, os_status = helper.MultiCloudServiceHelper(cloud_owner, regionid, v2_token_resp_json, service_type,
resource_uri, None, "GET")
self._logger.debug(" resp data:%s" % content)
- vserver_detail = content.get('server', None) if content else None
+ vserver_detail = content.get('server', None) if retcode == 0 and content else None
if vserver_detail:
# compose inventory entry for vserver
vserver_link = ""
@@ -214,16 +280,18 @@ class InfraWorkload(APIView):
pass
for resource in resources:
+ if resource.get('resource_status', None) != "CREATE_COMPLETE":
+ continue
if resource.get('resource_type', None) == 'OS::Neutron::Port':
# retrieve vserver details
service_type = "network"
resource_uri = "/v2.0/ports/%s" % (resource['physical_resource_id'])
self._logger.info("retrieve vserver detail, URI:%s" % resource_uri)
- content = helper.MultiCloudServiceHelper(cloud_owner, regionid, v2_token_resp_json, service_type,
+ retcode, content, os_status = helper.MultiCloudServiceHelper(cloud_owner, regionid, v2_token_resp_json, service_type,
resource_uri, None, "GET")
self._logger.debug(" resp data:%s" % content)
- vport_detail = content.get('port', None)
+ vport_detail = content.get('port', None) if retcode == 0 and content else None
if vport_detail:
# compose inventory entry for vport
# note: l3-interface-ipv4-address-list, l3-interface-ipv6-address-list are not updated yet
@@ -279,12 +347,12 @@ class APIv1InfraWorkload(InfraWorkload):
super(APIv1InfraWorkload, self).__init__()
# self._logger = logger
- def post(self, request, cloud_owner="", cloud_region_id="", requri=""):
+ def post(self, request, cloud_owner="", cloud_region_id=""):
#self._logger.info("cloud owner, cloud region id, data: %s,%s, %s" % (cloud_owner, cloud_region_id, request.data))
#self._logger.debug("META: %s" % request.META)
vimid = extsys.encode_vim_id(cloud_owner, cloud_region_id)
- return super(APIv1InfraWorkload, self).post(request, vimid, requri)
+ return super(APIv1InfraWorkload, self).post(request, vimid)
def get(self, request, cloud_owner="", cloud_region_id="", requri=""):
#self._logger.info("cloud owner, cloud region id, data: %s,%s, %s" % (cloud_owner, cloud_region_id, request.data))
diff --git a/windriver/titanium_cloud/urls.py b/windriver/titanium_cloud/urls.py
index 1d54325b..0387f2a4 100644
--- a/windriver/titanium_cloud/urls.py
+++ b/windriver/titanium_cloud/urls.py
@@ -71,6 +71,10 @@ urlpatterns = [
registration.APIv0Registry.as_view()),
url(r'^api/multicloud-titaniumcloud/v0/(?P<vimid>[0-9a-zA-Z_-]+)/exten',
include('titanium_cloud.extensions.urls')),
+ url(r'^api/multicloud-titaniumcloud/v0/(?P<vimid>[0-9a-zA-Z_-]+)/infra_workload/?$',
+ infra_workload.InfraWorkload.as_view()),
+ url(r'^api/multicloud-titaniumcloud/v0/(?P<vimid>[0-9a-zA-Z_-]+)/infra_workload/(?P<requri>[0-9a-zA-Z_-]*)/?$',
+ infra_workload.InfraWorkload.as_view()),
url(r'^api/multicloud-titaniumcloud/v0/(?P<vimid>[0-9a-zA-Z_-]+)/',
include('titanium_cloud.proxy.urls')),
url(r'^api/multicloud-titaniumcloud/v0/(?P<vimid>[0-9a-zA-Z_-]+)/tenants/?$',
diff --git a/windriver/titanium_cloud/vesagent/tests/__init__.py b/windriver/titanium_cloud/vesagent/tests/__init__.py
new file mode 100644
index 00000000..e4fe7a00
--- /dev/null
+++ b/windriver/titanium_cloud/vesagent/tests/__init__.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (c) 2017-2018 Wind River Systems, 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.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
diff --git a/windriver/titanium_cloud/vesagent/event_domain/tests_fault_vm.py b/windriver/titanium_cloud/vesagent/tests/tests_fault_vm.py
index 7cbc2229..7cbc2229 100644
--- a/windriver/titanium_cloud/vesagent/event_domain/tests_fault_vm.py
+++ b/windriver/titanium_cloud/vesagent/tests/tests_fault_vm.py
diff --git a/windriver/titanium_cloud/vesagent/tests_tasks.py b/windriver/titanium_cloud/vesagent/tests/tests_tasks.py
index fef8e8ee..fef8e8ee 100644
--- a/windriver/titanium_cloud/vesagent/tests_tasks.py
+++ b/windriver/titanium_cloud/vesagent/tests/tests_tasks.py
diff --git a/windriver/titanium_cloud/vesagent/tests.py b/windriver/titanium_cloud/vesagent/tests/tests_vesagent_ctrl.py
index 1fb8d51b..1fb8d51b 100644
--- a/windriver/titanium_cloud/vesagent/tests.py
+++ b/windriver/titanium_cloud/vesagent/tests/tests_vesagent_ctrl.py
diff --git a/windriver/titanium_cloud/vesagent/tests/tests_vespublish.py b/windriver/titanium_cloud/vesagent/tests/tests_vespublish.py
new file mode 100644
index 00000000..0178aaed
--- /dev/null
+++ b/windriver/titanium_cloud/vesagent/tests/tests_vespublish.py
@@ -0,0 +1,54 @@
+# Copyright (c) 2017-2018 Wind River Systems, 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.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import mock
+
+import unittest
+import json
+import urllib2
+
+from titanium_cloud.vesagent import vespublish
+
+MOCK_VESENDPOINT = {
+ "endpoint" : "MOCKED_VES_COLLECTOR_EP1",
+ "username" : "MOCKED_VES_COLLECTOR_USER1",
+ "password" : "MOCKED_VES_COLLECTOR_PASSWD1",
+}
+MOCK_VESPUBLISH_EVENT1 = [{"name":"event1"}]
+
+class VespublishTest(unittest.TestCase):
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ @mock.patch.object(urllib2, 'urlopen')
+ @mock.patch.object(urllib2, 'Request')
+ def test_publishAnyEventToVES(self, mock_Request, mock_urlopen):
+ mock_request = mock.Mock()
+
+ mock_Request.side_effect= [
+ mock_request
+ ]
+
+ mock_response = mock.Mock(["read"])
+ mock_response.read.return_value = "MOCKED_VESPUBLISH_RESPONSE_MESSAGE"
+ mock_urlopen.side_effect= [
+ mock_response
+ ]
+
+ vespublish.publishAnyEventToVES(MOCK_VESENDPOINT, MOCK_VESPUBLISH_EVENT1)
+
+ pass