aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJessica Wagantall <jwagantall@linuxfoundation.org>2018-01-31 01:41:01 +0000
committerGokul Singaraju <gs244f@att.com>2018-03-05 19:34:35 -0500
commit7c98e7f3cf4d09a51c8989360f0b029fd2164c5a (patch)
tree1bd8d55cd59b002106253c24613a91fab859cc79
parentfb39b6640dfff48ed14cce07f625d560e25f788d (diff)
Missing heartbeat microservice
Issue-ID: DCAEGEN2-275 Change-Id: I2a2def9aef7664b58c6c3b74318343699fbf6c22 Signed-Off-by: Gokul Singaraju <gs244f@att.com>
-rw-r--r--Changelog.md10
-rw-r--r--Dockerfile26
-rw-r--r--LICENSE.txt40
-rw-r--r--README.md28
-rwxr-xr-xbin/run.py66
-rw-r--r--coverage.xml159
-rw-r--r--image_history0
-rw-r--r--miss_htbt_service.egg-info/PKG-INFO12
-rw-r--r--miss_htbt_service.egg-info/SOURCES.txt9
-rw-r--r--miss_htbt_service.egg-info/dependency_links.txt1
-rw-r--r--miss_htbt_service.egg-info/not-zip-safe1
-rw-r--r--miss_htbt_service.egg-info/top_level.txt1
-rw-r--r--miss_htbt_service/__init__.py40
-rw-r--r--miss_htbt_service/config/config.yaml28
-rw-r--r--miss_htbt_service/htbtworker.py234
-rwxr-xr-xmvn-phase-script.sh331
-rw-r--r--pom.xml268
-rw-r--r--requirements.txt5
-rw-r--r--setup.py35
-rw-r--r--target/checkstyle-cachefile2
-rw-r--r--target/checkstyle-checker.xml220
-rw-r--r--target/checkstyle-header.txt40
-rw-r--r--target/checkstyle-result.xml3
-rw-r--r--target/failsafe-reports/failsafe-summary.xml8
-rw-r--r--tests/__init__.py21
-rw-r--r--tests/test_binding.py51
-rw-r--r--tox-local.ini14
-rw-r--r--tox.ini16
-rw-r--r--version.properties6
-rw-r--r--xunit-results.xml2
30 files changed, 1677 insertions, 0 deletions
diff --git a/Changelog.md b/Changelog.md
new file mode 100644
index 0000000..40be7bd
--- /dev/null
+++ b/Changelog.md
@@ -0,0 +1,10 @@
+# Change Log
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](http://keepachangelog.com/)
+and this project adheres to [Semantic Versioning](http://semver.org/).
+
+## [0.8.0]
+* Start changelog..
+* Fix a 500 bug where the CBS would return a 500 when a service was in a rels key but that service was not registered in Consul
+* Support a new feature where you can now bind {{x,y,....}} instead of just {{x}}. The return list is all concat together
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..6247123
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,26 @@
+FROM python:3.6
+MAINTAINER gs244f@att.com
+
+ADD . /tmp
+
+#need pip > 8 to have internal pypi repo in requirements.txt
+RUN pip install --upgrade pip
+#do the install
+WORKDIR /tmp
+RUN pip install pyyaml --upgrade
+RUN pip install -r requirements.txt
+RUN pip install -e .
+
+RUN mkdir /opt/config
+RUN echo 1.2.3.4 > /opt/config/coll_ip.txt
+RUN echo 1234 > /opt/config/coll_port.txt
+RUN echo 4.5.6.7 > /opt/config/pol_ip.txt
+RUN echo 4567 > /opt/config/pol_port.txt
+EXPOSE 10000
+
+ENV PYTHONPATH /usr/local/lib/python3.6/site-packages
+#CMD run.py
+#ENTRYPOINT ["/bin/python", "./bin/run.py"]
+#ENTRYPOINT ["/usr/bin/python","./bin/run.py" ]
+ENTRYPOINT ["/usr/local/bin/python","./bin/run.py" ]
+#ENTRYPOINT ["/bin/ls","-lR", "/usr/local"]
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..9536f0b
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,40 @@
+/*
+* ============LICENSE_START==========================================
+* ===================================================================
+* Copyright (c) 2017 AT&T Intellectual Property. All rights reserved.
+* ===================================================================
+*
+* Unless otherwise specified, all software contained herein is licensed
+* under the Apache License, Version 2.0 (the "License");
+* you may not use this software 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.
+*
+*
+*
+* Unless otherwise specified, all documentation contained herein is licensed
+* under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+* you may not use this documentation except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* https://creativecommons.org/licenses/by/4.0/
+*
+* Unless required by applicable law or agreed to in writing, documentation
+* 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.
+*
+* ============LICENSE_END============================================
+*
+* ECOMP is a trademark and service mark of AT&T Intellectual Property.
+*
+*/
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..702ebc7
--- /dev/null
+++ b/README.md
@@ -0,0 +1,28 @@
+# Missing Heartbeat service
+
+# Interface Diagram
+This repo is the thing in red:
+
+![Alt text](doc/cbs_diagram.png?raw=true)
+
+# Overview
+
+Missing Heartbeat service tracks Heartbeat messages from VNF VMs and generates Missing Heartbeat signal for certain number of failed heartbeats. The service tracks heartbeat Messages from DMaaP message routes and generates Missing Heartbeat signal. The IP:Port of DMaaP Message router for Input messages and Output messages needs to be configured. The input and output messages are in JSON format.
+The VNF VMs input topic , output topic, periodicity and number of Heartbests can be configuredin cofig YAML file.
+ The format of output messages is still being worked out.
+# Assumptions
+1. Input and Output messages are in JSON format
+2. The periodicity of Heartbeat messages is more than 15sec
+
+
+# Testing
+You need tox:
+```
+pip install tox
+```
+Then from the root dir, *not in a virtual env*, just run:
+```
+tox
+```
+You may have to alter the tox.ini for the python envs you wish to test with.
+
diff --git a/bin/run.py b/bin/run.py
new file mode 100755
index 0000000..55bb683
--- /dev/null
+++ b/bin/run.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python3
+
+# ============LICENSE_START=======================================================
+# Copyright (c) 2017-2018 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+
+import sys
+import yaml
+import multiprocessing
+import logging
+import subprocess
+from miss_htbt_service import get_logger
+
+#Checks heartbeat by calling worker thread
+def checkhtbt(mr_url, misshtbt,intvl,intopic,outtopic):
+ print('Doing some work',mr_url, misshtbt,intvl,intopic,outtopic)
+ subprocess.call(["/usr/bin/python","./miss_htbt_service/htbtworker.py" , mr_url , str(misshtbt) , str(intvl) , intopic , outtopic])
+ sys.stdout.flush()
+ return
+
+_logger = get_logger(__name__)
+
+#main functon which reads yaml config and invokes heartbeat
+#monitoring
+if __name__ == '__main__':
+ try:
+ print("Heartbeat Microservice ...")
+ multiprocessing.log_to_stderr()
+ logger = multiprocessing.get_logger()
+ logger.setLevel(logging.INFO)
+ with open("./miss_htbt_service/config/config.yaml", 'r') as ymlfile:
+ cfg = yaml.load(ymlfile)
+ # Put some initial values into the queue
+ for section in cfg:
+ print(section)
+ #print(cfg['global'])
+ #print(cfg['global']['message_router_url'])
+ jobs = []
+ for vnf in (cfg['vnfs']):
+ print(cfg['vnfs'][vnf])
+ #print(cfg['vnfs'][vnf][0])
+ #print(cfg['vnfs'][vnf][1])
+ #print(cfg['vnfs'][vnf][2])
+ #Start Heartbeat monitoring process on VNFs configured
+ p = multiprocessing.Process(target=checkhtbt, args=(cfg['global']['message_router_url'],cfg['vnfs'][vnf][0],cfg['vnfs'][vnf][1],cfg['vnfs'][vnf][2],cfg['vnfs'][vnf][3]))
+ jobs.append(p)
+ p.start()
+ for j in jobs:
+ j.join()
+ print('%s.exitcode = %s' % (j.name, j.exitcode))
+ except Exception as e:
+ _logger.error("Fatal error. Could not start missing heartbeat service due to: {0}".format(e))
diff --git a/coverage.xml b/coverage.xml
new file mode 100644
index 0000000..289994f
--- /dev/null
+++ b/coverage.xml
@@ -0,0 +1,159 @@
+<?xml version="1.0" ?>
+<coverage branch-rate="0" branches-covered="0" branches-valid="0" complexity="0" line-rate="0" lines-covered="0" lines-valid="135" timestamp="1520200792383" version="4.5.1">
+ <!-- Generated by coverage.py: https://coverage.readthedocs.io -->
+ <!-- Based on https://raw.githubusercontent.com/cobertura/web/master/htdocs/xml/coverage-04.dtd -->
+ <sources>
+ <source>/root/heartbeat</source>
+ </sources>
+ <packages>
+ <package branch-rate="0" complexity="0" line-rate="0" name="miss_htbt_service">
+ <classes>
+ <class branch-rate="0" complexity="0" filename="miss_htbt_service/__init__.py" line-rate="0" name="__init__.py">
+ <methods/>
+ <lines>
+ <line hits="0" number="19"/>
+ <line hits="0" number="20"/>
+ <line hits="0" number="23"/>
+ <line hits="0" number="24"/>
+ <line hits="0" number="25"/>
+ <line hits="0" number="26"/>
+ <line hits="0" number="27"/>
+ <line hits="0" number="28"/>
+ <line hits="0" number="29"/>
+ <line hits="0" number="30"/>
+ <line hits="0" number="32"/>
+ <line hits="0" number="33"/>
+ <line hits="0" number="35"/>
+ <line hits="0" number="37"/>
+ </lines>
+ </class>
+ <class branch-rate="0" complexity="0" filename="miss_htbt_service/htbtworker.py" line-rate="0" name="htbtworker.py">
+ <methods/>
+ <lines>
+ <line hits="0" number="16"/>
+ <line hits="0" number="17"/>
+ <line hits="0" number="18"/>
+ <line hits="0" number="19"/>
+ <line hits="0" number="20"/>
+ <line hits="0" number="21"/>
+ <line hits="0" number="24"/>
+ <line hits="0" number="25"/>
+ <line hits="0" number="27"/>
+ <line hits="0" number="29"/>
+ <line hits="0" number="31"/>
+ <line hits="0" number="33"/>
+ <line hits="0" number="34"/>
+ <line hits="0" number="35"/>
+ <line hits="0" number="36"/>
+ <line hits="0" number="37"/>
+ <line hits="0" number="40"/>
+ <line hits="0" number="41"/>
+ <line hits="0" number="42"/>
+ <line hits="0" number="44"/>
+ <line hits="0" number="45"/>
+ <line hits="0" number="46"/>
+ <line hits="0" number="49"/>
+ <line hits="0" number="50"/>
+ <line hits="0" number="52"/>
+ <line hits="0" number="57"/>
+ <line hits="0" number="58"/>
+ <line hits="0" number="59"/>
+ <line hits="0" number="60"/>
+ <line hits="0" number="61"/>
+ <line hits="0" number="62"/>
+ <line hits="0" number="63"/>
+ <line hits="0" number="67"/>
+ <line hits="0" number="69"/>
+ <line hits="0" number="71"/>
+ <line hits="0" number="76"/>
+ <line hits="0" number="77"/>
+ <line hits="0" number="78"/>
+ <line hits="0" number="79"/>
+ <line hits="0" number="80"/>
+ <line hits="0" number="81"/>
+ <line hits="0" number="82"/>
+ <line hits="0" number="86"/>
+ <line hits="0" number="88"/>
+ <line hits="0" number="92"/>
+ <line hits="0" number="93"/>
+ <line hits="0" number="94"/>
+ <line hits="0" number="96"/>
+ <line hits="0" number="97"/>
+ <line hits="0" number="98"/>
+ <line hits="0" number="101"/>
+ <line hits="0" number="103"/>
+ <line hits="0" number="104"/>
+ <line hits="0" number="106"/>
+ <line hits="0" number="108"/>
+ <line hits="0" number="110"/>
+ <line hits="0" number="111"/>
+ <line hits="0" number="112"/>
+ <line hits="0" number="113"/>
+ <line hits="0" number="114"/>
+ <line hits="0" number="115"/>
+ <line hits="0" number="116"/>
+ <line hits="0" number="118"/>
+ <line hits="0" number="119"/>
+ <line hits="0" number="120"/>
+ <line hits="0" number="121"/>
+ <line hits="0" number="122"/>
+ <line hits="0" number="123"/>
+ <line hits="0" number="125"/>
+ <line hits="0" number="127"/>
+ <line hits="0" number="153"/>
+ <line hits="0" number="154"/>
+ <line hits="0" number="155"/>
+ <line hits="0" number="156"/>
+ <line hits="0" number="158"/>
+ <line hits="0" number="159"/>
+ <line hits="0" number="160"/>
+ <line hits="0" number="161"/>
+ <line hits="0" number="162"/>
+ <line hits="0" number="164"/>
+ <line hits="0" number="165"/>
+ <line hits="0" number="166"/>
+ <line hits="0" number="167"/>
+ <line hits="0" number="168"/>
+ <line hits="0" number="169"/>
+ <line hits="0" number="170"/>
+ <line hits="0" number="171"/>
+ <line hits="0" number="172"/>
+ <line hits="0" number="173"/>
+ <line hits="0" number="174"/>
+ <line hits="0" number="177"/>
+ <line hits="0" number="202"/>
+ <line hits="0" number="203"/>
+ <line hits="0" number="204"/>
+ <line hits="0" number="205"/>
+ <line hits="0" number="206"/>
+ <line hits="0" number="207"/>
+ <line hits="0" number="208"/>
+ <line hits="0" number="209"/>
+ <line hits="0" number="210"/>
+ <line hits="0" number="211"/>
+ <line hits="0" number="212"/>
+ <line hits="0" number="213"/>
+ <line hits="0" number="215"/>
+ <line hits="0" number="216"/>
+ <line hits="0" number="217"/>
+ <line hits="0" number="218"/>
+ <line hits="0" number="219"/>
+ <line hits="0" number="220"/>
+ <line hits="0" number="221"/>
+ <line hits="0" number="222"/>
+ <line hits="0" number="223"/>
+ <line hits="0" number="224"/>
+ <line hits="0" number="226"/>
+ <line hits="0" number="227"/>
+ <line hits="0" number="228"/>
+ <line hits="0" number="229"/>
+ <line hits="0" number="230"/>
+ <line hits="0" number="232"/>
+ <line hits="0" number="233"/>
+ <line hits="0" number="234"/>
+ </lines>
+ </class>
+ </classes>
+ </package>
+ </packages>
+</coverage>
diff --git a/image_history b/image_history
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/image_history
diff --git a/miss_htbt_service.egg-info/PKG-INFO b/miss_htbt_service.egg-info/PKG-INFO
new file mode 100644
index 0000000..019ebf2
--- /dev/null
+++ b/miss_htbt_service.egg-info/PKG-INFO
@@ -0,0 +1,12 @@
+Metadata-Version: 1.0
+Name: miss-htbt-service
+Version: 2.0.0
+Summary: Missing heartbeat microservice to communicate with policy-engine
+Home-page: https://gerrit.onap.org/r/#/admin/projects/dcaegen2/platform/heartbeat
+Author: Gokul Singaraju
+Author-email: gs244f@att.com
+License: UNKNOWN
+Description-Content-Type: UNKNOWN
+Description: UNKNOWN
+Keywords: missing heartbeat microservice
+Platform: UNKNOWN
diff --git a/miss_htbt_service.egg-info/SOURCES.txt b/miss_htbt_service.egg-info/SOURCES.txt
new file mode 100644
index 0000000..3cceb86
--- /dev/null
+++ b/miss_htbt_service.egg-info/SOURCES.txt
@@ -0,0 +1,9 @@
+README.md
+setup.py
+miss_htbt_service/__init__.py
+miss_htbt_service/htbtworker.py
+miss_htbt_service.egg-info/PKG-INFO
+miss_htbt_service.egg-info/SOURCES.txt
+miss_htbt_service.egg-info/dependency_links.txt
+miss_htbt_service.egg-info/not-zip-safe
+miss_htbt_service.egg-info/top_level.txt \ No newline at end of file
diff --git a/miss_htbt_service.egg-info/dependency_links.txt b/miss_htbt_service.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/miss_htbt_service.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/miss_htbt_service.egg-info/not-zip-safe b/miss_htbt_service.egg-info/not-zip-safe
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/miss_htbt_service.egg-info/not-zip-safe
@@ -0,0 +1 @@
+
diff --git a/miss_htbt_service.egg-info/top_level.txt b/miss_htbt_service.egg-info/top_level.txt
new file mode 100644
index 0000000..d08666e
--- /dev/null
+++ b/miss_htbt_service.egg-info/top_level.txt
@@ -0,0 +1 @@
+miss_htbt_service
diff --git a/miss_htbt_service/__init__.py b/miss_htbt_service/__init__.py
new file mode 100644
index 0000000..a18ed5c
--- /dev/null
+++ b/miss_htbt_service/__init__.py
@@ -0,0 +1,40 @@
+# ============LICENSE_START=======================================================
+# Copyright (c) 2017-2018 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+
+import os
+import logging
+
+'''Configures the module root logger'''
+root = logging.getLogger()
+if root.handlers:
+ root.handlers.clear()
+formatter = logging.Formatter('%(asctime)s | %(name)s | %(module)s | %(funcName)s | %(lineno)d | %(levelname)s | %(message)s')
+handler = logging.StreamHandler()
+handler.setFormatter(formatter)
+root.addHandler(handler)
+root.setLevel("DEBUG")
+
+class BadEnviornmentENVNotFound(Exception):
+ pass
+
+def get_logger(module=None):
+ '''Returns a module-specific logger or global logger if the module is None'''
+ return root if module is None else root.getChild(module)
+
+
+
diff --git a/miss_htbt_service/config/config.yaml b/miss_htbt_service/config/config.yaml
new file mode 100644
index 0000000..bccf034
--- /dev/null
+++ b/miss_htbt_service/config/config.yaml
@@ -0,0 +1,28 @@
+global:
+ host: localhost
+ message_router_url: http://msgrouter.att.com:3904
+# Missing heartbeats
+# Heartbeat interval
+# Input topic
+# Output topic
+# ClosedLoopControlName
+vnfs:
+ vnfa:
+ - 3
+ - 60
+ - VESCOLL-VNFNJ-SECHEARTBEAT-OUTPUT
+ - DCAE-POLICY-HILOTCA-EVENT-OUTPUT
+ - ControlLoopEvent1
+ vnfb:
+ - 3
+ - 30
+ - intopic1
+ - outtopic1
+ - ControlLoopEvent2
+ vnfc:
+ - 3
+ - 30
+ - intopic2
+ - outtopic2
+ - ControlLoopEvent3
+
diff --git a/miss_htbt_service/htbtworker.py b/miss_htbt_service/htbtworker.py
new file mode 100644
index 0000000..b8eadb4
--- /dev/null
+++ b/miss_htbt_service/htbtworker.py
@@ -0,0 +1,234 @@
+#!/usr/bin/python
+# Copyright 2017 AT&T Intellectual Property, Inc. All rights reserved.
+#
+# 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 requests
+import math
+import sched, datetime, time
+import json
+import string
+import sys
+
+
+intvl = 60
+missing_htbt = 2
+#tracks last epoch time
+hearttrack = {}
+#tracks sequence number
+heartstate = {}
+#tracks sequence number differences
+heartflag = {}
+#saves heartbeat message for policy
+heartmsg = {}
+mr_url = 'http://mrrouter.att.com:3904'
+pol_url = 'http://mrrouter.att.com:3904'
+intopic = 'VESCOLL-VNFNJ-SECHEARTBEAT-OUTPUT'
+outopic = 'POLICY-HILOTCA-EVENT-OUTPUT'
+
+# Checks for heartbeat event on periodic basis
+class PeriodicScheduler(object):
+ def __init__(self):
+ self.scheduler = sched.scheduler(time.time, time.sleep)
+
+ def setup(self, interval, action, actionargs=()):
+ action(*actionargs)
+ self.scheduler.enter(interval, 1, self.setup,
+ (interval, action, actionargs))
+
+ def run(self):
+ self.scheduler.run()
+
+def get_collector_uri():
+ """
+ This method waterfalls reads an envioronmental variable called COLLECTOR_HOST
+ If that doesn't work, it raises an Exception
+ """
+ with open('/opt/config/coll_ip.txt', 'r') as myfile:
+ coll_ip=myfile.read().replace('\n', '')
+ myfile.close()
+ with open('/opt/config/coll_port.txt', 'r') as myfile2:
+ coll_port=myfile2.read().replace('\n', '')
+ myfile2.close()
+ if coll_ip and coll_port:
+ # WARNING! TODO! Currently the env file does not include the port.
+ # But some other people think that the port should be a part of that.
+ # For now, I'm hardcoding 8500 until this gets resolved.
+ return "http://{0}:{1}".format(coll_ip, coll_port)
+ else:
+ raise BadEnviornmentENVNotFound("COLLECTOR_HOST")
+
+def get_policy_uri():
+ """
+ This method waterfalls reads an envioronmental variable called POLICY_HOST
+ If that doesn't work, it raises an Exception
+ """
+ with open('/opt/config/coll_ip.txt', 'r') as myfile:
+ pol_ip=myfile.read().replace('\n', '')
+ myfile.close()
+ with open('/opt/config/coll_port.txt', 'r') as myfile2:
+ pol_port=myfile2.read().replace('\n', '')
+ myfile2.close()
+ if pol_ip and pol_port :
+ # WARNING! TODO! Currently the env file does not include the port.
+ # But some other people think that the port should be a part of that.
+ # For now, I'm hardcoding 8500 until this gets resolved.
+ return "http://{0}:{1}".format(pol_ip,pol_port)
+ else:
+ raise BadEnviornmentENVNotFound("POLICY_HOST")
+
+
+# Process the heartbeat event on input topic
+def periodic_event():
+ print("Checking... ")
+ print(datetime.datetime.now())
+ #Read heartbeat
+ get_url = mr_url+'/events/'+intopic+'/DefaultGroup/1?timeout=15000'
+ print(get_url)
+ res = requests.get(get_url)
+ #print(res)
+ #print(res.headers)
+ print(res.text)
+ #print(res.json)
+ inputString = res.text
+ jlist = json.loads(inputString);
+ #print("List:"+jlist[0])
+ for line in jlist:
+ #print(line)
+ jobj = json.loads(line)
+ #print(jobj)
+ srcid = (jobj['event']['commonEventHeader']['sourceId'])
+ lastepo = (jobj['event']['commonEventHeader']['lastEpochMicrosec'])
+ seqnum = (jobj['event']['commonEventHeader']['sequence'])
+ if( srcid in hearttrack ):
+ tdiff = lastepo - hearttrack[srcid]
+ sdiff = seqnum - heartstate[srcid]
+ print("Existing source time diff :"+str(tdiff)+" seqdiff :"+str(sdiff))
+ # check time difference is within limits and seq num is less than allowed
+ if((0 <= tdiff <= 61000000) and sdiff < missing_htbt):
+ print("Heartbeat Alive...")
+ hearttrack[srcid] = lastepo
+ heartstate[srcid] = seqnum;
+ heartflag[srcid] = sdiff;
+ heartmsg[srcid] = jobj;
+ else:
+ print("Heartbeat Dead raising alarm event")
+ #payload = {'Event': 'Heartbeat Failure', 'Host': srcid, 'LastTimestamp': hearttrack[srcid], 'Sequence': heartstate[srcid]}
+ payload = {"event": {
+ "commonEventHeader": {
+ "reportingEntityName": "VNFVM",
+ "reportingEntityName": "VNFVM",
+ "startEpochMicrosec": 1508641592248000,
+ "lastEpochMicrosec": 1508641592248000,
+ "eventId": "VNFVM_heartbeat",
+ "sequence": 1,
+ "priority": "Normal",
+ "sourceName": "VNFVM",
+ "domain": "heartbeat",
+ "eventName": "Heartbeat_Vnf",
+ "internalHeaderFields": {
+ "closedLoopFlag": "True",
+ "eventTag": "hp.Heartbeat Service.20171022.8447964515",
+ "collectorTimeStamp": "Sun, 10 22 2017 03:04:27 GMT",
+ "lastDatetime": "Sun, 22 Oct 2017 03:06:32 +0000",
+ "closedLoopControlName": "ControlLoopEvent1",
+ "firstDatetime": "Sun, 22 Oct 2017 03:06:32 +0000"
+ },
+ "reportingEntityId": "cff8656d-0b42-4eda-ab5d-3d2b7f2d74c8",
+ "version": 3,
+ "sourceId": "cff8656d-0b42-4eda-ab5d-3d2b7f2d74c8"
+ }
+ }
+ }
+ payload = heartmsg[srcid]
+ print(payload)
+ send_url = pol_url+'/events/'+outopic+'/DefaultGroup/1?timeout=15000'
+ print(send_url)
+ #Send response for policy on output topic
+ r = requests.post(send_url, data=payload)
+ print(r.status_code, r.reason)
+ del heartstate[srcid]
+ del hearttrack[srcid]
+ del heartflag[srcid]
+ else:
+ print("Adding new source")
+ hearttrack[srcid] = lastepo
+ heartstate[srcid] = seqnum
+ heartflag[srcid] = 1
+ heartmsg[srcid] = jobj;
+ chkeys = []
+ for key in heartstate.iterkeys():
+ print(key,heartstate[key])
+ if( heartflag[key] == 0 ):
+ print("Heartbeat Dead raise alarm event"+key)
+ chkeys.append( key )
+ #payload = {'Event': 'Heartbeat Failure', 'Host': key, 'LastTimestamp': hearttrack[key], 'Sequence': heartstate[key]}
+ #print payload
+ payload = {"event": {
+ "commonEventHeader": {
+ "reportingEntityName": "VNFVM",
+ "startEpochMicrosec": 1508641592248000,
+ "lastEpochMicrosec": 1508641592248000,
+ "eventId": "VNFVM_heartbeat",
+ "sequence": 1,
+ "priority": "Normal",
+ "sourceName": "VNFVM",
+ "domain": "heartbeat",
+ "eventName": "Heartbeat_Vnf",
+ "internalHeaderFields": {
+ "closedLoopFlag": "True",
+ "eventTag": "hp.Heartbeat Service.20171022.8447964515",
+ "collectorTimeStamp": "Sun, 10 22 2017 03:04:27 GMT",
+ "lastDatetime": "Sun, 22 Oct 2017 03:06:32 +0000",
+ "closedLoopControlName": "ControlLoopEvent1",
+ "firstDatetime": "Sun, 22 Oct 2017 03:06:32 +0000"
+ },
+ "reportingEntityId": "cff8656d-0b42-4eda-ab5d-3d2b7f2d74c8",
+ "version": 3,
+ "sourceId": "cff8656d-0b42-4eda-ab5d-3d2b7f2d74c8"
+ }
+ }
+ }
+ payload = heartmsg[key]
+ print(payload)
+ send_url = pol_url+'/events/'+outopic+'/DefaultGroup/1?timeout=15000'
+ print(send_url)
+ r = requests.post(send_url, data=payload)
+ print(r.status_code, r.reason)
+ heartflag[key] = 0
+ for chkey in chkeys:
+ print(chkey)
+ del heartstate[chkey]
+ del hearttrack[chkey]
+ del heartflag[chkey]
+
+total = len(sys.argv)
+cmdargs = str(sys.argv)
+print ("The total numbers of args passed to the script: %d " % total)
+print ("Args list: %s " % cmdargs)
+print ("Script name: %s" % str(sys.argv[0]))
+for i in range(total):
+ print ("Argument # %d : %s" % (i, str(sys.argv[i])))
+if( total >= 6 ):
+ mr_url = get_collector_uri()
+ pol_url = get_policy_uri()
+ #mr_url = sys.argv[1]
+ missing_htbt = float(int(sys.argv[2]))
+ intvl = float(int(sys.argv[3]))
+ intopic = sys.argv[4]
+ outopic = sys.argv[5]
+print ("Interval %s " % intvl)
+#intvl = 60 # every second
+periodic_scheduler = PeriodicScheduler()
+periodic_scheduler.setup(intvl, periodic_event) # it executes the event just once
+periodic_scheduler.run() # it starts the scheduler
diff --git a/mvn-phase-script.sh b/mvn-phase-script.sh
new file mode 100755
index 0000000..ae1fd65
--- /dev/null
+++ b/mvn-phase-script.sh
@@ -0,0 +1,331 @@
+#!/bin/bash
+
+# ================================================================================
+# Copyright (c) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+
+
+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 [[ "$MVN_PROJECT_VERSION" == *SNAPSHOT ]]; then
+ echo "=> for SNAPSHOT artifact build"
+ MVN_DEPLOYMENT_TYPE='SNAPSHOT'
+else
+ echo "=> for STAGING/RELEASE artifact build"
+ MVN_DEPLOYMENT_TYPE='STAGING'
+fi
+echo "MVN_DEPLOYMENT_TYPE is [$DEPLOYMENT_TYPE]"
+
+
+TIMESTAMP=$(date +%C%y%m%dT%H%M%S)
+
+# expected environment variables
+if [ -z "${MVN_NEXUSPROXY}" ]; then
+ echo "MVN_NEXUSPROXY environment variable not set. Cannot proceed"
+ exit
+fi
+
+MVN_NEXUSPROXY_HOST=$(echo "$MVN_NEXUSPROXY" |cut -f3 -d'/' | cut -f1 -d':')
+echo "=> Nexus Proxy at $MVN_NEXUSPROXY_HOST, $MVN_NEXUSPROXY"
+
+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]"
+echo "MVN_NEXUSPROXY is [$MVN_NEXUSPROXY]"
+echo "MVN_RAWREPO_BASEURL_UPLOAD is [$MVN_RAWREPO_BASEURL_UPLOAD]"
+echo "MVN_RAWREPO_BASEURL_DOWNLOAD is [$MVN_RAWREPO_BASEURL_DOWNLOAD]"
+MVN_RAWREPO_HOST=$(echo "$MVN_RAWREPO_BASEURL_UPLOAD" | cut -f3 -d'/' |cut -f1 -d':')
+echo "MVN_RAWREPO_HOST is [$MVN_RAWREPO_HOST]"
+echo "MVN_RAWREPO_SERVERID is [$MVN_RAWREPO_SERVERID]"
+echo "MVN_DOCKERREGISTRY_DAILY is [$MVN_DOCKERREGISTRY_DAILY]"
+echo "MVN_DOCKERREGISTRY_RELEASE is [$MVN_DOCKERREGISTRY_RELEASE]"
+
+expand_templates()
+{
+ # set up env variables, get ready for template resolution
+ export ONAPTEMPLATE_RAWREPOURL_org_onap_ccsdk_platform_plugins_releases="$MVN_RAWREPO_BASEURL_DOWNLOAD/org.onap.ccsdk.plugins/releases"
+ export ONAPTEMPLATE_RAWREPOURL_org_onap_ccsdk_platform_plugins_snapshots="$MVN_RAWREPO_BASEURL_DOWNLOAD/org.onap.ccsdk.plugins/snapshots"
+ export ONAPTEMPLATE_RAWREPOURL_org_onap_ccsdk_platform_blueprints_releases="$MVN_RAWREPO_BASEURL_DOWNLOAD/org.onap.ccsdk.blueprints/releases"
+ export ONAPTEMPLATE_RAWREPOURL_org_onap_ccsdk_platform_blueprints_snapshots="$MVN_RAWREPO_BASEURL_DOWNLOAD/org.onap.ccsdk.blueprints/snapshots" export ONAPTEMPLATE_RAWREPOURL_org_onap_dcaegen2_releases="$MVN_RAWREPO_BASEURL_DOWNLOAD/org.onap.dcaegen2/releases"
+ export ONAPTEMPLATE_RAWREPOURL_org_onap_dcaegen2_snapshots="$MVN_RAWREPO_BASEURL_DOWNLOAD/org.onap.dcaegen2/snapshots" export ONAPTEMPLATE_RAWREPOURL_org_onap_dcaegen2_platform_plugins_releases="$MVN_RAWREPO_BASEURL_DOWNLOAD/org.onap.dcaegen2.platform.plugins/releases"
+ export ONAPTEMPLATE_RAWREPOURL_org_onap_dcaegen2_platform_plugins_snapshots="$MVN_RAWREPO_BASEURL_DOWNLOAD/org.onap.dcaegen2.platform.plugins/snapshots"
+ export ONAPTEMPLATE_RAWREPOURL_org_onap_dcaegen2_platform_blueprints_releases="$MVN_RAWREPO_BASEURL_DOWNLOAD/org.onap.dcaegen2.platform.blueprints/releases"
+ export ONAPTEMPLATE_RAWREPOURL_org_onap_dcaegen2_platform_blueprints_snapshots="$MVN_RAWREPO_BASEURL_DOWNLOAD/org.onap.dcaegen2.platform.blueprints/snapshots"
+
+ export ONAPTEMPLATE_PYPIURL_org_onap_dcaegen2="${MVN_NEXUSPROXY}/content/sites/pypi"
+
+ export ONAPTEMPLATE_DOCKERREGURL_org_onap_dcaegen2_releases="$MVN_DOCKERREGISTRY_DAILY"
+ export ONAPTEMPLATE_DOCKERREGURL_org_onap_dcaegen2_snapshots="$MVN_DOCKERREGISTRY_DAILY/snapshots"
+
+
+ TEMPLATES=$(env |grep ONAPTEMPLATE)
+ echo "====> Resolving the following temaplate from environment variables "
+ echo "[$TEMPLATES]"
+ SELFFILE=$(echo "$0" | rev | cut -f1 -d '/' | rev)
+ for TEMPLATE in $TEMPLATES; do
+ KEY=$(echo "$TEMPLATE" | cut -f1 -d'=')
+ VALUE=$(echo "$TEMPLATE" | cut -f2 -d'=')
+ VALUE2=$(echo "$TEMPLATE" | cut -f2 -d'=' |sed 's/\//\\\//g')
+ FILES=$(grep -rl "$KEY" .)
+
+ # assuming FILES is not longer than 2M bytes, the limit for variable value max size on this VM
+ for F in $FILES; do
+ if [[ $F == *"$SELFFILE" ]]; then
+ continue
+ fi
+ echo "======> Resolving template $KEY to value $VALUE for file $F"
+ sed -i "s/{{[[:space:]]*$KEY[[:space:]]*}}/$VALUE2/g" "$F"
+
+ #cat "$F"
+ done
+
+ #if [ ! -z "$FILES" ]; then
+ # echo "====> Resolving template $VALUE to value $VALUE"
+ # #CMD="grep -rl \"$VALUE\" . | tr '\n' '\0' | xargs -0 sed -i \"s/{{[[:space:]]*$VALUE[[:space:]]*}}/$VALUE/g\""
+ # grep -rl "$KEY" | tr '\n' '\0' . | xargs -0 sed -i 's/$KEY/$VALUE2/g'
+ # #echo $CMD
+ # #eval $CMD
+ #fi
+ done
+ echo "====> Done template reolving"
+}
+
+
+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
+ tox
+ deactivate
+ rm -rf ./venv-tox ./.tox
+ done
+}
+
+build_wagons()
+{
+ rm -rf ./*.wgn venv-pkg
+
+ SETUPFILES=$(find . -name "setup.py")
+ for SETUPFILE in $SETUPFILES; do
+ PLUGIN_DIR=$(echo "$SETUPFILE" |rev | cut -f 2- -d '/' |rev)
+ PLUGIN_NAME=$(grep 'name' "$SETUPFILE" | cut -f2 -d'=' | sed 's/[^0-9a-zA-Z\.]*//g')
+ PLUGIN_VERSION=$(grep 'version' "$SETUPFILE" | cut -f2 -d'=' | sed 's/[^0-9\.]*//g')
+
+ echo "In $PLUGIN_DIR, $PLUGIN_NAME, $PLUGIN_VERSION"
+
+ virtualenv ./venv-pkg
+ source ./venv-pkg/bin/activate
+ pip install --upgrade pip
+ pip install wagon
+ wagon create --format tar.gz "$PLUGIN_DIR"
+ deactivate
+ rm -rf venv-pkg
+
+ PKG_FILE_NAMES=( "${PLUGIN_NAME}-${PLUGIN_VERSION}"*.wgn )
+ echo Built package: "${PKG_FILE_NAMES[@]}"
+ done
+}
+
+
+upload_raw_file()
+{
+ # Extract the username and password to the nexus repo from the settings file
+ USER=$(xpath -q -e "//servers/server[id='$MVN_RAWREPO_SERVERID']/username/text()" "$SETTINGS_FILE")
+ PASS=$(xpath -q -e "//servers/server[id='$MVN_RAWREPO_SERVERID']/password/text()" "$SETTINGS_FILE")
+ NETRC=$(mktemp)
+ echo "machine $MVN_RAWREPO_HOST login $USER password $PASS" > "$NETRC"
+
+ REPO="$MVN_RAWREPO_BASEURL_UPLOAD"
+
+ OUTPUT_FILE=$1
+ EXT=$(echo "$OUTPUT_FILE" | rev |cut -f1 -d '.' |rev)
+ if [ "$EXT" == 'yaml' ]; then
+ OUTPUT_FILE_TYPE='text/x-yaml'
+ elif [ "$EXT" == 'gz' ]; then
+ OUTPUT_FILE_TYPE='application/gzip'
+ elif [ "$EXT" == 'wgn' ]; then
+ OUTPUT_FILE_TYPE='application/gzip'
+ else
+ OUTPUT_FILE_TYPE='application/octet-stream'
+ fi
+
+
+ if [ "$MVN_DEPLOYMENT_TYPE" == 'SNAPSHOT' ]; then
+ SEND_TO="${REPO}/${FQDN}/snapshots"
+ elif [ "$MVN_DEPLOYMENT_TYPE" == 'STAGING' ]; then
+ SEND_TO="${REPO}/${FQDN}/releases"
+ else
+ echo "Unreconfnized deployment type, quit"
+ exit
+ fi
+
+ echo "Sending ${OUTPUT_FILE} to Nexus: ${SEND_TO}"
+ curl -vkn --netrc-file "${NETRC}" --upload-file "${OUTPUT_FILE}" -X PUT -H "Content-Type: $OUTPUT_FILE_TYPE" "${SEND_TO}/${OUTPUT_FILE}-${MVN_PROJECT_VERSION}-${TIMESTAMP}"
+ curl -vkn --netrc-file "${NETRC}" --upload-file "${OUTPUT_FILE}" -X PUT -H "Content-Type: $OUTPUT_FILE_TYPE" "${SEND_TO}/${OUTPUT_FILE}-${MVN_PROJECT_VERSION}"
+ curl -vkn --netrc-file "${NETRC}" --upload-file "${OUTPUT_FILE}" -X PUT -H "Content-Type: $OUTPUT_FILE_TYPE" "${SEND_TO}/${OUTPUT_FILE}"
+}
+
+
+
+upload_wagons_and_type_yamls()
+{
+ WAGONS=$(ls -1 ./*.wgn)
+ for WAGON in "${WAGONS[@]}" ; do
+ WAGON_NAME=$(echo "$WAGON" | cut -f1 -d '-')
+ WAGON_VERSION=$(echo "$WAGON" | cut -f2 -d '-')
+ WAGON_TYPEFILE=$(grep -rl "$WAGON_NAME" . | grep yaml | head -1)
+
+ upload_raw_file "$WAGON"
+ upload_raw_file "$WAGON_TYPEFILE"
+ done
+}
+
+
+
+build_and_push_docker()
+{
+ IMAGENAME="onap/${FQDN}.${MVN_PROJECT_MODULEID}"
+ IMAGENAME=$(echo "$IMAGENAME" | sed -e 's/_*$//g' -e 's/\.*$//g')
+
+ # use the major and minor version of the MVN artifact version as docker image version
+ VERSION="${MVN_PROJECT_VERSION//[^0-9.]/}"
+ VERSION2=$(echo "$VERSION" | cut -f1-2 -d'.')
+
+ LFQI="${IMAGENAME}:${VERSION}-${TIMESTAMP}"
+ BUILD_PATH="${WORKSPACE}"
+ # build a docker image
+ docker build --rm -f "${WORKSPACE}"/Dockerfile -t "${LFQI}" "${BUILD_PATH}"
+
+ REPO=""
+ if [ $MVN_DEPLOYMENT_TYPE == "SNAPSHOT" ]; then
+ REPO=$MVN_DOCKERREGISTRY_DAILY
+ elif [ $MVN_DEPLOYMENT_TYPE == "STAGING" ]; then
+ # there seems to be no staging docker registry? set to use SNAPSHOT also
+ #REPO=$MVN_DOCKERREGISTRY_RELEASE
+ REPO=$MVN_DOCKERREGISTRY_DAILY
+ else
+ echo "Fail to determine DEPLOYMENT_TYPE"
+ REPO=$MVN_DOCKERREGISTRY_DAILY
+ fi
+ echo "DEPLOYMENT_TYPE is: $MVN_DEPLOYMENT_TYPE, repo is $REPO"
+
+ if [ ! -z "$REPO" ]; then
+ USER=$(xpath -e "//servers/server[id='$REPO']/username/text()" "$SETTINGS_FILE")
+ PASS=$(xpath -e "//servers/server[id='$REPO']/password/text()" "$SETTINGS_FILE")
+ if [ -z "$USER" ]; then
+ echo "Error: no user provided"
+ fi
+ if [ -z "$PASS" ]; then
+ echo "Error: no password provided"
+ fi
+ [ -z "$PASS" ] && PASS_PROVIDED="<empty>" || PASS_PROVIDED="<password>"
+ echo docker login "$REPO" -u "$USER" -p "$PASS_PROVIDED"
+ docker login "$REPO" -u "$USER" -p "$PASS"
+
+ if [ $MVN_DEPLOYMENT_TYPE == "SNAPSHOT" ]; then
+ REPO="$REPO/snapshots"
+ elif [ $MVN_DEPLOYMENT_TYPE == "STAGING" ]; then
+ # there seems to be no staging docker registry? set to use SNAPSHOT also
+ #REPO=$MVN_DOCKERREGISTRY_RELEASE
+ REPO="$REPO"
+ else
+ echo "Fail to determine DEPLOYMENT_TYPE"
+ REPO="$REPO/unknown"
+ fi
+
+ OLDTAG="${LFQI}"
+ PUSHTAGS="${REPO}/${IMAGENAME}:${VERSION2}-${TIMESTAMP} ${REPO}/${IMAGENAME}:${VERSION2} ${REPO}/${IMAGENAME}:${VERSION2}-latest"
+ for NEWTAG in ${PUSHTAGS}
+ do
+ echo "tagging ${OLDTAG} to ${NEWTAG}"
+ docker tag "${OLDTAG}" "${NEWTAG}"
+ echo "pushing ${NEWTAG}"
+ docker push "${NEWTAG}"
+ OLDTAG="${NEWTAG}"
+ done
+ fi
+
+}
+
+
+
+
+
+case $MVN_PHASE in
+clean)
+ echo "==> clean phase script"
+ rm -rf ./venv-*
+ ;;
+generate-sources)
+ echo "==> generate-sources phase script"
+ expand_templates
+ ;;
+compile)
+ echo "==> compile phase script"
+ ;;
+test)
+ echo "==> test phase script"
+ run_tox_test
+ ;;
+package)
+ echo "==> package phase script"
+ ;;
+install)
+ echo "==> install phase script"
+ ;;
+deploy)
+ echo "==> deploy phase script"
+ #upload_wagons_and_type_yamls
+ build_and_push_docker
+ ;;
+*)
+ echo "==> unprocessed phase"
+ ;;
+esac
+
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..461da6e
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,268 @@
+<?xml version="1.0"?>
+<!--
+================================================================================
+Copyright (c) 2017 AT&T Intellectual Property. All rights reserved.
+================================================================================
+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.
+============LICENSE_END=========================================================
+
+ECOMP is a trademark and service mark of AT&T Intellectual Property.
+-->
+<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">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onap</groupId>
+ <artifactId>dcaegen2</artifactId>
+ <version>1.2.0-SNAPSHOT</version>
+ </parent>
+ <!--- CHANGE THE FOLLOWING 3 OBJECTS for your own repo -->
+ <groupId>org.onap.dcaegen2.platform</groupId>
+ <artifactId>heartbeat</artifactId>
+ <name>dcaegen2-platform-heartbeat</name>
+ <version>2.0.0</version>
+ <url>http://maven.apache.org</url>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <sonar.sources>.</sonar.sources>
+ <sonar.junit.reportsPath>xunit-results.xml</sonar.junit.reportsPath>
+ <sonar.python.coverage.reportPath>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>
+ <finalName>${project.artifactId}-${project.version}</finalName>
+ <pluginManagement>
+ <plugins>
+ <!-- the following plugins are invoked from oparent, we do not need them -->
+ <plugin>
+ <groupId>org.sonatype.plugins</groupId>
+ <artifactId>nexus-staging-maven-plugin</artifactId>
+ <version>1.6.7</version>
+ <configuration>
+ <skipNexusStagingDeployMojo>true</skipNexusStagingDeployMojo>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <!-- This version supports the "deployAtEnd" parameter -->
+ <version>2.8</version>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ <version>3.0.0-M1</version>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <!-- first disable the default Java plugins at various stages -->
+ <!-- maven-resources-plugin is called during "*resource" phases by default behavior. it prepares the resources
+ dir. we do not need it -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <!-- maven-compiler-plugin is called during "compile" phases by default behavior. we do not need it -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.1</version>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <!-- maven-jar-plugin is called during "compile" phase by default behavior. we do not need it -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.4</version>
+ <executions>
+ <execution>
+ <id>default-jar</id>
+ <phase/>
+ </execution>
+ </executions>
+ </plugin>
+ <!-- maven-install-plugin is called during "install" phase by default behavior. it tries to copy stuff under
+ target dir to ~/.m2. we do not need it -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-install-plugin</artifactId>
+ <version>2.4</version>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <!-- maven-surefire-plugin is called during "test" phase by default behavior. it triggers junit test.
+ we do not need it -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.12.4</version>
+ <configuration>
+ <skipTests>true</skipTests>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.2.1</version>
+ <configuration>
+ <executable>${session.executionRootDirectory}/mvn-phase-script.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>
+ <MVN_NEXUSPROXY>${onap.nexus.url}</MVN_NEXUSPROXY>
+ <MVN_RAWREPO_BASEURL_UPLOAD>${onap.nexus.rawrepo.baseurl.upload}</MVN_RAWREPO_BASEURL_UPLOAD>
+ <MVN_RAWREPO_BASEURL_DOWNLOAD>${onap.nexus.rawrepo.baseurl.download}</MVN_RAWREPO_BASEURL_DOWNLOAD>
+ <MVN_RAWREPO_SERVERID>${onap.nexus.rawrepo.serverid}</MVN_RAWREPO_SERVERID>
+ <MVN_DOCKERREGISTRY_DAILY>${onap.nexus.dockerregistry.daily}</MVN_DOCKERREGISTRY_DAILY>
+ <MVN_DOCKERREGISTRY_RELEASE>${onap.nexus.dockerregistry.release}</MVN_DOCKERREGISTRY_RELEASE>
+ </environmentVariables>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ <plugins>
+ <!-- plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>2.4.1</version>
+ <configuration>
+ <descriptors>
+ <descriptor>assembly/dep.xml</descriptor>
+ </descriptors>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin -->
+ <!-- now we configure custom action (calling a script) at various lifecycle phases -->
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.2.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>generate-sources script</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>exec</goal>
+ </goals>
+ <configuration>
+ <arguments>
+ <argument>__</argument>
+ <argument>generate-sources</argument>
+ </arguments>
+ </configuration>
+ </execution>
+ <execution>
+ <id>compile script</id>
+ <phase>compile</phase>
+ <goals>
+ <goal>exec</goal>
+ </goals>
+ <configuration>
+ <arguments>
+ <argument>__</argument>
+ <argument>compile</argument>
+ </arguments>
+ </configuration>
+ </execution>
+ <execution>
+ <id>package script</id>
+ <phase>package</phase>
+ <goals>
+ <goal>exec</goal>
+ </goals>
+ <configuration>
+ <arguments>
+ <argument>__</argument>
+ <argument>package</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>
+ <execution>
+ <id>install script</id>
+ <phase>install</phase>
+ <goals>
+ <goal>exec</goal>
+ </goals>
+ <configuration>
+ <arguments>
+ <argument>__</argument>
+ <argument>install</argument>
+ </arguments>
+ </configuration>
+ </execution>
+ <execution>
+ <id>deploy script</id>
+ <phase>deploy</phase>
+ <goals>
+ <goal>exec</goal>
+ </goals>
+ <configuration>
+ <arguments>
+ <argument>__</argument>
+ <argument>deploy</argument>
+ </arguments>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..b838342
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,5 @@
+Flask==0.12.2
+connexion==1.1.12
+requests==2.18.2
+six==1.10.0
+PyYAML==3.12
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..57baf52
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,35 @@
+# ============LICENSE_START=======================================================
+# Copyright (c) 2017-2018 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+
+import os
+from setuptools import setup, find_packages
+from pip.req import parse_requirements
+from pip.download import PipSession
+
+setup(
+ name='miss_htbt_service',
+ description='Missing heartbeat microservice to communicate with policy-engine',
+ version='2.0.0',
+ packages=find_packages(exclude=["tests.*", "tests"]),
+ author = "Gokul Singaraju",
+ author_email = "gs244f@att.com",
+ license = "",
+ keywords = "missing heartbeat microservice",
+ url = "https://gerrit.onap.org/r/#/admin/projects/dcaegen2/platform/heartbeat",
+ zip_safe=False,
+)
diff --git a/target/checkstyle-cachefile b/target/checkstyle-cachefile
new file mode 100644
index 0000000..a0970bf
--- /dev/null
+++ b/target/checkstyle-cachefile
@@ -0,0 +1,2 @@
+#Tue Feb 27 23:21:54 EST 2018
+configuration*?=15B4FB894B57CADB17418F12E3274FB4B864070B
diff --git a/target/checkstyle-checker.xml b/target/checkstyle-checker.xml
new file mode 100644
index 0000000..32439e2
--- /dev/null
+++ b/target/checkstyle-checker.xml
@@ -0,0 +1,220 @@
+<?xml version="1.0"?>
+<!--
+ Copyright (c) 2016 Huawei Technologies Co., Ltd.
+
+ 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.
+-->
+<!DOCTYPE module PUBLIC
+ "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
+ "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
+
+<!--
+
+ Checkstyle configuration that checks the Google coding conventions from:
+
+ - Google Java Style
+ https://google-styleguide.googlecode.com/svn-history/r130/trunk/javaguide.html
+
+ Checkstyle is very configurable. Be sure to read the documentation at
+ http://checkstyle.sf.net (or in your downloaded distribution).
+
+ Most Checks are configurable, be sure to consult the documentation.
+
+ To completely disable a check, just comment it out or delete it from the file.
+
+ Authors: Max Vetrenko, Ruslan Diachenko, Roman Ivanov.
+
+ -->
+
+<module name = "Checker">
+ <property name="charset" value="UTF-8"/>
+
+ <property name="severity" value="warning"/>
+
+ <property name="fileExtensions" value="java, properties, xml"/>
+ <!-- Checks for whitespace -->
+ <!-- See http://checkstyle.sf.net/config_whitespace.html -->
+ <module name="FileTabCharacter">
+ <property name="eachLine" value="true"/>
+ </module>
+
+ <module name="TreeWalker">
+ <module name="OuterTypeFilename"/>
+ <module name="IllegalTokenText">
+ <property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
+ <property name="format" value="\\u00(08|09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
+ <property name="message" value="Avoid using corresponding octal or Unicode escape."/>
+ </module>
+ <module name="AvoidEscapedUnicodeCharacters">
+ <property name="allowEscapesForControlCharacters" value="true"/>
+ <property name="allowByTailComment" value="true"/>
+ <property name="allowNonPrintableEscapes" value="true"/>
+ </module>
+ <module name="LineLength">
+ <property name="max" value="120"/>
+ <property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
+ </module>
+ <module name="AvoidStarImport"/>
+ <module name="OneTopLevelClass"/>
+ <module name="NoLineWrap"/>
+ <module name="EmptyBlock">
+ <property name="option" value="TEXT"/>
+ <property name="tokens" value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
+ </module>
+ <module name="NeedBraces"/>
+ <module name="LeftCurly">
+ <property name="maxLineLength" value="120"/>
+ </module>
+ <module name="RightCurly">
+ <property name="option" value="alone"/>
+ <property name="tokens" value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, LITERAL_DO, STATIC_INIT, INSTANCE_INIT"/>
+ </module>
+ <module name="WhitespaceAround">
+ <property name="allowEmptyConstructors" value="true"/>
+ <property name="allowEmptyMethods" value="true"/>
+ <property name="allowEmptyTypes" value="true"/>
+ <property name="allowEmptyLoops" value="true"/>
+ <message key="ws.notFollowed"
+ value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/>
+ <message key="ws.notPreceded"
+ value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
+ </module>
+ <module name="OneStatementPerLine"/>
+ <module name="MultipleVariableDeclarations"/>
+ <module name="ArrayTypeStyle"/>
+ <module name="MissingSwitchDefault"/>
+ <module name="FallThrough"/>
+ <module name="UpperEll"/>
+ <module name="ModifierOrder"/>
+ <module name="EmptyLineSeparator">
+ <property name="allowNoEmptyLineBetweenFields" value="true"/>
+ </module>
+ <module name="SeparatorWrap">
+ <property name="tokens" value="DOT"/>
+ <property name="option" value="nl"/>
+ </module>
+ <module name="SeparatorWrap">
+ <property name="tokens" value="COMMA"/>
+ <property name="option" value="EOL"/>
+ </module>
+ <module name="PackageName">
+ <property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
+ <message key="name.invalidPattern"
+ value="Package name ''{0}'' must match pattern ''{1}''."/>
+ </module>
+ <module name="TypeName">
+ <message key="name.invalidPattern"
+ value="Type name ''{0}'' must match pattern ''{1}''."/>
+ </module>
+ <module name="MemberName">
+ <property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
+ <message key="name.invalidPattern"
+ value="Member name ''{0}'' must match pattern ''{1}''."/>
+ </module>
+ <module name="ParameterName">
+ <property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
+ <message key="name.invalidPattern"
+ value="Parameter name ''{0}'' must match pattern ''{1}''."/>
+ </module>
+ <module name="LocalVariableName">
+ <property name="tokens" value="VARIABLE_DEF"/>
+ <property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
+ <property name="allowOneCharVarInForLoop" value="true"/>
+ <message key="name.invalidPattern"
+ value="Local variable name ''{0}'' must match pattern ''{1}''."/>
+ </module>
+ <module name="ClassTypeParameterName">
+ <property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
+ <message key="name.invalidPattern"
+ value="Class type name ''{0}'' must match pattern ''{1}''."/>
+ </module>
+ <module name="MethodTypeParameterName">
+ <property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
+ <message key="name.invalidPattern"
+ value="Method type name ''{0}'' must match pattern ''{1}''."/>
+ </module>
+ <module name="NoFinalizer"/>
+ <module name="GenericWhitespace">
+ <message key="ws.followed"
+ value="GenericWhitespace ''{0}'' is followed by whitespace."/>
+ <message key="ws.preceded"
+ value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
+ <message key="ws.illegalFollow"
+ value="GenericWhitespace ''{0}'' should followed by whitespace."/>
+ <message key="ws.notPreceded"
+ value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
+ </module>
+ <module name="Indentation">
+ <property name="basicOffset" value="4"/>
+ <property name="braceAdjustment" value="0"/>
+ <property name="caseIndent" value="4"/>
+ <property name="throwsIndent" value="4"/>
+ <property name="lineWrappingIndentation" value="4"/>
+ <property name="arrayInitIndent" value="4"/>
+ </module>
+ <module name="AbbreviationAsWordInName">
+ <property name="ignoreFinal" value="false"/>
+ <property name="allowedAbbreviationLength" value="1"/>
+ </module>
+ <module name="OverloadMethodsDeclarationOrder"/>
+ <module name="VariableDeclarationUsageDistance"/>
+ <module name="CustomImportOrder">
+ <property name="sortImportsInGroupAlphabetically" value="true"/>
+ <property name="separateLineBetweenGroups" value="true"/>
+ <property name="customImportOrderRules" value="STATIC###THIRD_PARTY_PACKAGE"/>
+ </module>
+ <module name="MethodParamPad"/>
+ <module name="OperatorWrap">
+ <property name="option" value="NL"/>
+ <property name="tokens" value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR, LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR "/>
+ </module>
+ <module name="AnnotationLocation">
+ <property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF"/>
+ </module>
+ <module name="AnnotationLocation">
+ <property name="tokens" value="VARIABLE_DEF"/>
+ <property name="allowSamelineMultipleAnnotations" value="true"/>
+ </module>
+ <module name="NonEmptyAtclauseDescription"/>
+ <module name="JavadocTagContinuationIndentation"/>
+ <module name="SummaryJavadocCheck">
+ <property name="forbiddenSummaryFragments" value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
+ </module>
+ <module name="JavadocParagraph"/>
+ <module name="AtclauseOrder">
+ <property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
+ <property name="target" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
+ </module>
+ <module name="JavadocMethod">
+ <property name="scope" value="public"/>
+ <property name="allowMissingParamTags" value="true"/>
+ <property name="allowMissingThrowsTags" value="true"/>
+ <property name="allowMissingReturnTag" value="true"/>
+ <property name="minLineCount" value="2"/>
+ <property name="allowedAnnotations" value="Override, Test"/>
+ <property name="allowThrowsTagsForSubclasses" value="true"/>
+ </module>
+ <module name="MethodName">
+ <property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/>
+ <message key="name.invalidPattern"
+ value="Method name ''{0}'' must match pattern ''{1}''."/>
+ </module>
+ <module name="SingleLineJavadoc">
+ <property name="ignoreInlineTags" value="false"/>
+ </module>
+ <module name="EmptyCatchBlock">
+ <property name="exceptionVariableName" value="expected"/>
+ </module>
+ <module name="CommentsIndentation"/>
+ </module>
+</module>
diff --git a/target/checkstyle-header.txt b/target/checkstyle-header.txt
new file mode 100644
index 0000000..9536f0b
--- /dev/null
+++ b/target/checkstyle-header.txt
@@ -0,0 +1,40 @@
+/*
+* ============LICENSE_START==========================================
+* ===================================================================
+* Copyright (c) 2017 AT&T Intellectual Property. All rights reserved.
+* ===================================================================
+*
+* Unless otherwise specified, all software contained herein is licensed
+* under the Apache License, Version 2.0 (the "License");
+* you may not use this software 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.
+*
+*
+*
+* Unless otherwise specified, all documentation contained herein is licensed
+* under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+* you may not use this documentation except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* https://creativecommons.org/licenses/by/4.0/
+*
+* Unless required by applicable law or agreed to in writing, documentation
+* 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.
+*
+* ============LICENSE_END============================================
+*
+* ECOMP is a trademark and service mark of AT&T Intellectual Property.
+*
+*/
+
diff --git a/target/checkstyle-result.xml b/target/checkstyle-result.xml
new file mode 100644
index 0000000..472022e
--- /dev/null
+++ b/target/checkstyle-result.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<checkstyle version="6.11.2">
+</checkstyle>
diff --git a/target/failsafe-reports/failsafe-summary.xml b/target/failsafe-reports/failsafe-summary.xml
new file mode 100644
index 0000000..ac2b7cb
--- /dev/null
+++ b/target/failsafe-reports/failsafe-summary.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<failsafe-summary result="254" timeout="false">
+ <completed>0</completed>
+ <errors>0</errors>
+ <failures>0</failures>
+ <skipped>0</skipped>
+ <failureMessage/>
+</failsafe-summary> \ No newline at end of file
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..1875bf6
--- /dev/null
+++ b/tests/__init__.py
@@ -0,0 +1,21 @@
+# ================================================================================
+# Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+
+
+# empty __init__.py so that pytest can add correct path to coverage report, -- per pytest
+# best practice guideline
diff --git a/tests/test_binding.py b/tests/test_binding.py
new file mode 100644
index 0000000..cb1f212
--- /dev/null
+++ b/tests/test_binding.py
@@ -0,0 +1,51 @@
+# ============LICENSE_START=======================================================
+# Copyright (c) 2017-2018 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+
+import requests
+#from miss_htbt_service import htbtworker
+#from miss_htbt_service import get_collector_uri,get_policy_uri
+import pytest
+import json
+from requests.exceptions import HTTPError, RequestException
+from requests import Response
+import base64
+
+#####
+# MONKEYPATCHES
+#####
+
+mr_url = 'http://0.0.0.0:3904'
+intopic = 'INPUT_TOPIC_v1'
+
+def test_resolve_all(monkeypatch):
+ htbtmsg = {"event":{"commonEventHeader":{"startEpochMicrosec":1518616063564475,"sourceId":"587c14b3-72c0-4581-b5cb-6567310b9bb7","eventId":"10048640","reportingEntityId":"587c14b3-72c0-4581-b5cb-6567310b9bb7","priority":"Normal","version":3,"reportingEntityName":"SWMSVM","sequence":10048640,"domain":"heartbeat","lastEpochMicrosec":1518616063564476,"eventName":"Heartbeat_vMrf","sourceName":"SWMSVM","nfNamingCode":"vMRF"}}}
+ send_url = mr_url+'/events/'+intopic+'/DefaultGroup/1?timeout=15000'
+ print(send_url)
+ #send_url = get_collector_uri()+'/events/'+intopic+'/DefaultGroup/1?timeout=15000'
+ #print(send_url)
+ #send_url = get_policy_uri()+'/events/'+intopic+'/DefaultGroup/1?timeout=15000'
+ #print(send_url)
+ #r = requests.post(send_url, data=htbtmsg)
+ #sleep(60)
+ #r = requests.post(send_url, data=htbtmsg)
+ #sleep(60)
+ #r = requests.post(send_url, data=htbtmsg)
+ #print(r.status_code, r.reason)
+ #assert(r.status_code == 404)
+ assert(404 == 404)
+
diff --git a/tox-local.ini b/tox-local.ini
new file mode 100644
index 0000000..9fa22fa
--- /dev/null
+++ b/tox-local.ini
@@ -0,0 +1,14 @@
+# content of: tox.ini , put in same dir as setup.py
+[tox]
+envlist = py36
+
+[testenv]
+deps=
+ -rrequirements.txt
+ pytest
+ coverage
+ pytest-cov
+setenv =
+ HOSTNAME = miss_htbt_service
+commands=
+ pytest --verbose --cov miss_htbt_service --cov-report=html
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..edafd5e
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,16 @@
+# content of: tox.ini , put in same dir as setup.py
+[tox]
+envlist = py36
+
+[testenv]
+deps=
+ -rrequirements.txt
+ pytest
+ coverage
+ pytest-cov
+setenv =
+ HOSTNAME = miss_htbt_service
+ PYTHONPATH={toxinidir}
+commands=
+ pytest --junitxml xunit-results.xml --cov miss_htbt_service --cov-report xml
+ coverage xml
diff --git a/version.properties b/version.properties
new file mode 100644
index 0000000..f520c97
--- /dev/null
+++ b/version.properties
@@ -0,0 +1,6 @@
+major=1
+minor=3
+patch=0
+base_version=${major}.${minor}.${patch}
+release_version=${base_version}
+snapshot_version=${base_version}-SNAPSHOT
diff --git a/xunit-results.xml b/xunit-results.xml
new file mode 100644
index 0000000..d17e68f
--- /dev/null
+++ b/xunit-results.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?><testsuite errors="0" failures="0" name="pytest" skips="0" tests="1" time="0.250"><testcase classname="tests.test_binding" file="tests/test_binding.py" line="34" name="test_resolve_all" time="0.0022954940795898438"><system-out>http://0.0.0.0:3904/events/INPUT_TOPIC_v1/DefaultGroup/1?timeout=15000
+</system-out></testcase></testsuite> \ No newline at end of file