move ceilometer service over from xos repo

Change-Id: I9402876545cf552675cd0a836e02e2c72fea5f6b
diff --git a/xos/synchronizer/steps/sync_monitoringchannel.py b/xos/synchronizer/steps/sync_monitoringchannel.py
new file mode 100644
index 0000000..2c0ba10
--- /dev/null
+++ b/xos/synchronizer/steps/sync_monitoringchannel.py
@@ -0,0 +1,84 @@
+import hashlib
+import os
+import socket
+import sys
+import base64
+import time
+from django.db.models import F, Q
+from xos.config import Config
+from synchronizers.base.syncstep import SyncStep
+from synchronizers.base.ansible import run_template_ssh
+from synchronizers.base.SyncInstanceUsingAnsible import SyncInstanceUsingAnsible
+from core.models import Service, Slice
+from services.ceilometer.models import CeilometerService, MonitoringChannel
+from xos.logger import Logger, logging
+
+parentdir = os.path.join(os.path.dirname(__file__),"..")
+sys.path.insert(0,parentdir)
+
+logger = Logger(level=logging.INFO)
+
+class SyncMonitoringChannel(SyncInstanceUsingAnsible):
+    provides=[MonitoringChannel]
+    observes=MonitoringChannel
+    requested_interval=0
+    template_name = "sync_monitoringchannel.yaml"
+    service_key_name = "/opt/xos/synchronizers/monitoring_channel/monitoring_channel_private_key"
+
+    def __init__(self, *args, **kwargs):
+        super(SyncMonitoringChannel, self).__init__(*args, **kwargs)
+
+    def fetch_pending(self, deleted):
+        if (not deleted):
+            objs = MonitoringChannel.get_tenant_objects().filter(Q(enacted__lt=F('updated')) | Q(enacted=None),Q(lazy_blocked=False))
+        else:
+            objs = MonitoringChannel.get_deleted_tenant_objects()
+
+        return objs
+
+    def get_extra_attributes(self, o):
+        # This is a place to include extra attributes. In the case of Monitoring Channel, we need to know
+        #   1) Allowed tenant ids
+        #   2) Ceilometer API service endpoint URL if running externally
+        #   3) Credentials to access Ceilometer API service
+
+        ceilometer_services = CeilometerService.get_service_objects().filter(id=o.provider_service.id)
+        if not ceilometer_services:
+            raise "No associated Ceilometer service"
+        ceilometer_service = ceilometer_services[0]
+        ceilometer_pub_sub_url = ceilometer_service.ceilometer_pub_sub_url
+        if not ceilometer_pub_sub_url:
+            ceilometer_pub_sub_url = ''
+        instance = self.get_instance(o)
+
+        try:
+            full_setup = Config().observer_full_setup
+        except:
+            full_setup = True
+
+        fields = {"unique_id": o.id,
+                  "allowed_tenant_ids": o.tenant_list,
+                  "auth_url":instance.controller.auth_url,
+                  "admin_user":instance.controller.admin_user,
+                  "admin_password":instance.controller.admin_password,
+                  "admin_tenant":instance.controller.admin_tenant,
+                  "ceilometer_pub_sub_url": ceilometer_pub_sub_url,
+                  "full_setup": full_setup}
+
+        return fields
+
+    def run_playbook(self, o, fields):
+        #ansible_hash = hashlib.md5(repr(sorted(fields.items()))).hexdigest()
+        #quick_update = (o.last_ansible_hash == ansible_hash)
+
+        #if quick_update:
+        #    logger.info("quick_update triggered; skipping ansible recipe")
+        #else:
+        super(SyncMonitoringChannel, self).run_playbook(o, fields)
+
+        #o.last_ansible_hash = ansible_hash
+
+    def map_delete_inputs(self, o):
+        fields = {"unique_id": o.id,
+                  "delete": True}
+        return fields
diff --git a/xos/synchronizer/steps/sync_monitoringchannel.yaml b/xos/synchronizer/steps/sync_monitoringchannel.yaml
new file mode 100644
index 0000000..ca72c5f
--- /dev/null
+++ b/xos/synchronizer/steps/sync_monitoringchannel.yaml
@@ -0,0 +1,145 @@
+---
+- hosts: {{ instance_name }}
+  gather_facts: False
+  connection: ssh
+  user: ubuntu
+  sudo: yes
+  vars:
+      unique_id: {{ unique_id }}
+      auth_url: {{ auth_url }}
+      admin_user: {{ admin_user }}
+      admin_password: {{ admin_password }}
+      admin_tenant: {{ admin_tenant }}
+      shared_lan_ip: {{ private_ip }}
+      shared_lan_mac: {{ private_mac }}
+      headnode_flat_lan_ip: {{ rabbit_host }}
+      ceilometer_client_acess_ip: {{ ceilometer_ip }}
+      ceilometer_client_acess_mac: {{ ceilometer_mac }}
+      ceilometer_host_port: {{ ceilometer_port }}
+      ceilometer_pub_sub_url: {{ ceilometer_pub_sub_url }}
+      allowed_tenant_ids:
+        {% for allowed_tenant_id in allowed_tenant_ids %}
+        - {{ allowed_tenant_id }}
+        {% endfor %}
+
+  tasks:
+{% if delete %}
+  - name: Remove tenant
+# FIXME: Adding dummy template action to avoid "action attribute missing in task" error
+    template: src=/opt/xos/synchronizers/monitoring_channel/templates/ceilometer_proxy_config.j2 dest=/usr/local/share/monitoring-channel-{{ unique_id }}_ceilometer_proxy_config mode=0777
+    notify:
+     - stop monitoring-channel
+     - remove container
+{% else %}
+{% if full_setup %}
+#  - name: Docker repository
+#    copy: src=/opt/xos/synchronizers/monitoring_channel/files/docker.list
+#      dest=/etc/apt/sources.list.d/docker.list
+#
+#  - name: Import the repository key
+#    apt_key: keyserver=keyserver.ubuntu.com id=36A1D7869245C8950F966E92D8576A8BA88D21E9
+#
+#  - name: install Docker
+#    apt: name=lxc-docker state=present update_cache=yes
+#
+#  - name: install python-setuptools
+#    apt: name=python-setuptools state=present
+#
+#  - name: install pip
+#    easy_install: name=pip
+#
+#  - name: install docker-py
+#    pip: name=docker-py version=0.5.3
+#
+#  - name: install Pipework
+#    get_url: url=https://raw.githubusercontent.com/jpetazzo/pipework/master/pipework
+#       dest=/usr/local/bin/pipework
+#       mode=0755
+#
+#  - name: Disable resolvconf service
+#    shell: service resolvconf stop
+#    shell: echo manual > /etc/init/resolvconf.override
+#    shell: rm -f /etc/resolv.conf
+#
+#  - name: Install resolv.conf
+#    copy: src=/opt/xos/synchronizers/monitoring_channel/files/vm-resolv.conf
+#      dest=/etc/resolv.conf
+{% endif %}
+
+# FIXME: Temporary workaround to delete the monitoring-channel_ceilometer_proxy_config file always 
+# to trigger ansible notify handlers in the following task. 
+# Due to some issue, ansible "changed" flag is set to false even though there is a change of 
+# ceilometer configuration file, because of which the configuration change is not reflecting in 
+# ceilometer containers 
+#  - file: path=/usr/local/share/monitoring-channel-{{ unique_id }}_ceilometer_proxy_config state=absent
+
+  - name: ceilometer proxy config
+    template: src=/opt/xos/synchronizers/monitoring_channel/templates/ceilometer_proxy_config.j2 dest=/usr/local/share/monitoring-channel-{{ unique_id }}_ceilometer_proxy_config mode=0777
+    notify:
+     - copy ceilo-config-file
+     - restart monitoring-channel container
+#     - stop monitoring-channel
+#     - remove container
+#     - start monitoring-channel
+
+  - name: Monitoring channel upstart
+    template: src=/opt/xos/synchronizers/monitoring_channel/templates/monitoring-channel.conf.j2 dest=/etc/init/monitoring-channel-{{ unique_id }}.conf
+
+  - name: Monitoring channel startup script
+    template: src=/opt/xos/synchronizers/monitoring_channel/templates/start-monitoring-channel.sh.j2 dest=/usr/local/sbin/start-monitoring-channel-{{ unique_id }}.sh mode=0755
+    notify:
+#    - restart monitoring-channel
+     - stop monitoring-channel
+     - remove container
+     - start monitoring-channel
+
+#  - name: Start monitoring-channel container
+#    docker:
+#      docker_api_version: "1.18"
+#      name: monitoring-channel-{{ unique_id }}
+#      # was: reloaded
+#      state: running
+#      image: srikanthvavila/monitoring-channel
+#      expose:
+#      - 8000
+#      ports:
+#      - "{{ ceilometer_port }}:8000"
+#      volumes:
+#      - /usr/local/share/monitoring-channel-{{ unique_id }}_ceilometer_proxy_config:/usr/local/share/ceilometer_proxy_config
+#
+#  - name: Get Docker IP
+#    #TODO: copy dockerip.sh to monitoring service synchronizer
+#    script: /opt/xos/synchronizers/onos/scripts/dockerip.sh monitoring-channel-{{ unique_id }}
+#    register: dockerip
+#
+#  - name: Wait for Monitoring channel to come up
+#    wait_for:
+#      host={{ '{{' }} dockerip.stdout {{ '}}' }}
+#      port={{ '{{' }} item {{ '}}' }}
+#      state=present
+#    with_items:
+#    - {{ ceilometer_port }}
+# These are samples, not necessary for correct function of demo
+
+  - name: Make sure Monitoring channel service is running
+    service: name=monitoring-channel-{{ unique_id }} state=started
+{% endif %}
+
+  handlers:
+  - name: copy ceilo-config-file
+    shell: docker cp /usr/local/share/monitoring-channel-{{ unique_id }}_ceilometer_proxy_config monitoring-channel-{{ unique_id }}:/usr/local/share/ceilometer_proxy_config
+
+  - name: restart monitoring-channel container
+    shell: docker restart monitoring-channel-{{ unique_id }}
+
+  - name: restart monitoring-channel
+    shell: service monitoring-channel-{{ unique_id }} stop; sleep 1; service monitoring-channel-{{ unique_id }} start
+
+  - name: stop monitoring-channel
+    service: name=monitoring-channel-{{ unique_id }} state=stopped
+
+  - name: remove container
+    docker: name=monitoring-channel-{{ unique_id }} state=absent image=monitoring-channel
+
+  - name: start monitoring-channel
+    service: name=monitoring-channel-{{ unique_id }} state=started
diff --git a/xos/synchronizer/steps/sync_sflowservice.py b/xos/synchronizer/steps/sync_sflowservice.py
new file mode 100644
index 0000000..154c5ab
--- /dev/null
+++ b/xos/synchronizer/steps/sync_sflowservice.py
@@ -0,0 +1,74 @@
+import hashlib
+import os
+import socket
+import sys
+import base64
+import time
+from django.db.models import F, Q
+from xos.config import Config
+from synchronizers.base.syncstep import SyncStep
+from synchronizers.base.ansible import run_template_ssh
+from synchronizers.base.SyncInstanceUsingAnsible import SyncInstanceUsingAnsible
+from core.models import Service, Slice
+from services.ceilometer.models import SFlowService
+from xos.logger import Logger, logging
+
+# hpclibrary will be in steps/..
+parentdir = os.path.join(os.path.dirname(__file__),"..")
+sys.path.insert(0,parentdir)
+
+logger = Logger(level=logging.INFO)
+
+class SyncSFlowService(SyncInstanceUsingAnsible):
+    provides=[SFlowService]
+    observes=SFlowService
+    requested_interval=0
+    template_name = "sync_sflowservice.yaml"
+    service_key_name = "/opt/xos/synchronizers/monitoring_channel/monitoring_channel_private_key"
+
+    def __init__(self, *args, **kwargs):
+        super(SyncSFlowService, self).__init__(*args, **kwargs)
+
+    def fetch_pending(self, deleted):
+        if (not deleted):
+            objs = SFlowService.get_service_objects().filter(Q(enacted__lt=F('updated')) | Q(enacted=None),Q(lazy_blocked=False))
+        else:
+            objs = SFlowService.get_deleted_service_objects()
+
+        return objs
+
+    def get_instance(self, o):
+        # We assume the ONOS service owns a slice, so pick one of the instances
+        # inside that slice to sync to.
+
+        serv = o
+
+        if serv.slices.exists():
+            slice = serv.slices.all()[0]
+            if slice.instances.exists():
+                return slice.instances.all()[0]
+
+        return None
+
+    def get_extra_attributes(self, o):
+        fields={}
+        fields["instance_hostname"] = self.get_instance(o).instance_name.replace("_","-")
+        fields["sflow_port"] = o.sflow_port
+        fields["sflow_api_port"] = o.sflow_api_port
+        fields["sflow_container"] = "sflowpubsub"
+        return fields
+
+    def sync_fields(self, o, fields):
+        # the super causes the playbook to be run
+        super(SyncSFlowService, self).sync_fields(o, fields)
+
+    def run_playbook(self, o, fields):
+        instance = self.get_instance(o)
+        if (instance.isolation=="container"):
+            # If the instance is already a container, then we don't need to
+            # install ONOS.
+            return
+        super(SyncSFlowService, self).run_playbook(o, fields)
+
+    def delete_record(self, m):
+        pass
diff --git a/xos/synchronizer/steps/sync_sflowservice.yaml b/xos/synchronizer/steps/sync_sflowservice.yaml
new file mode 100644
index 0000000..8d853a2
--- /dev/null
+++ b/xos/synchronizer/steps/sync_sflowservice.yaml
@@ -0,0 +1,74 @@
+---
+- hosts: {{ instance_name }}
+  gather_facts: False
+  connection: ssh
+  user: ubuntu
+  sudo: yes
+  vars:
+     sflow_port: {{ sflow_port }}
+     sflow_api_port: {{ sflow_api_port }}
+
+  tasks:
+
+  - name: Fix /etc/hosts
+    lineinfile:
+      dest=/etc/hosts
+      regexp="127.0.0.1 localhost"
+      line="127.0.0.1 localhost {{ instance_hostname }}"
+
+  - name: Add repo key
+    apt_key:
+      keyserver=hkp://pgp.mit.edu:80
+      id=58118E89F3A912897C070ADBF76221572C52609D
+
+  - name: Install Docker repo
+    apt_repository:
+      repo="deb https://apt.dockerproject.org/repo ubuntu-trusty main"
+      state=present
+
+  - name: Install Docker
+    apt:
+      name={{ '{{' }} item {{ '}}' }}
+      state=latest
+      update_cache=yes
+    with_items:
+    - docker-engine
+    - python-pip
+    - python-httplib2
+
+  - name: Install docker-py
+    pip:
+      name=docker-py
+      state=latest
+
+  - name: sflow pub-sub config
+    template: src=/opt/xos/synchronizers/monitoring_channel/templates/sflow_pub_sub/sflow_pub_sub_config.j2 dest=/usr/local/share/sflow_pub_sub.conf mode=0777
+
+  - name: Start SFLOW pub-sub container
+    docker:
+      docker_api_version: "1.18"
+      name: {{ sflow_container }}
+      # was: reloaded
+      state: running
+      image: srikanthvavila/sflowpubsub
+      expose:
+      - {{ sflow_api_port }}
+      - {{ sflow_port }}/udp
+      ports:
+      - "{{ sflow_port }}:{{ sflow_port }}/udp"
+      - "{{ sflow_api_port }}:{{ sflow_api_port }}"
+      volumes:
+      - /usr/local/share/sflow_pub_sub.conf:/usr/local/share/sflow_pub_sub/sflow_pub_sub.conf
+
+  - name: Get Docker IP
+    #TODO: copy dockerip.sh to monitoring service synchronizer
+    script: /opt/xos/synchronizers/onos/scripts/dockerip.sh {{ sflow_container }}
+    register: dockerip
+
+  - name: Wait for SFlow service to come up
+    wait_for:
+      host={{ '{{' }} dockerip.stdout {{ '}}' }}
+      port={{ '{{' }} item {{ '}}' }}
+      state=present
+    with_items:
+    - {{ sflow_api_port }}
diff --git a/xos/synchronizer/steps/sync_sflowtenant.py b/xos/synchronizer/steps/sync_sflowtenant.py
new file mode 100644
index 0000000..a15fa54
--- /dev/null
+++ b/xos/synchronizer/steps/sync_sflowtenant.py
@@ -0,0 +1,82 @@
+import hashlib
+import os
+import socket
+import socket
+import sys
+import base64
+import time
+import re
+import json
+from django.db.models import F, Q
+from xos.config import Config
+from synchronizers.base.syncstep import SyncStep
+from synchronizers.base.ansible import run_template_ssh
+from synchronizers.base.SyncInstanceUsingAnsible import SyncInstanceUsingAnsible
+from core.models import Service, Slice, ControllerSlice, ControllerUser
+from services.ceilometer.models import SFlowService, SFlowTenant
+from xos.logger import Logger, logging
+
+# hpclibrary will be in steps/..
+parentdir = os.path.join(os.path.dirname(__file__),"..")
+sys.path.insert(0,parentdir)
+
+logger = Logger(level=logging.INFO)
+
+class SyncSFlowTenant(SyncInstanceUsingAnsible):
+    provides=[SFlowTenant]
+    observes=SFlowTenant
+    requested_interval=0
+    template_name = "sync_sflowtenant.yaml"
+    service_key_name = "/opt/xos/synchronizers/monitoring_channel/monitoring_channel_private_key"
+
+    def __init__(self, *args, **kwargs):
+        super(SyncSFlowTenant, self).__init__(*args, **kwargs)
+
+    def fetch_pending(self, deleted):
+        if (not deleted):
+            objs = SFlowTenant.get_tenant_objects().filter(Q(enacted__lt=F('updated')) | Q(enacted=None),Q(lazy_blocked=False))
+        else:
+            objs = SFlowTenant.get_deleted_tenant_objects()
+
+        return objs
+
+    def get_sflow_service(self, o):
+        sflows = SFlowService.get_service_objects().filter(id=o.provider_service.id)
+        if not sflows:
+           raise "No associated SFlow service"
+
+        return sflows[0]
+
+    def get_instance(self, o):
+        # We assume the SFlow service owns a slice, so pick one of the instances
+        # inside that slice to sync to.
+
+        serv = self.get_sflow_service(o)
+
+        if serv.slices.exists():
+            slice = serv.slices.all()[0]
+            if slice.instances.exists():
+                return slice.instances.all()[0]
+
+        return None
+
+    def get_extra_attributes(self, o):
+        instance = self.get_instance(o)
+
+        fields={}
+        fields["sflow_api_base_url"] = self.get_sflow_service(o).sflow_api_url
+        fields["sflow_api_port"] = self.get_sflow_service(o).sflow_api_port
+        fields["listening_endpoint"] = o.listening_endpoint
+        fields["sflow_container"] = "sflowpubsub"
+
+        return fields
+
+    def sync_fields(self, o, fields):
+        # the super causes the playbook to be run
+        super(SyncSFlowTenant, self).sync_fields(o, fields)
+
+    def run_playbook(self, o, fields):
+        super(SyncSFlowTenant, self).run_playbook(o, fields)
+
+    def delete_record(self, m):
+        pass
diff --git a/xos/synchronizer/steps/sync_sflowtenant.yaml b/xos/synchronizer/steps/sync_sflowtenant.yaml
new file mode 100644
index 0000000..701ce5c
--- /dev/null
+++ b/xos/synchronizer/steps/sync_sflowtenant.yaml
@@ -0,0 +1,28 @@
+---
+- hosts: {{ instance_name }}
+  gather_facts: False
+  connection: ssh
+  user: {{ username }}
+  sudo: yes
+
+  tasks:
+
+  - name: Get Docker IP
+    #TODO: copy dockerip.sh to monitoring service synchronizer
+    script: /opt/xos/synchronizers/onos/scripts/dockerip.sh {{ sflow_container }}
+    register: sflowserviceaddr
+
+  - name: Wait for SFlow service to come up
+    wait_for:
+      host={{ '{{' }} sflowserviceaddr.stdout {{ '}}' }}
+      port={{ '{{' }} item {{ '}}' }}
+      state=present
+    with_items:
+    - {{ sflow_api_port }}
+
+  - name: Invoke SFlow service REST API to subscribe
+    uri:
+      url: http://{{ '{{' }} sflowserviceaddr.stdout {{ '}}' }}:{{ sflow_api_port }}/subscribe
+      body: "{{ listening_endpoint }}"
+      body_format: raw
+      method: POST