WIP: Initial implementation of Podder

Podder is a service which monitors consul registered services
in order to spin up their dependencies. Dependencies are
indicated as SERVICE_x_TAGS as a csv. Podder picks those
dependencies up and spins up specified containers in their own
network. For example, if a voltha_1 is instantiated
podder will spin up chameleon_1 and ofagent_1.

Change-Id: I0c1add8530c78fc761e39fe58cf24f14e96c0ba4
diff --git a/podder/consul_mgr.py b/podder/consul_mgr.py
new file mode 100644
index 0000000..c62ca58
--- /dev/null
+++ b/podder/consul_mgr.py
@@ -0,0 +1,90 @@
+import consul
+from structlog import get_logger
+from twisted.internet import reactor
+from twisted.internet.defer import inlineCallbacks, Deferred, returnValue
+
+from common.utils.dockerhelpers import create_container_network, start_container
+
+containers = {
+    'chameleon' : {
+                    'image' : 'opencord/chameleon',
+                    'command' : [ "/chameleon/main.py",
+                                    "-v",
+                                    "--consul=consul:8500",
+                                    "--fluentd=fluentd:24224",
+                                    "--rest-port=8881",
+                                    "--grpc-endpoint=@voltha-grpc",
+                                    "--instance-id-is-container-name",
+                                    "-v"],
+                    'ports' : [ 8881 ],
+                    'depends_on' : [ "consul", "voltha" ],
+                    'links' : [ "consul", "fluentd" ],
+                    'environment' : ["SERVICE_8881_NAME=chamleon-rest"],
+                    'volumes' : '/var/run/docker.sock:/tmp/docker.sock'
+                  }
+}
+
+class ConsulManager(object):
+
+    log = get_logger()
+
+    def __init__(self, arg):
+        self.log.info('Initializing consul manager')
+        self.running = False
+        self.index = 0
+        (host, port) = arg.split(':')
+        self.conn = consul.Consul(host=host, port=port)
+
+    @inlineCallbacks
+    def run(self):
+        if self.running:
+            return
+        self.running = True
+
+        self.log.info('Running consul manager')
+
+        reactor.callLater(0, self.provision_voltha_instances())
+
+        reactor.addSystemEventTrigger('before', 'shutdown', self.shutdown)
+        returnValue(self)
+
+    @inlineCallbacks
+    def shutdown(self):
+        self.log.info('Shutting down consul manager')
+        self.running = False
+
+    @inlineCallbacks
+    def provision_voltha_instances(self):
+        while True:
+            if not self.running:
+                return
+            # maintain index such that callbacks only happen is something has changed
+            # timeout is default to 5m
+            (self.index, data) = self.conn.catalog.service(service='voltha-grpc',
+                                                            index=self.index)
+            self.start_containers(data)
+
+    def start_containers(self, data):
+        for item in data:
+            serviceId = item['ServiceID'].split(':')[1].split('_')[2]
+            serviceTags = item['ServiceTags']
+            self.log.info('voltha instance %s, with tags %s' % (serviceId, serviceTags))
+            for tag in serviceTags:
+                if tag in containers:
+                    netcfg = self.create_network(serviceId, tag)
+                    self.create_container(serviceId, tag, netcfg)
+
+
+    def create_network(self, id, tag):
+        return create_container_network('podder_%s_%s' % (tag, id),
+                                        containers[tag]['links'])
+
+    def create_container(self, id, tag, netcfg):
+        args = {}
+        args['image'] = containers['image']
+        args['networking_config'] = netcfg
+        args['command'] = containers['command']
+        args['ports'] = containers['ports']
+        args['environment'] = containers['environment']
+        args['volumes'] = containers['volumes']
+        start_container(args)
\ No newline at end of file